Java反射机制总结

Posted ywb-articles

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射机制总结相关的知识,希望对你有一定的参考价值。

一.什么是反射

  在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为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

以上是关于Java反射机制总结的主要内容,如果未能解决你的问题,请参考以下文章

反射机制入门

反射机制入门

反射机制入门

JAVA反射机制—学习总结

java--反射机制总结

JAVA反射机制,总结下