Java的一切都是对象java
Object是反射的源头数组
Class是反射的导演函数
在Java程序运行时,JVM会对全部的对象维护一个独一无二的类型标识,这就是Class对象。spa
Java的基本类型和关键字void也对应一个Class对象。
相同元素类型和维数的数组也对应一个Class对象。code
获取Class对象的几种方法:对象
Class对象有一些重要的方法:继承
上述系列中包含Declared系列,能够获取当前对象的全部类型的反射(包含private),可是不能获取父类的反射接口
Constructor,Field,Method都是Class导演的三大利器,它们都位于java.lang.reflect
包下,接下来将分别对这三大利器进行展现。get
经过Class对象获取到的Constructor对象以后,最经常使用的操做就是用来实例化对象,调用newInstance方法便可。string
其实在Class对象中也有一个newInstance方法,也能够用来实例化对象,它们的区别是什么呢?
Demo
//Class.newInstance()
//只能调用public属性的无参构造函数
A a = (A)Class.forName(A.class.getName()).newInstance();
//Constructor.newInstance()
Class c= Class.forName(A.class.getName());
/*如下调用无参的、私有构造函数*/
//得到无参构造
Constructor c0=c.getDeclaredConstructor();
//设置无参构造是可访问的
c0.setAccessible(true);
A a0=(A)c0.newInstance();
//调用无参构造函数,生成对象实例
/*如下调用带参的、私有构造函数*/
Constructor c1=c.getDeclaredConstructor(new Class[]{int.class,int.class});
c1.setAccessible(true);
//调用有参构造函数,生成对象实例
A a1=(A)c1.newInstance(new Object[]{5,6});
复制代码
使用场景:
若是使用接口模式,使用new建立一个门的对象,Door door = new WoodenDoor(),当以换成其余门,须要修改代码,Door door = new OtherDoor()。因此咱们须要使用工厂模式,须要什么门就生产什么门,若是咱们再使用newInstance()方法来生产,则只须要修改配置文件便可。
经过Class对象获取到的Field对象以后,咱们就能够自由的查看和设置对象的属性值。
关键方法:
Demo
//获取Class对象
Class aClass = MyObject.class
//经过Class对象获取Field对象
Field field = aClass.getDeclaredField("someField");
//设置可访问权限
field.setAccessible(true);
MyObject objectInstance = new MyObject();
//获取特定的对象的变量属性值
Object value = field.get(objectInstance);
//给特定对象的变量设置属性
field.set(objetInstance, value);
复制代码
由于Constructor,Field,Method都继承自AccessibleObject类,全部都拥有setAccessible方法,我的感受setAccessible有点窥探隐私的感受,哈哈哈,不知道Class导演怎么看。
经过Class对象获取到的Method对象以后,想都不用想啊,获取一个方法不调用它干吗,因此咱们最经常使用的操做应该就是invoke方法。
相信你们对invoke并不会陌生,由于不少的异常,最后都会定位到invoke方法。
java.lang.NullPointerException
at ......
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
复制代码
invoke(Object receiver, Object… args),能够分为两种,传递receiver参数表示调用特定对象的方法,传null表示调用静态方法。
//获取一个方法名为doSomesthing,参数类型为String的方法
Method method = MyObject.class.getMethod("doSomething", String.class);
//调用静态的doSomesthing方法,传递参数"parameter-value1"
Object returnValue = method.invoke(null, "parameter-value1");
复制代码
本文只是对Clss对象以及reflect包下的对象进行简单的使用说明,关于反射的实现和原理,还有待于深刻研究。例如AccessibleObject对象以及对应相关xxxAccessor的实现。