反射
定义: 通过reflection包中的方法获取目标类中封装的field(属性),method(方法),constructor(构造方法),注意带private访问权限的元素,可以使用setaccessible方法来获取,不过这也使得代码变得不安全。
原理:
- 首先将java文件存储在存储设备中。
- 将java文件编译成class文件。
- 使用字节码框架生成对应的class文件的字节码。
- 将字节码文件通过jvm进行运行。
- 字节码文件在jvm内存上通过Class来表示。
- 通过获取Class来获取封装的属性、方法等。
反射常用的地方:
- jdk代理,常用做代理一个实现了接口的类,实现步骤一般要实现invocatonhandle接口,实现代理创建方法,实现invoke方法。
- cglib代理,常用做代理一个普通类,实现步骤一般要实现methodinterceptor接口,实现enhancer对象,这个代理是将被代理类设置为父类然后用enhancer继承其父类,设置回调函数,实现interceptor方法,存储时会将代理前和代理后的方法一起存储。
反射例子
public class Lie{
private String i="tony";
public int m=2;
public void show()
{
System.out.println("begin");
}
}
--------------------------------------------------------
//获取Class
Lie lie=new Lie();
Class c=lie.getClass();//第一种获取Class
Class c1=Lie.class;//第二种
Class c2=Class.forname("com.item.Lie");//第三种
----------------------------------------------------------------
//获取元素
String s=c.getName();//获取类名
Field[] field=c.getFields();//获取public修饰的属性
for(Field f:field){//foreach循环
System.out.println(f.getName());//输出
}
Field[] f=c.getDeclardFields();//获取所有的属性
Fileld i=c.getField("i");//获取具体属性的值
i.setaccessible(true);打破private限制,true时将关闭java对外来访问的检查
Object o=c.newInstance();//相当于实例化对象
i.set(o,"sind");//更改属性值
i.get(o);//获取属性值
Method[] m=c.getMethods();//获取public方法
Method[] m=c.getDeclardMethods();获取所有方法
Constructor ct=c.getConstructor();//获取构造方法
扩展:
- 枚举类:常用来封装一组常量,底层是语法糖,保证每个实例都可以转换为内部类,并且使用静态代码实现初始化,保证成员变量不可变
- 例子:
public enum Lie{
Book,Soccer,Shoes
}
------------------------------------------------------------------------
public class Zhu{
public void main(String args[])
{
System.out.println(Lie.Book);//输出为Book
}