java 反射 总结

 

 

一、 Class :注意和关键字 class 不是一回事。

 

 

Class java.lang 包下的;没有公开的构造方法;不允许直接创建对象;只能通过具体类获得;用来描述其他的一个类型

 

Class 类的实例表示正在运行的 Java 应用程序中的类和接口

 

获得一个 Class 对象的方式:

1) Class c1=Class.forName("( 类名 =)Student");

2) Class c2=Student.class;

3) Student s1=new Student("");

Class c3=s1.getClass();

不管通过哪种方式获得的,都是同一个对象;一种类型和一个 Class 对象一一对应;看如下程序 , OuterA test 包下的一个普通类。

 

Class c1 = Class.forName("test.OuterA");

System.out.println(c1);

Class c2 = OuterA.class;

System.out.println(c2==c1);// 结果为: true

OuterA out = new OuterA();

Class c3 = out.getClass();

System.out.println(c3==c1);// 结果为: true

 

Class 类的方法介绍:

 

1.int getModifiers() // 得到此类的修饰符的 int 值;

 

Modifiers.toString(int);// 返回的就是那个修饰符名称; 例如:

 

String modifier = Modifier.toString(c1.getModifiers());

System.out.println(modifier);

 

2. Class[] getInterfaces() // 如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。数组中接口对象顺序与此对象所表示的类的声明的 implements 子句中接口名顺序一致。 例如 ExFrame 如下:

 

public class ExFrame extends JFrame implements ActionListener,Serializable{

public int intAtt;

private double result;

public void actionPerformed(ActionEvent arg0) {

}

}

 

main 方法里:

 

Class cc = ExFrame.class;

Class[] interfaces = cc.getInterfaces();

for(int i=0; i<interfaces.length; i++){

System.out.println(interfaces[i]);

}

 

结果如下:

 

interface java.awt.event.ActionListener

interface java.io.Serializable

 

3. Field[] getDeclaredFields();// 得到所有属性;

Field[] getFields() // 得到所有公开属性

 

Field[] fields = cc.getDeclaredFields();

 

for(int i=0; i<fields.length; i++){

System.out.println(fields[i]);

}

 

结果如下:

 

public int test.ExFrame.intAtt

private double test.ExFrame.result

 

 

4. Constructor<T> getDeclaredConstructor(Class... parameterTypes)

... : 可变长参数, 0 ~ 多个,来决定得到哪个构造方法;

 

5. Method getDeclaredMethod(String name, Class... parameterTypes)

Method[] getDeclaredMethods()

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类

或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

 

6. Class<?>[] getParameterTypes() 得到参数表;

Class<?>[] getExceptionTypes() 得到异常类型;

 

二、反射机制的理解

 

反射的真正目的是让 JVM 动态加载类,并且来调用方法和修改属性;

 

并不是通过程序设置的,而是通过参数来加载类;类名不不出现在源码中;

 

一般是在源代码中:创建一个对象时,才加载这个类;

 

反射 不是给应用程序开发人员用的,是给框架开发人员用的;

 

T newInstance() ;生成新的对象;

 

Method getMethod(String name, Class... parameterTypes)

 

三、属性:类 Field

 

Field 类封装了一个类的属性的所有描述 包括 修饰符、属性类型、属性值、属性的注释,提供了一系列 get/set 方法来获得修改属性的值

 

Class 中有个方法: Field getField(String name) ; 可以得到 Field

 

Field 中常用的方法:

 

Object get(Object obj)

void set(Object obj, Object value)

 

Field f=c.getField("name"); // 得到 obj 对象的 name 属性的值;

f.get(obj); \\ 等价于 obj.name;

f.set(obj1,"hehe");// obj1 f 属性设置为 hehe

 

四、方法 : Method

 

Method 类封装了一个类的所有方法的描述 包括 修饰符、返回类型、方法名、参数列表、注释、异常信息,还提供了 invoke 方法 来调用自己

 

Method 有一个 invoke 方法: Object invoke(Object obj, Object... args)

调用 invoke 这个方法时至少传一个对象,

第一个参数:表示在哪个对象上调用该方法

第二个参数:表示传给该方法的参数;可以是 0 个或多个;

Method m=c.getMethod("move"); // 调用 obj1 move 方法;

m.invoke(obj1,"hello","hehe"); // 等价于相当于传统的调用: obj1.move("hello","hehe");

 

优势:是方法和方法参数都可以 通过参数传的,并不用写死在程序中;

 

五、构造方法 : Constructor<T>

 

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

 

对于无参构造方法,直接调用 Class 类的 newInstance() 方法就可以构造一个对象。

 

对于有参数的构造方法,先点用 Class 类的 getConstructors() ,利用返回的 Constructor 的对象 调用 newInstance(Object obj1,...); 例如

 

public class ExFrame extends JFrame implements ActionListener,Serializable{

public int intAtt=9;

private double result=90.0;

 

public ExFrame(JPanel pane, int i){

 

}

public void actionPerformed(ActionEvent arg0) {

System.out.println("actionPerformed is invoked.....");

}

}

 

Constructor [] cons = cc.getConstructors();

ExFrame ef = (ExFrame)cons[0].newInstance(new JPanel(), new Integer(20));

 

六、通过反射可以访问对象的私有属性吗?

 

访问权限对 java 虚拟机都是无效的,对于私有属性而言,反射是可以访问到的;

Field f = c.getDeclaredField("name");

f.setAccessible(true);// 私有属性必须加上这个才有效

System.out.println("obj name is: "+f.get(obj));

 

同样对私有成员方法有效: m.setAccessible(true);

对于私有构造方法同样有效, con.setAccessible(true);

构造方法为私有的就不能在外部 new 它的实例 , 但是通过反射可以 ;

 

