java.lang.Class对象
每一个java类都会被加载到jvm内存,生成一个对应的java.lang.Class对象才能使用。取得这个对象可以通过如下方式:
1、如:A.class
2、对象的getClass()方法。
3、如:Class.forName("com.test.javatest.A")
类载入分三个阶段
1、加载:加载class文件
2、链接:为静态成员变量分配内存,设置初始值,如int、long设置为0,Object设置为null,boolean设置为false
3、初始化:为静态成员变量设置用户指定的值,执行static块。
如果使用A.class这种方式访问到类时,只会执行第1、2阶段,不会执行static块(当调用它的方法时也会执行,如A.class.newInstance())。
使用Class.forName默认会执行全部3个阶段。也可以设定只做第一步(forName第二个参数设置为false,ClassLoader.loadClass(className,false);)。
反射的概念
通常使用类都是提前定义好java文件,然后创建对象,调用属性、方法。而有一些情况则不能提前定义类,如类的定义是运行期才知道的,比如spring框架中创建bean对象,框架无法预知用户会定义哪些bean类,但它要为这些用户定义的bean类创建bean对象,它只能在运行期动态获取类定义创建bean对象,而不能提前用new的方式写在代码中创建。
这种情况可以采用反射机制,首先通过类的全路径生成对应的java.lang.Class对象。java.lang.Class对象提供了通过Class创建实际对象的能力,但这时由于没有提前定义类的class文件,因此不能在代码里面直接通过"对象."的形式访问属性或者调用方法,而且反射出来的对象是个Object类型,由于没有类的class定义,也无法使用强转。
java.lang.Class提供了一系列的方法,可以实现创建对象、获取对象的属性、通过方法名调用对象的方法等操作。
常用的反射功能
isInstance判断是否为某个类的实例
如:
a = 2;
out.println(Number.class.isInstance(a)); // true
创建对象
1、通过Class的newInstance方法创建,只能调用无参构造函数,如果定义了有参构造函数,又没有写无参构造函数,则会报错。
使用,如:
classB = Class.forName("com.test.javatest.B");
bclassB.newInstance();
2、通过Constructor对象创建。
首先取得Constructor,可取得数组,或者根据参数类型取得单个。
然后调用它的newInstance方法即可
constructorclassB.getConstructor(String.class, Integer.class);
constructor.newInstance("kkk", 3);
ps:如果参数是int类型而不是Integer,则要用Integer.TYPE代替Integer.Class,或者用int.class,如:
获取方法
getMethods(),返回所有public方法,包括继承的。
getDeclaredMethods(),返回本类(接口)中声明的所有方法,不包括继承的。
getMethod(String name, Class<?>... parameterTypes),根据方法名、参数获取单个方法。
如:
获取方法数组:
由于所有类都继承了Object类,所以getMethods打印了很多从Object继承下来的public方法,但没有打印本类中的protected和private。getDeclaredMethods打印了本类中定义的三个方法。
获取单个方法:
ps:通过名称获取的方法必须是public的,否则报错,如:
获取成员变量
与获取方法类似:
getFields():获取所有的public成员变量,包括继承的
getDeclaredFields():获取本类(接口)中定义的成员变量,不包括继承的
如:
获取成员变量数组:
获取单个成员变量:
ps:通过名称获取的成员变量必须是public的,否则报错。
调用方法
使用getField得到的方法是类里面的定义,调用方法前必须有一个对象,然后将该对象作为参数传递个field的invoke方法,它会自动回调对象中的对应方法:
如:
使用数组
由于通常定义对象数组的时候需要指定对象类型,如:String[] s;而在运行期才知道对象类型的情况下,就不能使用这种方式直接创建数组了。
可以使用反射的方式创建,如:
import java.lang.reflect.Array;
publicclass A {
publicstaticvoidargs) throws Exception {
classB = Class.forName("com.test.javatest.B");
// 创建数组
bArray = Array.newInstance(classB, 5);
// 设置数组元素
Array.set(bArray, 0, classB.newInstance());
Array.set(bArray, 1, classB.newInstance());
// 获取数组元素
Array.get(bArray, 0);
}
}
class B {
}
反射调用private方法
反射越过泛型检查