反射

来源:互联网 发布:最全的php扩展开发教程 编辑:程序博客网 时间:2024/06/12 00:26

Class类

·Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。

·Class类代表Java类,它的各个实例对象又分别对应什么呢?
 对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等。

·一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型就是Class。
Class类描述了哪些方面的信息呢?类的名字,类的访问属性,类所属于的包名,字段名称的列表、方法名称的列表,等等。学习反射,首先就要明白Class这个类。

·如何得到各个字节码对应的实例对象(Class类型)
1-类名.class,例如,System.class。
2-对象.getClass(),例如,new Date().getClass()。
3-Class.forName("类名"),例如,Class.forName("java.util.Date");。

<span style="font-size:18px;">ReflectTest.javapackage com.itheima.day1;public class ReflectTest {       public static void main(String[] args) throws Exception {            String str = "abc";                        Class clazz1 = String.class;            Class clazz2 = str.getClass();            Class clazz3 = Class.forName("java.lang.String" );            System. out.println(clazz1 == clazz2);             //结果:true            System. out.println(clazz2 == clazz3);             //结果:true                        System. out.println(clazz1.isPrimitive());             //结果:false            System. out.println(int.class.isPrimitive());             //结果:true            System. out.println(int.class == Integer. class);             //结果:false            System. out.println(int.class == Integer. TYPE);             //结果:true            System. out.println(int[].class.isPrimitive());             //结果:false            System. out.println(int[].class.isArray());             //结果:true      }}</span>
构造方法的反射应用
·Constructor类代表某个类中的一个构造方法。
 Constructor对象代表一个构造方法,Constructor对象上会有的方法有:得到方法名字,得到所属于的类,产生实例对象。

·得到某个类所有的构造方法:
 例子:Constructor[] constructors= Class.forName("java.lang.String").getConstructors();
·得到某一个构造方法:
 例子:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);//获得方法时要用到类型
注意:
一个类有多个构造方法,用什么方式可以区分清楚想得到其中的哪个方法呢?根据参数的个数和类型,例如,Class.getMethod(name,Class... args)中的args参数就代表所要获取的那个方法的各个参数的类型的列表。重点:参数类型用什么方式表示?用Class实例对象。

·创建实例对象:
 通常方式:String str = new String(new StringBuffer("abc"));
 反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc")); //调用获得的方法时要用到上面相同类型的实例对象
·Class.newInstance()方法:
 例子:String obj = (String)Class.forName("java.lang.String").newInstance();
 该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

<span style="font-size:18px;">public class ReflectTest {       public static void main(String[] args) throws Exception {            Constructor constructor = String.class.getConstructor(StringBuffer.class);            String str = (String)constructor.newInstance( new StringBuffer("abc" ));            System. out.println(str.charAt(2));            //结果:c      }}</span>
成员变量的反射
·Field类代表某个类中的一个成员变量。
·问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联的是哪个对象呢?所以字段fieldX 代表的是x的定义,而不是具体的x变量。

<span style="font-size:18px;">public class ReflectPoint {       private int x;       public int y ;              public ReflectPoint(int x, int y) {             super();             this.x = x;             this.y = y;      }</span>
<span style="font-size:18px;">public class ReflectTest {       public static void main(String[] args) throws Exception {            ReflectPoint rp = new ReflectPoint(3, 5);            Field fieldY = rp.getClass().getField( "y");            System. out.println(fieldY.get(rp));            //结果:5      }}</span>
如果类的某个成员变量的修饰符是private,那么直接通过getDeclaredField方法获取Field类型的对象就会出现错误。

解决方法,暴力反射

<span style="font-size:18px;">public class ReflectTest {       public static void main(String[] args) throws Exception {            ReflectPoint rp = new ReflectPoint(3, 5);            Field fieldX = rp.getClass().getDeclaredField("x");            fieldX.setAccessible(true);            System. out.println(fieldX.get(rp));      }}</span>
成员方法的反射
·Method类代表某个类中的一个成员方法。

·得到类中的某一个方法:
例子:Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
调用方法:
 通常方式:System.out.println(str.charAt(1));
 反射方式:System.out.println(charAt.invoke(str, 1)); 

注意:
如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!

·jdk1.4和jdk1.5的invoke方法的区别:
Jdk1.5:public Object invoke(Object obj,Object... args)
Jdk1.4:public Object invoke(Object obj,Object[] args)
即按jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数。所以,调用charAt方法的代码也可以用Jdk1.4改写为 charAt.invoke("str", new Object[]{1})形式。

<span style="font-size:18px;">public class ReflectTest {       public static void main(String[] args) throws Exception {            String str = "abc";                        Method methodCharAt = String.class.getMethod("charAt" , int.class );            System. out.println(methodCharAt.invoke(str, 1));            //结果:b            System. out.println(methodCharAt.invoke(str, new Object[]{2}));            //结果:c      }}</span>

0 0
原创粉丝点击