但是既然设为私有 , 没有特殊情况不要打破封装 ;

 

 

Class java.lang 包下的;没有公开的构造方法;不允许直接创建对象;只能通过具体类获得;用来描述其他的一个类型

 

Class 类的实例表示正在运行的 Java 应用程序中的类和接口

 

获得一个 Class 对象的方式:

1) Class c1=Class.forName("( 类名 =)Student");

2) Class c2=Student.class;

3) Student s1=new Student("");

Class c3=s1.getClass();

不管通过哪种方式获得的,都是同一个对象;一种类型和一个 Class 对象一一对应;看如下程序 , OuterA test 包下的一个普通类。

 

Class c1 = Class.forName("test.OuterA");

System.out.println(c1);

Class c2 = OuterA.class;

System.out.println(c2==c1);// 结果为: true

OuterA out = new OuterA();

Class c3 = out.getClass();

System.out.println(c3==c1);// 结果为: true

 

Class 类的方法介绍:

 

1.int getModifiers() // 得到此类的修饰符的 int 值;

 

Modifiers.toString(int);// 返回的就是那个修饰符名称; 例如:

 

String modifier = Modifier.toString(c1.getModifiers());

System.out.println(modifier);

 

2. Class[] getInterfaces() // 如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。数组中接口对象顺序与此对象所表示的类的声明的 implements 子句中接口名顺序一致。 例如 ExFrame 如下:

 

public class ExFrame extends JFrame implements ActionListener,Serializable{

public int intAtt;

private double result;

public void actionPerformed(ActionEvent arg0) {

}

}

 

main 方法里:

 

Class cc = ExFrame.class;

Class[] interfaces = cc.getInterfaces();

for(int i=0; i<interfaces.length; i++){

System.out.println(interfaces[i]);

}

 

结果如下:

 

interface java.awt.event.ActionListener

interface java.io.Serializable

 

3. Field[] getDeclaredFields();// 得到所有属性;

Field[] getFields() // 得到所有公开属性

 

Field[] fields = cc.getDeclaredFields();

 

for(int i=0; i<fields.length; i++){

System.out.println(fields[i]);

}

 

结果如下:

 

public int test.ExFrame.intAtt

private double test.ExFrame.result

 

 

4. Constructor<T> getDeclaredConstructor(Class... parameterTypes)

... : 可变长参数, 0 ~ 多个,来决定得到哪个构造方法;

 

5. Method getDeclaredMethod(String name, Class... parameterTypes)

Method[] getDeclaredMethods()

返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类

或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

 

6. Class<?>[] getParameterTypes() 得到参数表;

Class<?>[] getExceptionTypes() 得到异常类型;

 

二、反射机制的理解

 

反射的真正目的是让 JVM 动态加载类,并且来调用方法和修改属性;

 

并不是通过程序设置的,而是通过参数来加载类;类名不不出现在源码中;

 

一般是在源代码中:创建一个对象时,才加载这个类;

 

反射 不是给应用程序开发人员用的,是给框架开发人员用的;

 

T newInstance() ;生成新的对象;

 

Method getMethod(String name, Class... parameterTypes)

 

三、属性:类 Field

 

Field 类封装了一个类的属性的所有描述 包括 修饰符、属性类型、属性值、属性的注释,提供了一系列 get/set 方法来获得修改属性的值

 

Class 中有个方法: Field getField(String name) ; 可以得到 Field

 

Field 中常用的方法:

 

Object get(Object obj)

void set(Object obj, Object value)

 

Field f=c.getField("name"); // 得到 obj 对象的 name 属性的值;

f.get(obj); \\ 等价于 obj.name;

f.set(obj1,"hehe");// obj1 f 属性设置为 hehe

 

四、方法 : Method

 

Method 类封装了一个类的所有方法的描述 包括 修饰符、返回类型、方法名、参数列表、注释、异常信息,还提供了 invoke 方法 来调用自己

 

Method 有一个 invoke 方法: Object invoke(Object obj, Object... args)

调用 invoke 这个方法时至少传一个对象,

第一个参数:表示在哪个对象上调用该方法

第二个参数:表示传给该方法的参数;可以是 0 个或多个;

Method m=c.getMethod("move"); // 调用 obj1 move 方法;

m.invoke(obj1,"hello","hehe"); // 等价于相当于传统的调用: obj1.move("hello","hehe");

 

优势:是方法和方法参数都可以 通过参数传的,并不用写死在程序中;

 

五、构造方法 : Constructor<T>

 

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

 

对于无参构造方法,直接调用 Class 类的 newInstance() 方法就可以构造一个对象。

 

对于有参数的构造方法,先点用 Class 类的 getConstructors() ,利用返回的 Constructor 的对象 调用 newInstance(Object obj1,...); 例如

 

public class ExFrame extends JFrame implements ActionListener,Serializable{

public int intAtt=9;

private double result=90.0;

 

public ExFrame(JPanel pane, int i){

 

}

public void actionPerformed(ActionEvent arg0) {

System.out.println("actionPerformed is invoked.....");

}

}

 

Constructor [] cons = cc.getConstructors();

ExFrame ef = (ExFrame)cons[0].newInstance(new JPanel(), new Integer(20));

 

六、通过反射可以访问对象的私有属性吗?

 

访问权限对 java 虚拟机都是无效的,对于私有属性而言,反射是可以访问到的;

Field f = c.getDeclaredField("name");

f.setAccessible(true);// 私有属性必须加上这个才有效

System.out.println("obj name is: "+f.get(obj));

 

同样对私有成员方法有效: m.setAccessible(true);

对于私有构造方法同样有效, con.setAccessible(true);

构造方法为私有的就不能在外部 new 它的实例 , 但是通过反射可以 ;