詳解Java高級(jí)特性之反射
定義
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱(chēng)為java語(yǔ)言的反射機(jī)制。
用途
在日常的第三方應(yīng)用開(kāi)發(fā)過(guò)程中,經(jīng)常會(huì)遇到某個(gè)類(lèi)的某個(gè)成員變量、方法或是屬性是私有的或是只對(duì)系統(tǒng)應(yīng)用開(kāi)放,這時(shí)候就可以利用Java的反射機(jī)制通過(guò)反射來(lái)獲取所需的私有成員或是方法。當(dāng)然,也不是所有的都適合反射,之前就遇到一個(gè)案例,通過(guò)反射得到的結(jié)果與預(yù)期不符。閱讀源碼發(fā)現(xiàn),經(jīng)過(guò)層層調(diào)用后在最終返回結(jié)果的地方對(duì)應(yīng)用的權(quán)限進(jìn)行了校驗(yàn),對(duì)于沒(méi)有權(quán)限的應(yīng)用返回值是沒(méi)有意義的缺省值,否則返回實(shí)際值起到保護(hù)用戶(hù)的隱私目的。
反射機(jī)制的相關(guān)類(lèi)
與Java反射相關(guān)的類(lèi)如下:
類(lèi)名 用途 Class類(lèi) 代表類(lèi)的實(shí)體,在運(yùn)行的Java應(yīng)用程序中表示類(lèi)和接口 Field類(lèi) 代表類(lèi)的成員變量(成員變量也稱(chēng)為類(lèi)的屬性) Method類(lèi) 代表類(lèi)的方法 Constructor類(lèi) 代表類(lèi)的構(gòu)造方法
Class類(lèi)
Class代表類(lèi)的實(shí)體,在運(yùn)行的Java應(yīng)用程序中表示類(lèi)和接口。在這個(gè)類(lèi)中提供了很多有用的方法,這里對(duì)他們簡(jiǎn)單的分類(lèi)介紹。
獲得類(lèi)相關(guān)的方法
方法 用途 asSubclass(Class<U> clazz) 把傳遞的類(lèi)的對(duì)象轉(zhuǎn)換成代表其子類(lèi)的對(duì)象 Cast 把對(duì)象轉(zhuǎn)換成代表類(lèi)或是接口的對(duì)象 getClassLoader() 獲得類(lèi)的加載器 getClasses() 返回一個(gè)數(shù)組,數(shù)組中包含該類(lèi)中所有公共類(lèi)和接口類(lèi)的對(duì)象 getDeclaredClasses() 返回一個(gè)數(shù)組,數(shù)組中包含該類(lèi)中所有類(lèi)和接口類(lèi)的對(duì)象 forName(String className) 根據(jù)類(lèi)名返回類(lèi)的對(duì)象 getName() 獲得類(lèi)的完整路徑名字 newInstance() 創(chuàng)建類(lèi)的實(shí)例 getPackage() 獲得類(lèi)的包 getSimpleName() 獲得類(lèi)的名字 getSuperclass() 獲得當(dāng)前類(lèi)繼承的父類(lèi)的名字 getInterfaces() 獲得當(dāng)前類(lèi)實(shí)現(xiàn)的類(lèi)或是接口
獲得類(lèi)中屬性相關(guān)的方法
方法 用途 getAnnotation(Class<A> annotationClass) 返回該類(lèi)中與參數(shù)類(lèi)型匹配的公有注解對(duì)象 getAnnotations() 返回該類(lèi)所有的公有注解對(duì)象 getDeclaredAnnotation(Class<A> annotationClass) 返回該類(lèi)中與參數(shù)類(lèi)型匹配的所有注解對(duì)象 getDeclaredAnnotations() 返回該類(lèi)所有的注解對(duì)象
獲得類(lèi)中構(gòu)造器相關(guān)的方法
方法 用途 getConstructor(Class...<?> parameterTypes) 獲得該類(lèi)中與參數(shù)類(lèi)型匹配的公有構(gòu)造方法 getConstructors() 獲得該類(lèi)的所有公有構(gòu)造方法 getDeclaredConstructor(Class...<?> parameterTypes) 獲得該類(lèi)中與參數(shù)類(lèi)型匹配的構(gòu)造方法 getDeclaredConstructors() 獲得該類(lèi)所有構(gòu)造方法
獲得類(lèi)中方法相關(guān)的方法
方法 用途 getMethod(String name, Class...<?> parameterTypes) 獲得該類(lèi)某個(gè)公有的方法 getMethods() 獲得該類(lèi)所有公有的方法 getDeclaredMethod(String name, Class...<?> parameterTypes) 獲得該類(lèi)某個(gè)方法 getDeclaredMethods() 獲得該類(lèi)所有方法
類(lèi)中其他重要的方法
方法 用途 isAnnotation() 如果是注解類(lèi)型則返回true isAnnotationPresent(Class<? extends Annotation> annotationClass) 如果是指定類(lèi)型注解類(lèi)型則返回true isAnonymousClass() 如果是匿名類(lèi)則返回true isArray() 如果是一個(gè)數(shù)組類(lèi)則返回true isEnum() 如果是枚舉類(lèi)則返回true isInstance(Object obj) 如果obj是該類(lèi)的實(shí)例則返回true isInterface() 如果是接口類(lèi)則返回true isLocalClass() 如果是局部類(lèi)則返回true isMemberClass() 如果是內(nèi)部類(lèi)則返回true
Field類(lèi)
Field代表類(lèi)的成員變量(成員變量也稱(chēng)為類(lèi)的屬性)。
方法 用途 equals(Object obj) 屬性與obj相等則返回true get(Object obj) 獲得obj中對(duì)應(yīng)的屬性值 set(Object obj, Object value) 設(shè)置obj中對(duì)應(yīng)屬性值
Method類(lèi)
Method代表類(lèi)的方法。
方法 用途 invoke(Object obj, Object... args) 傳遞object對(duì)象及參數(shù)調(diào)用該對(duì)象對(duì)應(yīng)的方法
Constructor類(lèi)
Constructor代表類(lèi)的構(gòu)造方法。
方法 用途 newInstance(Object... initargs) 根據(jù)傳遞的參數(shù)創(chuàng)建類(lèi)的對(duì)象
示例
為了演示反射的使用,首先構(gòu)造一個(gè)與書(shū)籍相關(guān)的model——Book.java,然后通過(guò)反射方法示例創(chuàng)建對(duì)象、反射私有構(gòu)造方法、反射私有屬性、反射私有方法,最后給出兩個(gè)比較復(fù)雜的反射示例——獲得當(dāng)前ZenMode和關(guān)機(jī)Shutdown。
被反射類(lèi)Book.java
public class Book{ private final static String TAG = 'BookTag'; private String name; private String author; @Override public String toString() { return 'Book{' +'name=’' + name + ’’’ +', author=’' + author + ’’’ +’}’; } public Book() { } private Book(String name, String author) { this.name = name; this.author = author; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } private String declaredMethod(int index) { String string = null; switch (index) { case 0:string = 'I am declaredMethod 1 !';break; case 1:string = 'I am declaredMethod 2 !';break; default:string = 'I am declaredMethod 1 !'; } return string; }}
反射邏輯封裝在ReflectClass.java
public class ReflectClass { private final static String TAG = 'peter.log.ReflectClass'; // 創(chuàng)建對(duì)象 public static void reflectNewInstance() { try { Class<?> classBook = Class.forName('com.android.peter.reflectdemo.Book'); Object objectBook = classBook.newInstance(); Book book = (Book) objectBook; book.setName('Android進(jìn)階之光'); book.setAuthor('劉望舒'); Log.d(TAG,'reflectNewInstance book = ' + book.toString()); } catch (Exception ex) { ex.printStackTrace(); } } // 反射私有的構(gòu)造方法 public static void reflectPrivateConstructor() { try { Class<?> classBook = Class.forName('com.android.peter.reflectdemo.Book'); Constructor<?> declaredConstructorBook = classBook.getDeclaredConstructor(String.class,String.class); declaredConstructorBook.setAccessible(true); Object objectBook = declaredConstructorBook.newInstance('Android開(kāi)發(fā)藝術(shù)探索','任玉剛'); Book book = (Book) objectBook; Log.d(TAG,'reflectPrivateConstructor book = ' + book.toString()); } catch (Exception ex) { ex.printStackTrace(); } } // 反射私有屬性 public static void reflectPrivateField() { try { Class<?> classBook = Class.forName('com.android.peter.reflectdemo.Book'); Object objectBook = classBook.newInstance(); Field fieldTag = classBook.getDeclaredField('TAG'); fieldTag.setAccessible(true); String tag = (String) fieldTag.get(objectBook); Log.d(TAG,'reflectPrivateField tag = ' + tag); } catch (Exception ex) { ex.printStackTrace(); } } // 反射私有方法 public static void reflectPrivateMethod() { try { Class<?> classBook = Class.forName('com.android.peter.reflectdemo.Book'); Method methodBook = classBook.getDeclaredMethod('declaredMethod',int.class); methodBook.setAccessible(true); Object objectBook = classBook.newInstance(); String string = (String) methodBook.invoke(objectBook,0); Log.d(TAG,'reflectPrivateMethod string = ' + string); } catch (Exception ex) { ex.printStackTrace(); } } // 獲得系統(tǒng)Zenmode值 public static int getZenMode() { int zenMode = -1; try { Class<?> cServiceManager = Class.forName('android.os.ServiceManager'); Method mGetService = cServiceManager.getMethod('getService', String.class); Object oNotificationManagerService = mGetService.invoke(null, Context.NOTIFICATION_SERVICE); Class<?> cINotificationManagerStub = Class.forName('android.app.INotificationManager$Stub'); Method mAsInterface = cINotificationManagerStub.getMethod('asInterface',IBinder.class); Object oINotificationManager = mAsInterface.invoke(null,oNotificationManagerService); Method mGetZenMode = cINotificationManagerStub.getMethod('getZenMode'); zenMode = (int) mGetZenMode.invoke(oINotificationManager); } catch (Exception ex) { ex.printStackTrace(); } return zenMode; } // 關(guān)閉手機(jī) public static void shutDown() { try { Class<?> cServiceManager = Class.forName('android.os.ServiceManager'); Method mGetService = cServiceManager.getMethod('getService',String.class); Object oPowerManagerService = mGetService.invoke(null,Context.POWER_SERVICE); Class<?> cIPowerManagerStub = Class.forName('android.os.IPowerManager$Stub'); Method mShutdown = cIPowerManagerStub.getMethod('shutdown',boolean.class,String.class,boolean.class); Method mAsInterface = cIPowerManagerStub.getMethod('asInterface',IBinder.class); Object oIPowerManager = mAsInterface.invoke(null,oPowerManagerService); mShutdown.invoke(oIPowerManager,true,null,true); } catch (Exception ex) { ex.printStackTrace(); } } public static void shutdownOrReboot(final boolean shutdown, final boolean confirm) { try { Class<?> ServiceManager = Class.forName('android.os.ServiceManager'); // 獲得ServiceManager的getService方法 Method getService = ServiceManager.getMethod('getService', java.lang.String.class); // 調(diào)用getService獲取RemoteService Object oRemoteService = getService.invoke(null, Context.POWER_SERVICE); // 獲得IPowerManager.Stub類(lèi) Class<?> cStub = Class.forName('android.os.IPowerManager$Stub'); // 獲得asInterface方法 Method asInterface = cStub.getMethod('asInterface', android.os.IBinder.class); // 調(diào)用asInterface方法獲取IPowerManager對(duì)象 Object oIPowerManager = asInterface.invoke(null, oRemoteService); if (shutdown) {// 獲得shutdown()方法Method shutdownMethod = oIPowerManager.getClass().getMethod( 'shutdown', boolean.class, String.class, boolean.class);// 調(diào)用shutdown()方法shutdownMethod.invoke(oIPowerManager, confirm, null, false); } else {// 獲得reboot()方法Method rebootMethod = oIPowerManager.getClass().getMethod('reboot', boolean.class, String.class, boolean.class);// 調(diào)用reboot()方法rebootMethod.invoke(oIPowerManager, confirm, null, false); } } catch (Exception e) { e.printStackTrace(); } }}
調(diào)用相應(yīng)反射邏輯方法
try { // 創(chuàng)建對(duì)象 ReflectClass.reflectNewInstance(); // 反射私有的構(gòu)造方法 ReflectClass.reflectPrivateConstructor(); // 反射私有屬性 ReflectClass.reflectPrivateField(); // 反射私有方法 ReflectClass.reflectPrivateMethod(); } catch (Exception ex) { ex.printStackTrace(); } Log.d(TAG,' zenmode = ' + ReflectClass.getZenMode());
Log輸出結(jié)果如下:
08-27 15:11:37.999 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectNewInstance book = Book{name=’Android進(jìn)階之光’, author=’劉望舒’}08-27 15:11:38.000 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectPrivateConstructor book = Book{name=’Android開(kāi)發(fā)藝術(shù)探索’, author=’任玉剛’}08-27 15:11:38.000 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectPrivateField tag = BookTag08-27 15:11:38.000 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectClass: reflectPrivateMethod string = I am declaredMethod 1 !08-27 15:11:38.004 11987-11987/com.android.peter.reflectdemo D/peter.log.ReflectDemo: zenmode = 0
以上就是詳解Java高級(jí)特性之反射的詳細(xì)內(nèi)容,更多關(guān)于JAVA高級(jí)特性反射的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. 低版本IE正常運(yùn)行HTML5+CSS3網(wǎng)站的3種解決方案2. jsp實(shí)現(xiàn)局部刷新頁(yè)面、異步加載頁(yè)面的方法3. xml文件的結(jié)構(gòu)解讀第1/2頁(yè)4. Jsp中request的3個(gè)基礎(chǔ)實(shí)踐5. python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5工具欄控件QToolBar的詳細(xì)使用方法與實(shí)例6. 使用python修改文件并立即寫(xiě)回到原始位置操作(inplace讀寫(xiě))7. python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5計(jì)數(shù)器控件QSpinBox詳細(xì)使用方法與實(shí)例8. Python填充任意顏色,不同算法時(shí)間差異分析說(shuō)明9. Java map.getOrDefault()方法的用法詳解10. 什么是python的id函數(shù)
