Java反射机制是通过内部提供的Reflaction APIs来获得任意已知名称的类信息。
Class类
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.
上面是Class类的java文档解释,Class中包含了一个类型全部的信息,其内部提供了一些列方法来访问这些信息,要用反射机制就需要用到Class类。
Class获取方式
1、Object.getClass()Object类提供了一个方法getClass来获取一个对象对应的类型,因为java中所有对象都继承自Object,所以子类都可以通过此方法获得;
2、Class.forName() 提供一个全限定名,返回相应的Class类;
3、.class 如String.class;
4、对于基本数据类型,采用.TYPE,如Boolean.TYPE;
Class提供的一些方法
1、Package getPackage(),返回当前类的包名;
2、int getModifiers(),获取类的访问权限,对应到方法Method和属性Field也有这个方法;
3、String getName(),返回类名
4、Class getSuperClass(),返回父类
5、Class[] getInterfaces(),返回接口
6、Class[] getDeclaredClasses(),返回内部类
7、Method[] getMethods(),返回所有方法,包括父类的、接口的
8、Method[] getDeclaredMethods(),返回本类声明的方法,不包括未覆写的父类的方法;
9、Field[] getFields(),返回字段
10、Field[] getDecclaredFields(),返回本类声明的字段
11、Constructor[] getConstructors(),返回构造函数
其中getField用于返回一个指定名称的属性,但是这个属性必须是公有的,这个属性可以在父类中定义。如果是私有属性或者是保护属性,那么都会抛出异常提示找不到这个属性。getDeclaredField获得在这个类型的声明中定义的指定名称的属性,这个属性必须是在这个类型的声明中定义,可以使私有和保护的,但是所有父类的属性都不会被返回。
运行时生成对象
对于含有无参构造函数的类,可以使用
Class c = Class.forName("Test");
Object obj = c.newInstance();
如果需要向构造函数传入参数,就需要用Constructor来实例化
Class c = Class.forName("Test");
Class[] pTypes = new Class[] { String.class };
Constructor tor = c.getConstructor(pTypes);
Object[] args = new Object[] {"test"};
Object obj = tor.newInstance(args);
调用methods
Class c = Class.forName("Test");
Class[] pTypes = new Class[] {String.class};
Method m = c.getMethod("func", pTypes);
Test obj = new Test();
Object[] args = new Object[] {"Test"};
Object result = m.invoke(obj, args);
修改变量Fields
Class c = Class.forName("Test");
Field f = c.getField("mStr");
Test obj = new Test();
f.get(obj);
f.set(obj, "Test");
如果得到的方法或者变量是私有的,这时候需要setAccessible(true)来使其可访问,否则再调用set或get方法时会抛IllegalAccessException异常。