自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java高級(jí)編程:使用反射強(qiáng)制給private字段賦值

開發(fā) 后端
反射看來根本不區(qū)分是否是private的,調(diào)用本身的私有方法是可以的,但是調(diào)用父類的私有方法則不行,糾其原因很有可能是因?yàn)間etDeclaredMethod方法和getMethod方法并不會(huì)查找父類的私有方法,自己寫遞歸可以解決,不過利用反射來做的話性能不會(huì)太好。

一般情況下,我們并不能對(duì)類的私有字段進(jìn)行操作,但有的時(shí)候我們又必須有能力去處理這些字段,這時(shí)候,我們就需要調(diào)用AccessibleObject上的setAccessible()方法來允許這種訪問,而由于反射類中的Field,Method和Constructor繼承自AccessibleObject,因此,通過在這些類上調(diào)用setAccessible()方法,我們可以實(shí)現(xiàn)對(duì)這些字段的操作。今天項(xiàng)目中遇到了一個(gè)問題,要調(diào)用一個(gè)類,并獲取這個(gè)類的屬性進(jìn)行賦值然后將這個(gè)類傳遞到方法中做為參數(shù)。

實(shí)際操作時(shí)才發(fā)現(xiàn),這個(gè)類中的字段屬性是私有的,不能進(jìn)行賦值!沒有提供公有的方法。而這個(gè)類又是打包成jar給我的,我還不能更改它的代碼,以至于想手動(dòng)給它寫個(gè)set方法都是問題。后來想到用反射可以解決這個(gè)問題,于是試了一下,果然!

反射看來根本不區(qū)分是否是private的,調(diào)用本身的私有方法是可以的,但是調(diào)用父類的私有方法則不行,糾其原因很有可能是因?yàn)間etDeclaredMethod方法和getMethod方法并不會(huì)查找父類的私有方法,自己寫遞歸可以解決,不過利用反射來做的話性能不會(huì)太好。

我們來看下面這個(gè)代碼。

  1. Field[] fields = obj.getDeclaredFields();  
  2.             for (int i = 0; i < fields.length; i++) {  
  3.                 fields[i].setAccessible(true);  
  4.                 for (int j = 0; j < args.length; j++) {  
  5.                     String str = args[j];  
  6.                     String strs[] = str.split(",");  
  7.                     if (strs[0].equals(fields[i].getName())) {  
  8.                         fields[i].set(object, strs[1]);  
  9.                         break;  
  10.                     }  
  11.                 }  
  12.             } 

 

  1. fields[i].setAccessible(true); 

這句話是關(guān)鍵。看它的表面英文意思是設(shè)置可進(jìn)入可訪問為:true。編程意思大家猜想也應(yīng)該知道了。

通過查看JDK的源碼:

  1. public void setAccessible(boolean flag) throws SecurityException {  
  2.     SecurityManager sm = System.getSecurityManager();  
  3.     if (sm != null) sm.checkPermission(ACCESS_PERMISSION);  
  4.     setAccessible0(this, flag);  
  5.     } 

我們可以看到它是通過SecurityManager來管理權(quán)限的,我們可以啟用java.security.manager來判斷程序是否具有調(diào)用setAccessible()的權(quán)限。默認(rèn)情況下,內(nèi)核API和擴(kuò)展目錄的代碼具有該權(quán)限,而類路徑或通過URLClassLoader加載的應(yīng)用程序不擁有此權(quán)限。

例如:當(dāng)我們以這種方式來執(zhí)行上述程序時(shí)將會(huì)拋出異常

  1. java.security.AccessControlException:   access   denied  

一般情況下,我們并不能對(duì)類的私有字段進(jìn)行操作,但有的時(shí)候我們又必須有能力去處理這些字段,這時(shí)候,我們就需要調(diào)用AccessibleObject上的setAccessible()方法來允許這種訪問,而由于反射類中的Field,Method和Constructor繼承自AccessibleObject,因此,通過在這些類上調(diào)用setAccessible()方法,我們可以實(shí)現(xiàn)對(duì)這些字段的操作。

我們來看看這個(gè)ACCESS_PERMISSION里面究竟怎么處理的:

  1. static final private java.security.Permission ACCESS_PERMISSION =  
  2. new ReflectPermission("suppressAccessChecks"); 

查找JDK幫助文檔可以看到詳細(xì)解釋:

  1. public final class ReflectPermissionextends BasicPermission 

反射操作的 Permission 類。ReflectPermission 是一種指定權(quán)限,沒有動(dòng)作。當(dāng)前定義的唯一名稱是suppressAccessChecks,它允許取消由反射對(duì)象在其使用點(diǎn)上執(zhí)行的標(biāo)準(zhǔn) Java 語言訪問檢查 - 對(duì)于 public、default(包)訪問、protected、private 成員。

下表提供了允許權(quán)限的簡要說明,并討論了授予代碼權(quán)限的風(fēng)險(xiǎn)。

權(quán)限目標(biāo)名稱 權(quán)限允許的內(nèi)容 允許此權(quán)限的風(fēng)險(xiǎn)
suppressAccessChecks 能夠訪問類中的字段和調(diào)用方法。注意,這不僅包括 public、而且還包括 protected 和 private 字段和方法。 存在的風(fēng)險(xiǎn)是,通常不可用的信息(也許是保密信息)和方法可能會(huì)接受惡意代碼訪問。

