工作一年多了,总是听说框架都是基于反射和代理实现的,可就是不知道反射是啥玩意,也不知道Java还能坚持多久,反正现在我靠她吃饭,总要把重要的东西弄懂才是!下面是我对反射机制的总结。
Java语言的反射机制
Java的反射机制允许程序在运行时通过Reflection APIs获得任何一个已知名称的类的内部信息,包括它的访问修饰符(modifiers)、父类(superclass)、接口以及field和method是所有信息,并且可于运行时调用任意一个method以及操作任意一个field。
Java的反射机制具有如下功能:
在运行时判断任意一个对象所属的类
构造任意一个类所属的对象
判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
反射的基本使用:
1、获得反射的入口即获得待处理类或对象的Class对象:通常使用如下三种方法
当已知某个类的全类名时,使用Class类的静态方法forName,如Class.forName("java.lang.String");
已知某个类的全类名时,使用类的class语法,如 Class<?> classType = String.class;
当对象已获得时,使用getClass方法,如String str = "aa"; Class<?> classType = str.getClass();
2、创建对象:通过目标类的Class对象创建该类的实例
通用方法是获得这个类的构造方法所对应的Constructor对象,通过Constructor对象的newInstance方法创建,如
Constructor cons = classType.getDeclaredConstructor(new Class[]{String.class, int.class});//如果是调用无参的构造方法,则数组长度为0
Object obj = cons.newInstance(new Object[]{"张三", 22});
如果调用的无参的构造方法创建对象,不仅可以通过Constructor对象来创建,还可以直接使用Class对象创建:
使用Class对象创建:
Object obj = classType.newInstance();
使用Constructor对象创建:
Constructor cons = classType.getDeclaredConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
3、调用某个方法:通过反射入口获得该方法所对应的Method对象,前提是该方法名已知,然后调用invoke方法
Method method = classType.getMethod("add", new Class[]{int.class, int.class});//获得public类型的add()方法
Method method = classType.getMethod("add", new Class[]{int.class, int.class});//可以获得private类型的add()方法
调用invoke方法
method.invoke(obj, new Object[]{1, 3});//第一个蚕食表示调用这个方法的对象
4、获得成员变量:同调用方法类似,前提是已知该成员变量的名字
Field field = classType.getField("name");//该name属性是public的
Field field = classType.getDeclaredField("name");//可以获得private类型的属性
5、通过Constructor、Method、Field这三个类的父类AccessibleObject类中的setAccessible(boolean flag)来设置是否压制(suppress)默认的
Java语言的访问控制检查,当设置为true时,表示压制,则使用反射可以调用私有的方法,操作私有的成员变量。
例如:
public class PrivateTest(){
private String sayHello(String name){
return "Hello " + name;
}
}
public class Test(){
public static void main(String[] args){
PrivateTest pt = new PrivateTest();
Class<?> classType = pt.getClass();
Method method = classType.getDeclatedMethod("sayHello", new Class[]{String.class});
method.setAccessible(true);//压制Java语言的访问控制检查
String result = method.invoke(pt, new Object[]{"Jack"});
System.out.println((String)result);
}
}
6、java.lang.reflect.Array:在反射包下的Array类提供
静态的方法动态的创建和访问Java数组
介绍两个创建数组的API
public static Object newInstance(Class<?> componentType, int length)
public static Object newInstance(Class<?> componentType, int...dimensions)
第一个的实现其实是调用了第二个。。。
第二个中两个参数:componentType表示组建类型,认为数组是由一个个的组件构成的,若组件类型是String.class则这个数组是一个字符串数组
dimensions是一个可变参数,它实际上是一个int类型的数组,这个int类型数组的长度作为新创建数组的维度,如果dimensions.length为1,则创建的新数组是一位数组。