JAVA反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。  
 

Java反射机制主要提供了以下功能: (伟大的作用)

      1 在运行时判断任意一个对象所属的类;

      2 在运行时构造任意一个类的对象;

      3 在运行时判断任意一个类所具有的成员变量和方法;

      4 在运行时调用任意一个对象的方法;

      5  生成动态代理。  

 Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。

基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。 
      每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。


1   如何得到Class的对象呢?有三种方法可以的获取:

     1、调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。 例如:
    MyObject x;
    Class c1 = x.getClass();
     2、使用Class类的中静态forName()方法获得与字符串对应的Class对象。 例如: 
    Class c2=Class.forName("MyObject"),Employee必须是接口或者类的名字。
     3、获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配的类对象。 例如
    Class cl1 = Manager.class;
    Class cl2 = int.class;
    Class cl3 = Double[].class;

(一句话):对象用.getClass,类用.class,


2  Class类的常用方法

    1 、getName() 
    一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
    2、newInstance()
    Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:
    x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。
    3、getClassLoader() 
    返回该类的类加载器。
    4、getComponentType() 
    返回表示数组组件类型的 Class。
    5、getSuperclass() 
    返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
    6、isArray() 
    判定此 Class 对象是否表示一个数组类

Constructor getConstructor(Class[] params) -- 

获得使用特殊的参数类型的公共构造函数,

 

Constructor[] getConstructors() -- 

获得类的所有公共构造函数

 

Constructor 

getDeclaredConstructor(Class[] 

params) 

-- 

获得使用特定参数类型的构造函数

