关于JAVA反射

反射的定义:

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

自己的理解:

java会在编译时将类的信息保存到堆中,反射便是获取的编译时保存的类的信息,反射不是该类的实例,反射更应该理解成类的图 纸。通过这张图纸可以获取反射映射的类的所有信息,也可以通过这张图纸创建一个实例。

    //动态调用method
    Method method = stuClass.getDeclaredMethod("setName", String.class);
    method.invoke(stu1, "Lee");

通过动态调用的方式可以使得程序更为的灵活,如果想要调用私有的方法和属性可以通过setAccessible来关闭安全检测。

反射的效率

package com.lee.myTest;

public class Student {
    private int id;
    private String name;
    private int age;
    //默认构造方法一定得有
    public Student(){
    }

    public Student(int id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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;
    }


}

package com.lee.myTest;

import java.lang.reflect.Method;

public class TestReflex {

    //通过普通调用执行
    public static void test01(){
        Student student = new Student();
        long startTime = System.currentTimeMillis();
        for(int i = 0;i < 1000000000;i++)
        {
            student.getAge();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(endTime-startTime+"ms");
    }
    //通过反射执行
    public static void test02(){
        try {
            //通过反射获取实例
            Class<Student> c = (Class<Student>) Class.forName("com.lee.myTest.Student");
            Student stu = c.newInstance();
            Method m = c.getDeclaredMethod("getId");
            long startTime = System.currentTimeMillis();
            for(int i = 0; i < 1000000000;i++)
            {
                m.invoke(stu);
            }
            long endTime = System.currentTimeMillis();
            System.out.println(endTime-startTime+"ms");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //通过反射执行(关闭安全检查)
    public static void test03(){
        try {
            //通过反射获取实例
            Class<Student> c = (Class<Student>) Class.forName("com.lee.myTest.Student");
            Student stu = c.newInstance();
            Method m = c.getDeclaredMethod("getId");
            m.setAccessible(true);//关闭安全检查
            long startTime = System.currentTimeMillis();
            for(int i = 0; i < 1000000000;i++)
            {
                m.invoke(stu);
            }
            long endTime = System.currentTimeMillis();
            System.out.println(endTime-startTime+"ms");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        test01();
        test02();
        test03();
    }
}

关于输出结果

对于不同的电脑可能会有不同的结果,setAccessible为true可以提高反射的运行效率,并且可以访问到被private修饰的变量。

版权声明: 本文由Lee创作和发表,采用署名(BY)-非商业性使用(NC)-相同方式共享(SA)国际许可协议进行许可,转载请注明作者及出处
本文链接:http://leewant.github.io/2018/07/05/关于JAVA反射/