最近在学习框架,而为了更好的理解框架底层的原理,需要对反射有着足够的理解,这几天利用课余时间又复习了下反射,所以总结成博客与大家分享也方便以后的复习,不足之处,请批评指正。
一.反射是什么:
Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时取得任何一个已知名称的class的内
部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields
和methods的所有信息,并可于运行时改变fields内容或唤起methods。Java反射机制容许程序在运行时加载、探知、使用编译期间完
全未知的classes。换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。
翻了好多书和博客,大佬们基本都是这么写的,我理解,简单的认为就是在程序运行期间,动态的取得一个类中的所有信息,
或改变field内容,调用method等。具体底层原理,如果了解jvm类加载机制,会对反射有着更好的理解,这里简单来说,就是jvm在
加载一个类是,会为这个类生成一个class对象,这个对象包含此类的诸多信息,反射也是通过这个对象完成的。
二,反射基础知识
我建议先浏览一下api文档,对reflect这个包有个总体的把握,其中Method field Constructor Modifier Proxy 等都是常用的类
1. 取得class对象:
1.对象.getClass();
2.类.class
3.Class.forName(“name”) 常用
2.获得实例化对象
Public T newInstance() throws InstantiationException,IllegalAcessException
3. 获得方法
构造方法:
Public Constructor<?>[] getConstructors() throws SecurityException
Public Constructor<T> getConstructor(Class<?>... parameterTypes)
利用构造函数获得对象实例:(T)constructor.newInstance(Object obj...);
普通方法:
Public Method[] getMethods()
Public Method getMethod(String name ,Class<?>...parameterTypes) 取得指定参数的方法
利用反射调用方法:
Public Object invoke(Object obj,Object params...) 第一个参数为调用对象,后面为参数
4. 获得成员:
Public Field[] getDeclaredField()
Public Field getDeclaredField(String name) 获得指定的成员
Public Field[] getFields()
Public Field getField(String name)
这里说一下:对于getFields() 取到的是包括父类中全部public的属性,而getDeclaredfields()取得的是不包括父类的全部范围的属性
,即包括private等,其实,对于方法来说,也有此类的方法,道理也是一样,这里只给出最常用的方法
Field类常用方法:
Public void set(Object obj,Object value) 相当于对象.属性=内容
Public Object get(Object obj) 相当于对象.属性
Public void setAccessible(boolean flag) 解除封装
注意:如果要调用Field类中的get set方法,必须解除封装
5. 其他常用方法
getName()
Class<?> getSuperClass()
Class<?>[] getInterfaces()
Class<?> type = field.getType() 获得属性类型
Int mo = field.getModifiers(); 获得属性权限修饰符
String modifier = Modifier.toString(mo);
其他的方法,可参考API文档
三.测试代码
下面是我自己实现的一个测试代码,知识熟悉反射的方法,没有实际含义
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return name +" "+ age;
}
public void say(String lag){
System.out.println(lag);
}
private void eat(){
}
}
public class ReflectTest {
public static void main(String[] args){
try {
Class cls = Class.forName("Reflect.Person");//取得class对象
System.out.println(cls.getName()); //输出类名
Object obj = (Person)cls.newInstance(); //获取对象实例
System.out.println(obj.toString());
Method[] methods = cls.getMethods(); //取得所有方法
System.out.println(methods.length);
Constructor[] cons = cls.getConstructors(); //取得所有构造方法
System.out.println(cons.length);
Method method = cls.getMethod("setName",String.class);//取得指定参数的方法
System.out.println(method.toString());
Constructor con = cls.getConstructor(String.class,int.class);//取得指定参数的构造方法
Person linda = (Person) con.newInstance("Linda",20);//根据构造方法生成实例
System.out.println(linda.toString());
Method method2 = cls.getMethod("say",String.class);//得到给定方法名的方法
method2.invoke(linda, "hello"); //运用反射执行方法
Field[] fields = cls.getFields(); //获取所有公有属性
System.out.println(fields.length);
Field[] pfields = cls.getDeclaredFields();//获取仅此类中全部属性
System.out.println(pfields.length);
Object bob = (Person)cls.newInstance();
pfields[0].setAccessible(true);//解除封装
pfields[0].set(bob, "Bob");
pfields[1].setAccessible(true);
pfields[1].set(bob, 25);
System.out.println(bob.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
控制台输出:
Reflect.Person
null 0
14
2
public void Reflect.Person.setName(java.lang.String)
Linda 20
hello
0
2
Bob 25
四 反射应用
反射在框架中有着广泛的应用,为了更好的学习框架的原理,我们要先学习一些设计模式,下面具体讨论一下反射在工厂模式及
动态代理中的应用,关于设计模式的详细总结,我会在后续的博客中更新。