Java反射机制
时不时回顾一下基础知识,也算是温故而知新,每次都记笔记,想想还是发出来记录一下,写错的地方求大神们指正。
动态语言,所谓动态是指在运行时允许程序修改自身结构或者变量类型。
Java不是动态语言,但是提供了强大的反射机制,可以一定程度上达到动态语言的效果。
Java反射机制的目的有两点:
运行状态下获取任意一个类的所有属性与方法(动态获取信息)
能够调用任意一个对象的方法和属性(动态调用对象方法)
反射机制提供了运行时的灵活性,只要知道某个类,就可以反射创建新的对象和调用对象的方法等,但提升灵活性的同时,反射的效率相比于直接在代码中生成对象或调用方法要差一些,使用时应该权衡效率与灵活性。
Java Reflection API基本功能
获取类的内部结构,包括构造方法、声明的属性、定义的方法、注解等,主要通过java.lang.Class类的对象来完成。已下面这个MyClass类为例。
public class MyClass {
private String className;
public MyClass(String className) {
this.className = className;
}
public MyClass() {
}
public String append(String number) {
return className + number;
}
}
一般生成对象以及调用方法:
MyClass myClass = new MyClass("Class A"); //创建对象
System.out.println(myClass.append("100")); //结果:Class A100
通过反射生成对象以及调用方法:
只要获得java.lang.Class类的对象,比如MyClass.class,就可以通过反射获得该类中构造方法、属性和方法,分别有三类方法:
getConstructors()/getConstructor()
getFields()/getField()
getMethods()/getMethod()
这三类方法对应的还有getDeclared***()方法,区别在于后者只会获取当前类自己声明的构造方法、属性和方法,而前者则会获取通过继承得到的元素。
//获取指定参数类型的构造函数, 比如MyClass类有一个带String参数的构造函数
Constructor constructor = MyClass.class.getDeclaredConstructor(String.class);
MyClass myClass = (MyClass)constructor.newInstance("Class B"); //生成对象
//获取类的所有构造函数
//只会获取明确声明的构造函数,比如无参的构造函数,如果不声明,则不会被获取到
Constructor[] constructors = MyClass.class.getDeclaredConstructors();
//获取类中声明的方法
Method[] methods = MyClass.class.getDeclaredMethods();
Method method = MyClass.class.getDeclaredMethod("append", String.class);
System.out.println(method.invoke(myClass, "100")); //调用方法
//获取类中声明的属性字段
Field[] fields = MyClass.class.getDeclaredFields();
Field field = MyClass.class.getDeclaredField("className");
//Array提供了数组类型的反射
Object array = Array.newInstance(String.class, 5);
Array.set(array, 0, "A");
Array.set(array, 1, "B");
System.out.println(Array.get(array, 1));
带泛型的反射
Java5开始引入了泛型,因此Java反射机制也进行了一定的调整来适应泛型。
在Constructor和Field类中都有一个signature字段,通过这个字段可以在运行时获取到泛型参数类型。
//获取带泛型的属性字段
Field field = MyClass.class.getDeclaredField("students");
//获得类型,如果有泛型则返回带泛型的类型,否则返回类型
//通过Field类的signature字段来判断是否带泛型
//返回 java.util.List<java.lang.String>
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
System.out.println(type);
ParameterizedType parameterizedType =(ParameterizedType) type;
//获取参数类型
Type[] types = parameterizedType.getActualTypeArguments();
for (Type t : types) {
System.out.println(t.getTypeName());
}
}
转载于:https://blog.51cto.com/wentaoxie/1719743