中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java基礎之反射機制的示例分析

發布時間:2021-08-12 09:22:29 來源:億速云 閱讀:127 作者:小新 欄目:開發技術

小編給大家分享一下Java基礎之反射機制的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

    1、什么是Java反射機制?

    在程序運行中動態地獲取類的相關屬性,同時調用對象的方法和獲取屬性,這種機制被稱之為Java反射機制

    下面給出一個反射的簡單例子:

    import lombok.Data;
    
    @Data
    public class User {
    
        public String username;
        private String password;
    
        @Override
        public String toString() {
            return "User{" +
                    "username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    }
    public static void reflectionSimpleExample() throws Exception{
        User user = new User();
        System.out.println(user.toString());
    	// 獲取對應類的class
        Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
        Object obj = cls.newInstance();
        System.out.println(obj);
    	// 獲取成員變量,注意要是public的
        Field field = cls.getField("username");
        System.out.println(field.get(obj));
    
    }

    2、反射機制原理

    Java反射是Java實現動態語言的關鍵,也就是通過反射實現類動態加載

    靜態加載: 在編譯時加載相關的類,如果找不到類就會報錯,依賴性比較強動態加載:在運行時加載需要的類,在項目跑起來之后,調用才會報錯,降低了依賴性

    例子:靜態加載,如下代碼,如果找不到類的情況,代碼編譯都不通過

    User user = new User();

    而動態加載,就是反射的情況,是可以先編譯通過的,然后在調用代碼時候,也就是運行時才會報錯

     Class<?> cls = Class.forName("com.example.core.example.reflection.User");
    Object obj = cls.newInstance();

    Exception in thread “main” java.lang.ClassNotFoundException: com.example.core.example.reflection.User

    java中的反射允許程序在執行期借助jdk中Reflection API來獲取類的內部信息,比如成員變量、成員方法、構造方法等等,并能操作類的屬性和方法

    java中反射的實現和jvm和類加載機制有一定的關系,加載好類之后,在jvm的堆中會產生一個class類型的對象,這個class類包括了類的完整結構信息,通過這個class對象就可以獲取到類的結構信息,所以形象地稱之為java反射

    Java基礎之反射機制的示例分析

    3、Class類介紹

    3.1、Class類基本介紹

    然后這個Class類是什么?看下uml類圖:

    Java基礎之反射機制的示例分析

    Class也是類,因此也繼承Object類

    Class不是直接new出來的,而是經過系統創建的

    User user = new User();

    打個斷點,debug進行看看源碼,可以看到傳統的直接new一個對象也是通過類加載器loadClass拿到的

    Java基礎之反射機制的示例分析

    java反射方式,通用通過調試看看:

     Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");

    同樣本質也是通過ClassLoad再通過類的全類名

    Java基礎之反射機制的示例分析

    3.2、Class類對象的獲取方法 Class.forname()

    Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");

    應用場景:多用于讀取類全路徑,加載類

    具體類.class
    已經知道具體類的情況,通過具體類的class屬性獲取

    Class u = User.class;

    應用場景:多用于用于參數傳遞

    對象.getClass
    已經創建好對象的情況,直接通過對象實例獲取class對象

    Class cls = user.getClass();

    應用場景:通過創建好的對象,獲取Class對象

    ClassLoader獲取

    ClassLoader cl = user.getClass().getClassLoader();
    Class cls = cl.loadClass("com.example.core.example.reflection.domain.User");

    基本數據類型

    Class cls = int.class;

    包裝類

    基本數據類型對應的包裝類可以通過.TYPE得到Class類對象

    Class cls = Integer.TYPE;

    3.3 、可以獲取Class對象的類型

    1、外部類,成員內部類,靜態內部類,局部內部類,匿名內部類

    2、interface:接口

    3、數組

    4、enum:枚舉

    5、annotation:注解

    6、基本數據類型

    7、void8、Class… ,等等

    import com.example.core.example.reflection.domain.User;
    import lombok.ToString;
    
    import java.util.List;
    
    public class GetClassObjectExample {
    
        public static void main(String[] args) {
            // 外部類
            Class<User> cls1 = User.class;
            // 接口
            Class<List> cls2 = List.class;
            // 數組
            Class<Integer[]> cls3 = Integer[].class;
            // 二維數組
            Class<String[][]> cls4 = String[][].class;
            // 注解
            Class<lombok.ToString> cls5 = ToString.class;
    
            // 枚舉
            Class<Thread.State> cls6 = Thread.State.class;
            // 基本數據類型
            Class<Long> cls7 = Long.class;
            // void 數據類型
            Class<Void> cls8 = Void.class;
            // Class
            Class<Class> cls9 = Class.class;
    
            System.out.println(cls1);
            System.out.println(cls2);
            System.out.println(cls3);
            System.out.println(cls4);
            System.out.println(cls5);
            System.out.println(cls6);
            System.out.println(cls7);
            System.out.println(cls8);
            System.out.println(cls9);
        }
    }

    4、java反射的作用?

    可以通過外部類的全路徑名創建對象,并使用這些類可以枚舉出類的全部成員,包括構造函數、屬性、方法利用反射 API 訪問類的私有成員

    5、反射API主要類

    1、java.lang.Class:代表一個類,表示某個類在jvm堆中的對象

    2、 java.lang.reflect.Method:代表類的方法

    3、 java.lang.reflect.Field:代表類的成員變量

    4、 java.lang.reflect.Constructor:代表類額構造方法

    6、Java反射的優缺點

    優點:使用Java反射可以靈活動態地創建和使用對象,反射是框架的底層支撐缺點:使用Java反射,基本就是解釋執行的,對執行速度是有影響的

    7、反射調用的優化方法

    前面介紹了Java反射雖然很靈活,但是缺點就是調用時候比較慢,相對直接new對象來說,情況是怎么樣的?下面通過例子進行試驗:

    import com.example.core.example.reflection.domain.User;
    
    import java.lang.reflect.Method;
    
    public class TestReflectionExample {
    
        private static final Integer TOTAL_COUNT = 1000000;
    
        public static void main(String[] args) throws Exception{
            test0();
            test1();
            test2();
        }
    
        public static void test0() {
            long start = System.currentTimeMillis();
            User user = new User();
            for (int i = 0 ; i < TOTAL_COUNT; i++) {
                user.hello();
            }
            System.out.println(String.format("傳統調用方法執行時間:%d" , System.currentTimeMillis() - start));
        }
    
        public static void test1() throws Exception{
            long start = System.currentTimeMillis();
            Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
            Object obj = cls.newInstance();
            Method hello = cls.getMethod("hello");
            for (int i = 0 ; i < TOTAL_COUNT; i++) {
                hello.invoke(obj);
            }
            System.out.println(String.format("反射方法調用執行時間:%d" , System.currentTimeMillis() - start));
        }
    
        public static void test2() throws Exception{
            long start = System.currentTimeMillis();
            Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
            Object obj = cls.newInstance();
            Method hello = cls.getMethod("hello");
            // 關鍵,取消調用反射方法時的安全檢查
            hello.setAccessible(true);
            for (int i = 0 ; i < TOTAL_COUNT; i++) {
                hello.invoke(obj);
            }
            System.out.println(String.format("優化后的反射方法調用執行時間:%d" , System.currentTimeMillis() - start));
        }
    }

    傳統調用方法執行時間:19
    反射方法調用執行時間:112
    優化后的反射方法調用執行時間:50

    8、反射的基本使用例子

    java.lang.Class類

    方法名作用
    getName獲取全類名
    getSimpleName獲取簡單類名
    getFields獲取所有public修飾的屬性、包括本類以及父類的
    getDeclaredFields獲取本類中所有的屬性
    getMethods獲取所有的public修飾的方法,包括本類以及父類的
    getDeclaredMethod獲取本類中所有方法
    getConstructors獲取所有public修飾的構造器,只有本類
    getDeclaredConstructors獲取本類中所有構造器
    getPackagePackage形式返回 包信息
    getSuperClassClass形式返回父信息
    getInterfacesClass[]形式返回父接口信息
    getAnnotationsAnnotation[]形式返回注解信息
    String allClassName = "com.example.core.example.reflection.domain.User";
    // 通過全類名獲取class對象
    Class<?> cls = Class.forName(allClassName);
    System.out.println(cls);
    // 通過對象獲取class
    System.out.println(cls.getClass());
    // 獲取全類名
    System.out.println(cls.getName());
    // 獲取包名
    System.out.println(cls.getClass().getPackage().getName());
    // 獲取對象實例
    Object obj = cls.newInstance();
    System.out.println(obj);

    java.lang.reflect.Field類

    方法名作用
    getModifiers以int形式返回修飾符,默認修飾符是0,public是1,private是2,protected是4,static是8,final是16
    getType以Class形式返回類型
    getName返回屬性名稱
    // 獲取類屬性
    Field field = cls.getField("username");
    field.set(obj , "admin");
    System.out.println(field.get(obj));
    // 獲取所有類屬性,private的成員變量沒有權限訪問
    Field[] fields = cls.getFields();
    for (Field field1 : fields) {
        System.out.println(field1.get(obj));
    }
    // 獲取所有類屬性包括private成員變量
    Field[] allFields = cls.getDeclaredFields();
    for (Field afield : allFields) {
        // 開放權限,私有的成員變量也能打印出來
        afield.setAccessible(true);
        System.out.println(afield.get(obj));
    }

    java.lang.reflect.Method類

    方法名作用
    getModifiers以int形式返回修飾符,默認修飾符是0,public是1,private是2,protected是4,static是8,final是16
    getName返回方法名
    getReturnType以class形式返回類型
    getParmeterTypes以Class[] 返回參數類型數組
    // 獲取class方法,同樣默認情況不能獲取private的方法
    Method method = cls.getMethod("hello");
    System.out.println(method.invoke(obj));

    java.lang.reflect.Constructor類

    方法名作用
    getModifiers以int形式返回修飾符,默認修飾符是0,public是1,private是2,protected是4,static是8,final是16
    getName返回方法名
    getParmeterTypes以Class[] 返回參數類型數組
    Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
    Constructor<?> con = cls.getDeclaredConstructor();
    con.setAccessible(true);
    Object obj = con.newInstance();
    System.out.println(obj);

    9、反射開放權限操作

    在我們使用Java反射獲取class的private成員變量或者方法時,這種情況是不允許獲取的,不過可以通過開放權限的方式來處理,通過設置setAccessible(true);即可

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * <pre>
     *      開放java反射權限,允許調用類的private屬性或者方法
     * </pre>
     * <p>
     * <pre>
     * @author mazq
     * 修改記錄
     *    修改后版本:     修改人:  修改日期: 2021/08/09 19:10  修改內容:
     * </pre>
     */
    public class AccessibleReflectionExample {
    
        public static void main(String[] args) throws Exception{
    
            test();
        }
    
        public static void test() throws Exception{
            // 創建class實例對象
            Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
            Constructor<?> con = cls.getDeclaredConstructor();
            con.setAccessible(true);
            Object obj = con.newInstance();
    
            // 獲取私有成員變量
            Field pwd = cls.getDeclaredField("password");
            // 開放私有變量的訪問權限
            pwd.setAccessible(true);
            pwd.set(obj , "123456");
    
            // 私有方法調用
            Method method = cls.getDeclaredMethod("priToString");
            method.setAccessible(true);
            System.out.println(method.invoke(obj));
        }
    }

    以上是“Java基礎之反射機制的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    宜城市| 历史| 鲁山县| 巴楚县| 喀喇| 林芝县| 丰镇市| 灌南县| 花垣县| 新丰县| 汽车| 璧山县| 金湖县| 隆化县| 梧州市| 清水河县| 石首市| 浮山县| 休宁县| 北票市| 英德市| 张家川| 吐鲁番市| 衡山县| 昌吉市| 盱眙县| 兴山县| 济源市| 思南县| 万州区| 确山县| 自贡市| 盐源县| 株洲县| 凌云县| 扎赉特旗| 汉阴县| 财经| 繁昌县| 武功县| 资溪县|