這里就一點(diǎn)了然了。fields.setAccessible(true);的實(shí)際作用就是使權(quán)限可以訪問public,protected,private的字段!

是不是很爽呢。當(dāng)然這種方法破壞了JAVA原有的權(quán)限體系。所以不到萬不得已,還是少用,反射的效率畢竟不是那么高滴。

好,知道了這個(gè)我們再來寫一個(gè)通用的***方法,只是傳遞相應(yīng)的類,字段名稱和值,我們在方法內(nèi)部將其反射并進(jìn)行實(shí)例化。然后進(jìn)行相應(yīng)字段的賦值。由于我只用到了字段。你可以加上其它的東東。嗯。這個(gè)好玩。

  1. package com.sinoglobal.utils;  
  2.  
  3. import java.lang.reflect.Field;  
  4.  
  5. import com.jasson.mas.api.smsapi.Sms;  
  6.  
  7. /**  
  8.  * 反射的通用工具類  
  9.  *   
  10.  * @author lz  
  11.  *   
  12.  */ 
  13. public class ReflectionUtils {  
  14.       
  15.     /**  
  16.      * 用于對(duì)類的字段賦值,無視private,project修飾符,無視set/get方法  
  17.      * @param c 要反射的類  
  18.      * @param args 類的字段名和值 每個(gè)字段名和值用英文逗號(hào)隔開  
  19.      * @return  
  20.      */ 
  21.     @SuppressWarnings("unchecked")  
  22.     public static Object getInstance(Class c, String... args) {  
  23.         try {  
  24.             Object object = Class.forName(c.getName()).newInstance();  
  25.             Class<?> obj = object.getClass();  
  26.             Field[] fields = obj.getDeclaredFields();  
  27.             for (int i = 0; i < fields.length; i++) {  
  28.                 fields[i].setAccessible(true);  
  29.                 for (int j = 0; j < args.length; j++) {  
  30.                     String str = args[j];  
  31.                     String strs[] = str.split(",");  
  32.                     if (strs[0].equals(fields[i].getName())) {  
  33.                         fields[i].set(object, strs[1]);  
  34.                         break;  
  35.                     }  
  36.                 }  
  37.             }  
  38.             return object;  
  39.         } catch (IllegalAccessException e) {  
  40.             e.printStackTrace();  
  41.         } catch (ClassNotFoundException e) {  
  42.             e.printStackTrace();  
  43.         } catch (InstantiationException e) {  
  44.             e.printStackTrace();  
  45.         }  
  46.         return null;  
  47.     }  
  48.     public static void main(String[] args) {  
  49.         Object object=getInstance(Sms.class,"destID,01201101","mobile,15810022404","content,測試數(shù)據(jù)。");  
  50.         Sms sms=(Sms)object;  
  51.         System.out.println("短信內(nèi)容:"+sms.content);  
  52.         System.out.println("手機(jī)號(hào)碼:"+sms.mobile);  
  53.         System.out.println("尾號(hào):"+sms.destID);  
  54.     }  

控制臺(tái)輸出:

短信內(nèi)容:測試數(shù)據(jù)。

手機(jī)號(hào)碼:15810022404

尾號(hào):01201101

fields.setAccessible(true);的使用可能大家都會(huì),但我們要做的是,知其然,知其所以然。

看JDK的源碼,無疑是學(xué)習(xí)和解決此方法的***途徑。

原文鏈接:http://blog.csdn.net/yaerfeng/article/details/7103397

【編輯推薦】

  1. 使用Java 2D繪制黑白太極圖案
  2. Java并發(fā)編程:守護(hù)線程
  3. 深入Java虛擬機(jī)之內(nèi)存優(yōu)化
  4. 深入Java虛擬機(jī)之虛擬機(jī)體系結(jié)構(gòu)
  5. 從Java的角度理解Ext的extend
責(zé)任編輯:林師授 來源: yaerfeng的博客
相關(guān)推薦

2009-08-31 14:07:57

C# private字C# public屬性

2011-08-15 17:15:45

CASE語句Oracle給指定字段賦值

2022-12-14 08:42:46

IDEAIDEA插件

2017-05-26 10:15:39

Java高級(jí)特性反射

2021-11-28 18:23:53

Java特性序列化

2011-08-29 13:10:59

SQL Server 給新加字段賦值

2024-07-30 14:46:55

2011-10-08 11:05:04

GPUMATLAB

2023-06-27 08:37:35

Java反射動(dòng)態(tài)代理機(jī)制

2024-09-11 08:00:00

Java優(yōu)于反射開發(fā)

2024-03-04 18:49:59

反射C#開發(fā)

2024-05-24 10:51:51

框架Java

2018-06-07 09:29:34

數(shù)據(jù)庫MySQL慢SQL

2021-03-22 08:45:30

異步編程Java

2019-11-27 10:05:00

LombokJava編程

2015-08-07 09:33:24

RuntimeModel

2021-10-30 18:38:49

Java c++反射

2023-11-06 13:32:38

Go編程

2024-11-08 08:56:01

2010-11-12 10:46:16

SQL Server變
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)