學會了反射,你就是高手了

前言:

​ 相信不少人都知道反射能夠說是Java中最強大的技術了,它能夠作的事情太多太多,不少優秀的開源框架都是經過反射完成的,好比最初的不少註解框架,後來由於java反射影響性能,因此被運行時註解APT替代了,java反射有個開源框架jOOR相信不少人都用過,不過咱們仍是要學習反射的基礎語法,這樣才能本身寫出優秀的框架,固然這裏所講的反射技術,是學習Android插件化技術、Hook技術等必不可少的!java

概述:

JAVA反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的字節碼文件對象。而解剖使用的就是Class類中的方法.因此先要獲取到每個字節碼文件對應的Class類型的對象.數組

以上的總結就是什麼是反射
反射就是把java類中的各類成分映射成一個個的Java對象
例如:一個類有:成員變量、方法、構造方法、包等等信息,利用反射技術能夠對一個類進行解剖,把個個組成部分映射成一個個對象。(其實:一個類中這些成員方法、構造方法、在加入類中都有一個類來描述)
如圖是類的正常加載過程:反射的原理在與class對象。
熟悉一下加載的時候:Class對象的由來是將class文件讀入內存,併爲之建立一個Class對象。框架

學會了反射,你就是高手了

主要做用

經過反射能夠使程序代碼訪問裝載到JVM 中的類的內部信息,獲取已裝載類的屬性信息,獲取已裝載類的方法,獲取已裝載類的構造方法信息ide

經常使用方法

(1)建立Student類性能

package cn.tedu.reflection;
//測試 反射
public class Student {
 public String name = "皮皮霞";
 public int age = 22 ;
    //提供構造方法-右鍵-generate...constructor...
    public Student() {
    }
    public Student(String name) {
        this.name = name;
    }
    public Student(int age) {
        this.age = age;
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
`public void show(){
        System.out.println("show()...");
    }
    public void test(String n){
        System.out.println("test()..."+n);
    }
    //爲了能查看屬性值,而不是地址值,提供重寫的toString()
    //右鍵-generate...toString()-ok
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

(2)建立測試類學習

package cn.tedu.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
//測試 反射
public class Test1_Reflect {
    public static void main(String[] args) throws Exception {
        //method();//經過反射的技術,獲取Class對象
//        method2();//經過反射的技術,獲取類中的全部構造方法
//        method3();//經過反射的技術,獲取成員方法
//        method4();//經過反射的技術,獲取成員變量
        method5();//經過反射的技術,建立實例
    }
    //經過反射的技術,建立實例
    private static void method5() throws Exception {
        //1,獲取Class對象
        Class<Student> clazz = Student.class;
        //2,建立實例
        //newInstance()--會觸發構造方法--觸發無參構造
        Student s = clazz.newInstance();
        //s = Student{name='皮皮霞', age=22}
        System.out.println("s = " + s);

        //3,需求:能夠觸發含參構造嗎?能夠-可是你得指定想要觸發哪一個含參構造
        // --參數是class對象類型,和含參構造的參數類型匹配
        //public Student(String name){} -- new Student("jack");
        Constructor<Student> c = clazz.getConstructor(String.class);
        Student s2 = c.newInstance("jack");
        //s2 = Student{name='jack', age=22}
        System.out.println("s2 = " + s2);
    }
    //經過反射的技術,獲取成員變量
    private static void method4() throws ClassNotFoundException {
        //1,獲取Class對象
        Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
        //2,獲取成員變量--!!!!只能獲取public的!!!!
        Field[] fs = clazz.getFields();
        //3,遍歷數組,獲取每一個Field
        for (Field f : fs) {
            //獲取變量名
            System.out.println( f.getName() );
            //獲取變量類型
            System.out.println( f.getType().getName() );
        }
    }
    //經過反射的技術,獲取成員方法
    private static void method3() {
        //1,獲取Class對象
        Class clazz = Student.class;
        //2,獲取成員方法們
        Method[] ms = clazz.getMethods();
        //3,遍歷數組,獲取每一個Method
        for (Method m : ms) {
            //獲取方法名
            System.out.println(m.getName());
            //獲取方法參數
            Class<?>[] cs = m.getParameterTypes();
            System.out.println( Arrays.toString(cs) );
        }
    }
    //經過反射的技術,獲取類中的構造方法
    private static void method2() {
        //1,獲取Class對象
        Class<Student> clazz = Student.class;
        //2,獲取構造方法們
        Constructor<?>[] cs = clazz.getConstructors();
        //3,foreach循環獲取每一個構造方法
        for (Constructor<?> c : cs) {
            //獲取構造方法名
            System.out.println(c.getName());
            //獲取構造方法的參數
            Class<?>[] cs2 = c.getParameterTypes();
            System.out.println(Arrays.toString(cs2));
        }
    }
    //經過反射的技術,獲取Class對象//三種方式
    private static void method() throws ClassNotFoundException {
//        -- static Class<?> forName(String className)--參數是類的全路徑
        Class<?> clazz = Class.forName("java.lang.Object");
//        -- 類名.class
        Class<String> clazz2 = String.class;
//        -- 對象.getClass()--泛型上限,最大是String類型,約束了元素的類型<=String類型
        Class<? extends String> clazz3 = new String().getClass();

        System.out.println("clazz = " + clazz);
        System.out.println("clazz2 = " + clazz2);
        System.out.println("clazz3 = " + clazz3);
    }
}

暴力反射

暴力的獲取類中的私有資源順便獲取公開的。
暴力反射和普通反射的反射原理是同樣的,都是拿到.class文件中的全部數據並封裝成Class對象,經過各類方法來操做數據,只不過是換了一套API測試

反射機制的優缺點

優勢:

反射提升了Java程序的靈活性和擴展性,下降耦合性,提升自適應能力。它容許程序建立和控制任何類的對象,無需提早硬編碼目標類;反射是其它一些經常使用語言,如C、C++、Fortran 或者Pascal等都不具有的this

缺點:

  • 性能問題:使用反射基本上是一種解釋操做,用於字段和方法接入時要遠慢於直接代碼。所以Java反射機制主要應用在對靈活性和擴展性要求很高的系統框架上,普通程序不建議使用。編碼

  • 使用反射會模糊程序內部邏輯:程序人員但願在源代碼中看到程序的邏輯,反射等繞過了源代碼的技術,於是會帶來維護問題。反射代碼比相應的直接代碼更復雜。
相關文章
相關標籤/搜索