91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

如何理解Java反射技術

發布時間:2021-11-01 15:56:29 來源:億速云 閱讀:139 作者:iii 欄目:編程語言

本篇內容介紹了“如何理解Java反射技術”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

一、前期概要

1、 什么是反射

Java 反射機制在程序運行時,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性。這種 動態的獲取信息 以及 動態調用對象的方法 的功能稱為 java 的反射機制。反射中的反的理解:在使用的之前,提前不知道需要使用什么類型的對象。只是在調用的時候,才知道要調用的對象類型。這種反其道而行的就是反射中反的理解。程序執行分為編譯器和運行期,編譯時刻加載一個類就稱為靜態加載類,運行時刻加載類稱為動態加載類,核心思想 讓你在寫代碼的時候可以更加靈活,降低耦合,提高代碼的自適應能力。反射框架提供如下常用的核心功能:1.在運行時判斷任意對象所屬的類;2.在運行時構造任意一個類的對象;3.在運行時判斷任意一個類所具有的成員變量和方法(通過反射甚至可以調用private方法);4.在運行時調用任意一個對象的方法;

2、反射的主要用途

通用框架,很多框架都是配置化的(比如Spring通過xml配置Bean), 為了保證框架的通用性,可能需要根據不同的配置文件加載不同的對象或者類,調用不同的方法,這個時候就需要反射,運行時動態加載需要加載的對象。

3、缺點

· 性能不佳 - 由于java反射動態解析類型,因此涉及掃描類路徑以查找要加載的類的處理,從而導致性能降低。

· 安全限制 - Reflection需要運行時權限,這些權限可能不適用于在安全管理器下運行的系統。由于安全管理器,這可能導致應用程序在運行時失敗。

· 安全問題 - 使用反射,我們可以訪問我們不應該訪問的部分代碼,例如,我們可以訪問類的私有字段并更改它的值。這可能是嚴重的安全威脅,并導致您的應用程序出現異常行為。

· 高維護 - 反射代碼很難理解和調試,在編譯時也無法找到代碼的任何問題,因為這些類可能不可用,使其不太靈活且難以維護。

00001. Class 對象

00002. 類名

00003. 修飾符

00004. 包信息

00005. 父類

00006. 實現的接口

00007. 構造器

00008. 方法

00009. 變量

00010. 注解

二、獲得 Class 對象

在運行期間,一個類,只有一個Class對象產生

1、類的靜態方法(常用) :

00001. 說明獲取指定的類完整的路徑相關聯接口的Class對象。

00002. 方法// 掌握public static Class<?> forName(String className)// 了解public static Class<?> forName(String className, boolean initialize,ClassLoader loader)

00003. 舉個栗子Class clazz = Class.forName("http://com.wener.reflect.Xxx")// 或者 Class clazz = Class.forName("http://com.wener.reflect.Xxx",initialize,this.getClass().getClassLoader)

1. 說明任何數據類型(包括基本數據類型)都有一個“靜態”的class屬性

2. 方法Class<?> cls = 類型.class;

3. 舉個栗子Class<String> cls = String.class;System.out.println(cls.toString());

1. 說明通過對象的實例來返回Class對象

2. 方法Class<?> cls = instance.getClass()

3. 舉個栗子public class User {}User user = new User();Class<? extends User> clz = user.getClass();

1. 方法// 通過字段名,返回一個具體的具有public屬性的成員變量(包括父類的)Field getField(String name) // 通過字段名所有已聲明的所有成員變量(私有的 默認的 共有的),但不能得到其父類的成員變量Field getDeclaredField(String name)

2. 舉個栗子public class User {private String name;public String detail;}public static void main(String[] args) {try {Class<?> cls = Class.forName("com.wener.reflect.demo1.User");/*** 獲取類的指定名稱公開的屬性*/Field detail = cls.getField("detail");System.out.println(detail);/*** 獲取類的指定名稱的的屬性(包括私有的屬性)*/Field name = cls.getDeclaredField("name");System.out.println(name);} catch (ClassNotFoundException | NoSuchFieldException e) {e.printStackTrace();}}

