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

相關文章
相關標籤/搜索