天天看點

Java反射

<b>閱讀目錄</b>

<a href="http://www.cnblogs.com/kaituorensheng/p/7398069.html#_label0">1. 介紹</a>

<a href="http://www.cnblogs.com/kaituorensheng/p/7398069.html#_label1">2. Java反射相關操作</a>

<a href="http://www.cnblogs.com/kaituorensheng/p/7398069.html#_label2">3. 分析</a>

反射是一種能夠在程式運作時動态通路、修改某個類中任意屬性和方法的機制。

具體:

對于任意一個類,都能夠知道這個類的所有屬性和方法

對于任意一個對象,都能夠調用它的任意一個方法和屬性

在運作時,當加載完類之後,JVM在堆記憶體中會自動産生一個Class類型的對象,這個對象包含了完整的類的結構資訊

這個Class對象就像一面鏡子,透過這個鏡子看到類的結構

Java反射

那麼,如何得到這個Class對象呢?以下可否

答案是不行的,因為Class的構造函數定義為私有的,隻有JVM可以通路

Class對象擷取的三種方式

舉例

<a></a>

輸出

本文以Student類為例:

接口

Java反射
Java反射

以下具體介紹下具體的用法

2.1 類名稱、包名

1

2

3

<code>getSimpleName:Student</code>

<code>getName:com.example.refs.Student</code>

<code>getPackage:package: com.example.refs</code>

2.2 方法

結果

4

5

6

7

8

9

10

11

12

13

14

15

<code>getMethods:      </code><code>public</code> <code>void</code> <code>com.example.refs.Student.read()</code>

<code>getMethods:      </code><code>public</code> <code>void</code> <code>com.example.refs.Student.setId(</code><code>int</code><code>)</code>

<code>getMethods:      </code><code>public</code> <code>final </code><code>void</code> <code>java.lang.Object.wait() throws java.lang.InterruptedException</code>

<code>getMethods:      </code><code>public</code> <code>final </code><code>void</code> <code>java.lang.Object.wait(</code><code>long</code><code>,</code><code>int</code><code>) throws java.lang.InterruptedException</code>

<code>getMethods:      </code><code>public</code> <code>final native </code><code>void</code> <code>java.lang.Object.wait(</code><code>long</code><code>) throws java.lang.InterruptedException</code>

<code>getMethods:      </code><code>public</code> <code>boolean java.lang.Object.</code><code>equals</code><code>(java.lang.Object)</code>

<code>getMethods:      </code><code>public</code> <code>java.lang.String java.lang.Object.toString()</code>

<code>getMethods:      </code><code>public</code> <code>native </code><code>int</code> <code>java.lang.Object.hashCode()</code>

<code>getMethods:      </code><code>public</code> <code>final native java.lang.Class java.lang.Object.getClass()</code>

<code>getMethods:      </code><code>public</code> <code>final native </code><code>void</code> <code>java.lang.Object.notify()</code>

<code>getMethods:      </code><code>public</code> <code>final native </code><code>void</code> <code>java.lang.Object.notifyAll()</code>

<code>getDeclaredMethods:      </code><code>public</code> <code>void</code> <code>com.example.refs.Student.read()</code>

<code>getDeclaredMethods:      </code><code>private</code> <code>int</code> <code>com.example.refs.Student.getId()</code>

<code>getDeclaredMethods:      </code><code>public</code> <code>void</code> <code>com.example.refs.Student.setId(</code><code>int</code><code>)   </code>

指定方法  

異常

原因:setId為私有方法,利用反射時會進行安全檢查,用setAccessible(true)不進行安全檢查,可以直接對調用私有方法、修改私有變量

2.3 構造函數

2.4 成員變量

getDeclaredFields()獲得某個類的所有申明的字段,即包括public、private和proteced,但是不包括父類的申明字段。

getFields()獲得某個類的所有的公共(public)的字段,包括父類。

2.5 修飾符

2.6 父類

2.7 接口

2.8 建立對象執行個體

舉例用2種方法建立

<code>com.example.refs.Student@72ea2f77</code>

<code>com.example.refs.Student@33c7353a</code>

<code>com.example.refs.Student@681a9515</code>

2.9 注解

自定義一個注解

注:RetentionPolicy.RUNTIME 這個表示運作期注解,這樣在反射的時候才能取到

2.10 泛型

參數類型、傳回值類型舉例

<code>#:java.util.Map&lt;java.lang.String, com.example.refs.Student&gt;</code>

<code>泛型類型:class java.lang.String</code>

<code>泛型類型:class com.example.refs.Student</code>

<code>#:java.util.List&lt;com.example.refs.Student&gt;</code>

<code>Returntypejava.util.Map&lt;java.lang.Integer, com.example.refs.Student&gt;</code>

<code>傳回值,泛型類型:class java.lang.Integer</code>

<code>傳回值,泛型類型:class com.example.refs.Student</code>

2.11 數組

<code>array[0]:123</code>

<code>array[1]:124</code>

<code>array[2]:125</code>

<code>intArray是否是數組類型:</code><code>true</code>

<code>intArray成員類型:int </code>

3.1 使用場景

操作因通路權限限制的屬性和方法

實作自定義注解

動态加載第三方jar包

按需加載類,節省編譯和初始化APK的時間

3.2 優缺點

優點:靈活、自由度高:不受類的通路權限限制

缺點

性能問題:通過反射通路、修改類的屬性和方法時會遠慢于直接操作,但性能問題的嚴重程度取決于在程式中是如何使用反射的。如果使用得很少,不是很頻繁,性能将不是問題

安全性問題:反射可以随意通路和修改類的所有狀态和行為,破壞了類的封裝性,如果不熟悉被反射類的實作原理,随意修改可能導緻潛在的邏輯問題

相容性問題:因為反射會涉及到直接通路類的方法名和執行個體名,不同版本的API如果有變動,反射時找不到對應的屬性和方法時會報異常

3.3 說明

通過反射通路方法比執行個體慢很多

有用到反射的類不能被混淆

反射存在性能問題,但使用不頻繁、按需使用時,對程式性能影響并不大

反射存在安全性問題,因為可以随意修改類的所有狀态和行為(包括private方法和執行個體)

使用反射通路Android的API時需要注意因為不同API版本導緻的相容性問題

3.4 性能對比

不使用反射、啟用安全檢查、啟用安全檢查進行對比

結果對比

差異

耗時(ms)

沒用反射

952

取消安全檢查

4283

啟用安全檢查

14892

本文轉自jihite部落格園部落格,原文連結:http://www.cnblogs.com/kaituorensheng/p/7398069.html,如需轉載請自行聯系原作者

下一篇: Java集合

繼續閱讀