1. 說明反射非常強大,但是學習了之后,會不知道該如何使用,反而覺得還不如直接調用方法來的直接和方便。但等我們后面接觸到一些框架之后才會有一些感觸

2. 測試類package com.wener.reflect.demo2; public class ReflectDemo1 { public void say() { System.out.println("ReflectDemo1"); } } public class ReflectDemo2 { public void say() { System.out.println("ReflectDemo2"); } }

3. 配置文件reflect.propertiesclass=ReflectDemo2. method=say

4. 測試代碼public static void main(String[] args) { //從spring.txt中獲取類名稱和方法名稱 File springConfigFile = new File("/Users/zhangwei/work/IdeaProjects/JavaExample/ReflectExample/src/reflect.properties"); Properties properties = new Properties(); try { properties.load(new FileInputStream(springConfigFile)); String className = (String) properties.get("class"); String methodName = (String) properties.get("method"); //根據類名稱獲取類對象 Class cls = Class.forName(className); //根據方法名稱,獲取方法對象 Method m = cls.getMethod(methodName); //根據構造器,實例化出對象 Object service = cls.newInstance(); //調用對象的指定方法 m.invoke(service); } catch (IOException | InvocationTargetException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException | InstantiationException e) { e.printStackTrace(); } }

5. 優點當需要從調用第一個類的方法,切換到調用第二類的方法的時候,不需要修改一行代碼

1、通過配置文件動態切換六、綜合案例返回值 方法說明String getName()獲取方法的名稱int getModifiers()獲取方法的修飾符Class<?> getReturnType() Type getGenericReturnType返回方法的返回值類型Class<?>[] getParameterTypes() Type[] getGenericParameterTypes()返回方法的參數(列表)Class<?>[] getExceptionTypes() Type[] getGenericExceptionTypes()返回方法的異常信息4、其它API

1. 舉個栗子public class User { private String name = "木木"; public String detail = "hello"; private int age; private BigDecimal balance; public void increment() { this.age++; System.out.println(age); } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } private void say(int num) { System.out.println(num + "號技師"); } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", detail='" + detail + '\'' + '}'; } } public class TestReflectUser { public static void main(String[] args) { reflectMethod(); } public static void reflectMethod() { try { // 1.實例化class對象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); // 2.實例化User對象 Object o = cls.newInstance(); // 3.獲取set方法 Method method = cls.getMethod("increment"); // 4 執行方法 method.invoke(o); // 有參數無返回值 Method setBalance = cls.getMethod("setBalance", BigDecimal.class); Object methodSet = setBalance.invoke(o, new BigDecimal(100.00)); System.out.println(methodSet); // 有返回值值無參數 Method methodGet = cls.getMethod("getBalance"); Object invoke = methodGet.invoke(o); System.out.println(invoke); // 獲取私有的方法 Method say = cls.getDeclaredMethod("say", int.class); // 運行時取消訪問權限檢測機制 say.setAccessible(true); // 執行方法 say.invoke(o, 1); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } }

使用參數 args 在 obj 上指派該對象所表示方法的結果 

1. 方法Object invoke(Object obj, Object... args)

2. 參數說明

· obj - 從中調用底層方法的對象,必須是實例化的對象

· args - 用于方法調用的參數,是個Object數組,因為參數有可能有多個

1. 返回值

3、調用方法

1. 方法// 返回類或接口聲明的所有方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。 public Method[] getDeclaredMethods() throws SecurityException// 返回某個類的所有公用(public)方法,包括其繼承類的公用方法。 public Method[] getMethods() throws SecurityException

2. 舉個栗子public class TestReflectUser { public static void main(String[] args) { reflectMethod(); } public static void reflectMethod() { try { // 1.實例化class對象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); // 2.實例化User對象 Object o = cls.newInstance(); // 獲取所有的共有的方法(包括父類的方法) Method[] methods = cls.getMethods(); for (Method method1 : methods) { System.out.println(method1.getName()); } // 獲取所有的方法(包括私有的,共有的,默認的) Method[] declaredMethods = cls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod.getName()); } } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } }

2、獲取所有的方法

1. 方法// 方法返回一個特定的方法,其中第一個參數為方法名稱,后面的參數為方法的參數對應Class的對象 public Method getMethod(String name, Class<?>... parameterTypes)

2. 舉個栗子public class User { private String name = "木木"; public String detail = "hello"; private int age; private BigDecimal balance; public void increment() { this.age++; System.out.println(age); } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } private void say(int num) { System.out.println(num + "號技師"); } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", detail='" + detail + '\'' + '}'; } } public class TestReflectUser { public static void main(String[] args) { reflectMethod(); } public static void reflectMethod() { try { // 1.實例化class對象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); // 2.實例化User對象 Object o = cls.newInstance(); // 3.獲取increment方法 Method method = cls.getMethod("increment"); // 有參數無返回值 Method setBalance = cls.getMethod("setBalance", BigDecimal.class); // 有返回值值無參數 Method methodGet = cls.getMethod("getBalance"); // 獲取私有的方法 Method say = cls.getDeclaredMethod("say", int.class); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } }

1、獲取單個方法五、方法操作

1. 方法// 將指定對象參數上的此Field對象表示的字段設置為指定的新值 field.set(Object obj,Object value)

2. 參數說明

· Object obj: 字段所在的類的實例對象

· Object value : 新值

1. 注意// 如果要給私有變量賦值必須取消權限的訪問控制 field.setAccessible(true);

2. 舉個栗子public static void main(String[] args) { try { // 1 實例化Class對象 Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); /** * 獲取類的指定名稱公有的屬性 */ Field detail = cls.getField("detail"); System.out.println(detail); /** * 獲取類的所有的屬性(包括私有 默認的 公有的) */ Field name = cls.getDeclaredField("name"); // 2.創建對象 Object o = cls.newInstance(); // 3 通過字段的set方法設置 name.set(o, "嬌嬌"); System.out.println(o.toString()); } catch (ClassNotFoundException | NoSuchFieldException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } }

4、字段賦值

1. 方法// 獲取所有的”公有字段” Field[] getFields() // 獲取所有字段(私有、受保護、默認、公有) Field[] getDeclaredFields()

2. 舉個栗子public class TestReflectUserField { public static void main(String[] args) { try { Class<?> cls = Class.forName("com.wener.reflect.demo1.User"); Field[] fields = cls.getFields(); for (Field field : fields) { System.out.println("類型: " + field.getType() + "方法名: " + field.getName()); } Field[] declaredFields = cls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("類型: " + declaredField.getType() + "方法名: " + declaredField.getName()); } } catch (ClassNotFoundException | NoSuchFieldException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } }

3、獲取所有成員字段

2、獲取單個成員字段類的成員變量也是一個對象,它是java.lang.reflect.Field的一個對象,所以我們通過java.lang.reflect.Field里面封裝的方法來獲取這些信息并且操作這些屬性1、說明四、屬性操作

1. cls.newInstance()方法返回的是一個泛型T,我們要強轉成自定義類

2. cls.newInstance()默認返回的是類的無參數構造對象

3. 被反射機制加載的類必須有無參數構造方法,否者運行會拋出異常

1.4、注意三、創建實例

1. 常用的是類的靜態方法,

2. getClass()的話一般在繼承的時候用的比較多一點,比如Android里的注解框架

3. .class 靜態語法: 需要導入類的包,依賴太強,不導包就拋編譯錯誤

“如何理解Java反射技術”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

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

AI

洱源县| 舞阳县| 宕昌县| 扶绥县| 建水县| 布拖县| 如皋市| 成安县| 拉孜县| 云霄县| 聂荣县| 宜黄县| 商南县| 读书| 威海市| 内丘县| 马鞍山市| 株洲县| 石阡县| 台中县| 太仆寺旗| 鄱阳县| 东莞市| 理塘县| 罗江县| 鲁甸县| 佛山市| 龙山县| 襄城县| 达拉特旗| 石林| 新兴县| 育儿| 略阳县| 桂阳县| 虎林市| 武安市| 黄冈市| 河北省| 淮滨县| 拜泉县|