Java反射机制

动态语言

程序运行的时,能够改变程序结构或变量类型。典型的语言:
    Python,ruby,javascript等
    如javascript代码:
        function test(){
            var s = "var a = 3, var b = 4; alert(a+b)";
            eval(s);
        }

C、C++、Java不是动态语言,可是Java有必定的动态性,咱们能够利用反射机制、字节码操做得到相似动态语言的特性。
Java的动态性让编程的时候更加灵活。

反射机制

  • 指的是能够运行时加载、探知、使用编译期间彻底未知的类。javascript

  • 程序在运行状态中,能够加载一个只有名称的类,对于任意一个已加载的类,都可以知道它的方法 和属性,对于任意一个对象,都能调用它的任意一个方法和属性。java

  • 加载完类以后,在堆内存(HotSpot虚拟机是在方法区),就会产生一个Class对象(一个类只用一个Class 对象),这个对象包含整个类的结构信息。咱们能够经过这个对象看到类的结构。这个对象就像一面镜子,经过这个镜子能够个看到 类的结构,因此咱们称之为“反射”。编程

Class类介绍

jdk对Class的介绍:数组

Class类的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每一个数组属于被映射为Class 对象的一个类,全部具备相同元素类型和维数的数组都共享该 Class 对象。基本的Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。 Class没有公共构造方法。Class对象是在加载类时由Java虚拟机以及经过调用类加载器中的defineClass方法自动构造的。ruby

总结:this

  • Class类的对象包含了某个被加载类的结构,一个被加载类的对应一个Class对象。spa

  • 当一个类被加载,或当加载器的defineClass()被JVM掉用,JVM便自动产生一个Class对象。.net

  • Class类是反射的根源。code

获取Class对象

public class ClassTest {
    public static void main(String[] args) throws ClassNotFoundException {
        // (1)forName()获取Class对象(最经常使用)
        Class clazz1 = Class.forName("reflection.Student");
        System.out.println(clazz1.hashCode());
        // (2).class获取Class对象
        Class clazz2 = String.class;
        System.out.println(clazz2.hashCode());
        // (3)getClass()获取Class对象
        // 一个类只对应一个Class对象
        Class clazz3 = "reflection.Student".getClass();
        System.out.println(clazz3.hashCode());


        //每一个数组属于被映射为Class对象的一个类,全部具备相同元素类型和维数的数组都共享该Class对象
        int[] arr01 = new int[10];
        int[][] arr02 = new int[30][3];
        int[] arr03 = new int[30];
        double[] arr04 = new double[10];

        System.out.println(arr01.getClass().hashCode());
        System.out.println(arr02.getClass().hashCode());
        System.out.println(arr03.getClass().hashCode());
        System.out.println(arr04.getClass().hashCode());
    }
}

反射调用方法、属性、构造器

public class Student {
    public String name;
    private int 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;
    }

    private void myPrivateMethod(){

    }

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

    //默认构造器反射的时候不要省略
    public Student() {
    }
}

public class ClassTest {
    public static void main(String[] args) throws Exception {
        // 得到类型
        Class clazz = Class.forName("reflection.Student");
        System.out.println(clazz.getName());
        System.out.println(clazz.getSimpleName());
        // 得到属性
        // 获取所有方法
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("所有的属性:" + field.getName());
        }
        // 获取public修饰的方法
        Field[] fields1 = clazz.getFields();
        for (Field field : fields1) {
            System.out.println("私有的属性:" + field.getName());
        }
        // 得到方法
        // 得到所有方法
        Method[] methods = clazz.getDeclaredMethods();
        // 方法名字 + 无参数
        Method m01 = clazz.getDeclaredMethod("getName", null);
        // 方法名 + 有参数
        Method m02 = clazz.getDeclaredMethod("setName", String.class);
        for(Method m:methods){
            System.out.println("方法:"+m);
        }
        // 得到构造器
        Constructor[] constructors = clazz.getDeclaredConstructors();
        Constructor c = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println("得到构造器:"+c);
        for(Constructor temp:constructors){
            System.out.println("构造器:"+temp);
        }
    }
}

//反射生成对象、调用普通方法、修改属性
public class ClassTest3 {
    public static void main(String[] args) throws Exception {
        //默认构造器产生对象
        Class<Student> clazz = (Class<Student>) Class.forName("reflection.Student");
        System.out.println(clazz.newInstance());

        //指定构造器产生对象
        Constructor<Student> c = clazz.getDeclaredConstructor(String.class, int.class);
        Student student = c.newInstance("xiaoming", 12);
        System.out.println("指定构造器产生对象后获取姓名: " + student.getName());

        //反射调用普通方法
        Method m = clazz.getDeclaredMethod("setName", String.class);
        m.invoke(student, "XIAOHUA ");
        System.out.println("反射调用普通方法修改姓名后获取姓名: " + student.getName());

        //修改该属性
        Student student1 = clazz.newInstance();
        Field field = clazz.getDeclaredField("name");
        field.setAccessible(true);
        field.set(student1, "wjk");
        System.out.println(student1.getName());
        System.out.println(field.get(student1));
    }
}

反射的效率

setAccessible(boolean flag)对象

(1) 将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。

(2) 设置false效率提升。

//验证
public class ClassTest4 {
    public static void test1() {
        Student student = new Student();
        long start = System.currentTimeMillis();
        for (Long i = 1L; i < 1000000L; i++) {
            student.getName();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    public static void test2() throws Exception {
        Student student = new Student();
        Class clazz = student.getClass();
        Method method = clazz.getDeclaredMethod("getName", null);
        long start = System.currentTimeMillis();
        for (Long i = 1L; i < 1000000L; i++) {
            method.invoke(student);
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);

    }

    public static void test3() throws Exception {
        Student student = new Student();
        Class clazz = student.getClass();
        Method method = clazz.getDeclaredMethod("getName", null);
        method.setAccessible(true);
        long start = System.currentTimeMillis();
        for (Long i = 1L; i < 1000000L; i++) {
            method.invoke(student);
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);

    }

    public static void main(String[] args) throws Exception {
        test1();
        test2();
        test3();
    }
}
//结果
37
72
48

反射操做泛型

public class ClassTest5 {
    public static void test1(List<String> strings, Map<String, Object> map) {
        System.out.println("test1");
    }

    public static List<String> test2() {
        return null;
    }

    public static void main(String[] args) throws Exception {
        Class clazz = ClassTest5.class;
        Method m = clazz.getMethod("test1", List.class, Map.class);
        Type[] t = m.getGenericParameterTypes();
        for (Type type : t) {
            System.out.println("#" + type);
            if (type instanceof ParameterizedType) {
                Type[] genericTypes = ((ParameterizedType) type).getActualTypeArguments();
                for (Type genericType : genericTypes) {
                    System.out.println("泛型类型:" + genericType);
                }
            }
        }


        Method m2 = ClassTest5.class.getMethod("test2", null);
        Type returnType = m2.getGenericReturnType();
        if (returnType instanceof ParameterizedType) {
            Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();

            for (Type genericType : genericTypes) {
                System.out.println("返回值,泛型类型:" + genericType);
            }

        }

    }
}
//结果
#java.util.List<java.lang.String>
泛型类型:class java.lang.String
#java.util.Map<java.lang.String, java.lang.Object>
泛型类型:class java.lang.String
泛型类型:class java.lang.Object
返回值,泛型类型:class java.lang.String

反射操做注解

参考:http://my.oschina.net/u/2361475/blog/597726

相关文章
相关标签/搜索