(

接入级别无关

Constructor[] getDeclaredConstructors() -- 

获得类的所有构造函数

(

与接入级别无关

 

 

获得字段信息的

Class 

反射调用不同于那些用于接入构造函数的调用,

在参数类型数组中使

用了字段名:

Field getField(String name) -- 

获得命名的公共字段

 

Field[] getFields() -- 

获得类的所有公共字段

 

Field getDeclaredField(String name) -- 

获得类声明的命名的字段

 

Field[] getDeclaredFields() -- 

获得类声明的所有字段

 

 

 

用于获得方法信息函数:

 

 

Method getMethod(String name, Class[] params) -- 

使用特定的参数类型,获得命名的公共方

 

Method[] getMethods() -- 

获得类的所有公共方法

 

Method getDeclaredMethod(String name, Class[] params) -- 

使用特写的参数类型,

获得类声明

3.4父类

通过Class对象可以获取类的父类,如下:

Class  aClass = MyObject.class;
Class superclass = aClass.getSuperclass();

父类的Class对象和其它Class对象一样是一个Class对象,可以继续使用反射.

3.5实现的接口

通过给定的类可以获取这个类所实现的接口列表,如下:

Class aClass = MyObject.class;
Class[] interfaces = aClass.getInterfaces();

一个类可以实现多个接口。因此返回一个Class数组。在Java反射机制中,接口也由Class对象表示。

注意:只有给定类声明实现的接口才会返回。例如,如果类A的父类B实现了一个接口C,但类A并没有声明它也实现了C,那么C不会被返回到数组中。即使类A实际上实现了接口C,因为它的父类B实现了C。

为了得到一个给定的类实现接口的完整列表,需要递归访问类和其超类。

3.6构造函数

使用Class对象可以获取类的构造函数,如下:

     Class aClass = MyObject.class;
Constructor[] constructors = aClass.getConstructors();

关于构造函数更详细信息参见 构造函数这节。

3.7方法

使用Class对象可以获取类的方法,如下:

     Class aClass = MyObject.class;
Method[] methods = aClass.getMethods();

关于方法更详细信息参见方法这节.

3.8字段

使用Class对象可以获取类的字段(成员变量),如下:

      Class aClass = MyObject.class;
Field[] fields = aClass.getFields();

关于字段更详细信息参见 字段这节.

3.9注解

使用Class对象可以获取类的注解,如下:

      Class aClass = MyObject.class;
Annotation[] annotations = aClass.getAnnotations();

关于注解更详细信息参见注解这节.

4. 构造函数

使用Java反射可以在运行时检查类的构造函数并实例化对象。这是通过Java类java.lang.reflect.Constructor来实现的。以下是Java Construcor对象的更多细节:

(1) 获取Constructor对象

(2) 构造函数参数

(3) 使用Constructor对象实例化对象

4.1获取Constructor对象

 Constructor类是从Class对象获取的,举例:

Class aClass = MyObject.class;
Constructor[] constructors = aClass.getConstructors();

Constructor数组为每一个在类中声明的public构造函数保存一个Constructor实例

如果知道要访问的构造函数确切的参数类型,可以不获取构造函数数组。本示例将返回给定类中接受一个字符串作为参数的公共构造函数。

Class aClass = MyObject.class;//MyObject有一个参数为字符串的公共构造函数
Constructor constructor = aClass.getConstructor(new Class[]{String.class});

如果没有匹配给定的构造函数参数,在这个例子当中是String.class,会抛出 NoSuchMethodException 异常.

4.2构造函数参数

可以知道给定的构造函数接受什么参数,如下:

Class aClass = MyObject.class;//MyObject有一个参数为字符串的公共构造函数
Constructor constructor = aClass.getConstructor(new Class[]{String.class});
Class[] parameterTypes = constructor.getParameterTypes();

4.3使用Constructor对象实例化对象

可以像这样实例化对象:

//获取使用字符串作为参数的constructor
Constructor constructor = MyObject.class.getConstructor(String.class);
MyObject myObject = (MyObject)constructor.newInstance("constructor-arg1");

Constructor.newInstance() 方法使用可变长度的参数,但是在调用构造函数时必须为每一个参数提供一个准确的参量.在这个例子中构造函数接受一个字符串作为参数,所以必须要提供一个字符串。

5. 字段

使用Java反射你可以在运行时检查类的字段(成员变量)并 get / set它们.这是通过Java类java.lang.reflect.Field来完成的.以下是JavaField对象更多细节:

(1) 获取Field 对象

(2) 字段名称

(3) 字段类型

(4) 获取和设置字段

5.1获取Field 对象

     Field类是从Class对象获取的.举例:

Class aClass = MyObject.class;
Field[] methods = aClass.getFields();

Field数组为类中声明的每一个public字段保存一个Field 实例。

如果知道要访问的字段名称,可以这样获取它:

Class aClass = MyObject.class
Field field = aClass.getField("someField");

根据下面 MyObject 声明的someField字段,以上的例子将返回Field实例:

public class MyObject{
       public String someField = null;
}

如果不存在getField()方法中所给参数名字对应的字段,会抛出NoSuchFieldException异常.

5.2字段名称

一旦获得一个 Field实例,可以使用Field.getName()方法获取它的字段名字,如下:

Field field = ... //获取 field 对象
String fieldName = field.getName();

5.3字段类型

你可以使用Field.getType()方法确定一个字段的类型(String,int等):

Field field = aClass.getField("someField");
Object fieldType = field.getType();

5.4获取和设置字段值

一旦获得一个Field引用,可以使用Field.get() 和 Field.set()方法获取和设置它的值,如下:

Class aClass = MyObject.class
Field field = aClass.getField("someField");
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objetInstance, value);

传递给get和set方法的对象实例参数应该是拥有该字段的类的一个实例。在上述的例子中使用了MyObject的一个实例,因为someField是MyObject类的一个实例成员。静态字段(public static)给get和set方法传递null作为参数,而不是以上传递的objectInstance参数。

6. 方法

使用Java反射你可以在运行时检查类的方法并调用它们.这是通过Java类java.lang.reflect.Method来实现的.本章将会更详细的介绍 Java Method对象.下面是本章所涵盖的主题:

(1) 获取 Method对象

(2) 方法的参数和返回值类型

(3) 使用Method对象调用方法

6.1获取Method对象

Method类是从 Class 对象中获取的.举例:

Class aClass = MyObject.class;
Method[] methods = aClass.getMethods();

 Method数组将为类中声明的每一个public的方法保存一个Method实例.

如果你知道要访问方法的确切的参数类型,可以不必获取方法数组。本示例返回给定类中接受一个字符串作为参数的公共方法”doSomething”。

Class  aClass = MyObject.class;
Method method = aClass.getMethod("doSomething", new Class[]{String.class});

如果没有方法匹配所给的方法名和参数,在这个例子中是String.class,将抛出NoSuchMethodException异常.

如果你想访问的方法没有参数,传递 null作为参数类型数组,如下:

Class  aClass = MyObject.class;
Method method = aClass.getMethod("doSomething", null);

6.2方法的参数和返回值类型

使用Method对象可以获取方法的参数,如下:

Method method = ... //获取 method – 如上
Class[] parameterTypes = method.getParameterTypes();

亦可以获取方法的返回值类型,如下:

Method method = ... // obtain method - see above
Class returnType = method.getReturnType();

6.3使用Method对象调用方法

可以像这样调用方法:

//get method that takes a String as argument
Method method = MyObject.class.getMethod("doSomething", String.class);
Object returnValue = method.invoke(null, "parameter-value1");

空参数是你想要调用该方法的对象。如果该方法是静态的,使用null,而不是一个对象实例。在这个例子中,如果doSomething(String.class)不是静态的,你需要提供有效的MyObject实例而不是null作为参数;
    Method.invoke(Object target, Object ...parameters)方法接受可变长度的参数,但是你在调用时必须为每一个参数提供一个准确的参量。在这个例子中,方法以字符串作为参数的,所以必须提供一个字符串。





//来自http://blog.youkuaiyun.com/jackiehff/article/details/8509075博客:

  此博客写的非常好!

我只是载录一下对自己有用的!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值