标签:eth java反射机制 类名.class proxy 它的 反编译 spring tcl 构造
一.什么是反射
在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。
二.为什么需要反射
首先我们要了解Java的编译类型有两种:
1.静态编译:在编译时确定类型,绑定对象即通过。
2.动态编译:运行时确定类型,绑定对象。动态编译最大限度地发挥了Java的灵活性,体现了多态的应用,可以减低类之间的耦合性。
而Java反射机制在Java动态编译的起到了一个关键作用。
三.反射获取Class对象的三种方式(获取字节码对象)
public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException { //方式一(通过Class.forName的方式,括号中是包名.类名)常用 Class clazz1 = Class.forName("xx.ReflectDemo1"); //方式二(类名.class) Class clazz2 = ReflectDemo1.class; //方式三(创建类的实例对象,再通过getClass的方式) ReflectDemo1 ref = new ReflectDemo1(); Class clazz3 = ref.getClass(); System.out.println(clazz1 == clazz2);//true System.out.println(clazz2 == clazz3);//true,三个字节码对象是同一个字节码对象 } }
四.通过反射获构造器,成员变量,方法等
public class ReflectDemo2 { private String name; public ReflectDemo2(String name) { super(); this.name = name; } @Override public String toString() { return "[name=" + name + "]"; } public void method1(){ System.out.println("你好啊"); } public void method2(String name){ System.out.println("hello"+name); } public static void main(String[] args) throws Exception { //通过反射获取有参构造,并通过有参构造创建对象 Class clazz = Class.forName("course9.ReflectDemo2"); Constructor c = clazz.getConstructor(String.class); ReflectDemo2 ref = (ReflectDemo2) c.newInstance("zx"); System.out.println(ref); //通过反射获取成员变量并使用 Field f = clazz.getDeclaredField("name");//获取姓名字段(暴力反射获取,即使是私有变量) f.setAccessible(true);//设置去除私有权限 f.set(ref, "ls"); System.out.println(ref); //通过反射获取方法并使用 Method m1 = clazz.getMethod("method1"); Method m2 = clazz.getMethod("method2",String.class); m1.invoke(ref); m2.invoke(ref,"张三"); } }
输出结果如下:
五.通过反射越过泛型检查
public class ReflectDemo3 { public static void main(String[] args) throws Exception { //使用反射越过泛型的检查 ArrayList<Integer> list = new ArrayList<>();//创建一个存放整型的链表 list.add(11); list.add(22); Class clazz = Class.forName("java.util.ArrayList");//获取java.util.ArrayList类的字节码对象 Method m = clazz.getMethod("add", Object.class);//获取其中的add方法 m.invoke(list, "abc");//链表中添加字符串 System.out.println(list); } }
输出结果如下:(“abc”不是Interger类型,但是能存放在创建的链表中)
六.反射实现动态代理
public class ReflectDemo4 implements User{ public static void main(String[] args) { ReflectDemo4 ref = new ReflectDemo4(); ref.add(); ref.delete(); MyInvocationHandler m = new MyInvocationHandler(ref);//创建动态代理类(放入需要代理的对象) User user = (User) Proxy.newProxyInstance(ref.getClass().getClassLoader(), ref.getClass().getInterfaces(), m);//获取类加载器和接口 System.out.println("-----------------------"); user.add(); user.delete(); } @Override public void add() { System.out.println("添加功能"); } @Override public void delete() { System.out.println("删除功能"); } } interface User{ public void add(); public void delete(); } //动态代理类 class MyInvocationHandler implements InvocationHandler{ private Object target; public MyInvocationHandler(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验"); method.invoke(target, args);//执行被代理target对象的方法 System.out.println("日志记录"); return null; } }
输出结果如下:(动态代理前的输出和代理后的输出)
七.反射的一些应用
如加载一些文件
逆向代码 ,例如反编译
与注解相结合的框架 例如Spring
动态生成类框架 例如Gson
标签:eth java反射机制 类名.class proxy 它的 反编译 spring tcl 构造
原文地址:https://www.cnblogs.com/ywb-articles/p/10588298.html