今天就跟大家聊聊有關(guān)Java中final的屬性值怎么利用反射機制進行修改,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
站在用戶的角度思考問題,與客戶深入溝通,找到銅梁網(wǎng)站設(shè)計與銅梁網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋銅梁地區(qū)。
假設(shè)有個類
class Person { public final String name = "Mike"; }
這里聲明 name 為非靜態(tài)的屬性只是為了說明反射修改 final 屬性無關(guān)乎靜態(tài)不靜態(tài),靜態(tài)只是表現(xiàn)在它是一個類屬性,在一個類加載器空間只會有一份拷貝,僅此而已。
創(chuàng)建一個通用方法進行反射修改屬性值
public static void modify(Object object, String fieldName, Object newFieldValue) throws Exception { Field field = object.getClass().getDeclaredField(fieldName); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); //Field 的 modifiers 是私有的 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); if(!field.isAccessible()) { field.setAccessible(true); } field.set(object, newFieldValue); }
調(diào)用 modify(...)
方法試圖修改 person 的 name 屬性
Person person = new Person(); modify(person, "name", "Michael"); System.out.println(person.name); //輸出仍然是 Mike
為什么代碼執(zhí)行下來沒問題,但輸出又還是原來的值呢?但總是可以通過反射方式獲取到修改后的新值。這就是 Java 編譯器對 final 屬型的內(nèi)聯(lián)優(yōu)化,即編譯時把該 final 的值直接放到了引用它的地方。即使是反射修改了該屬性,但這種事后處理于事無補。
所以我在標題中所說如何有效的修改 final 屬性值是指:反射修改了 final 屬性值后能夠在后續(xù)代碼中使用修改后的值。
如果 Person 有個方法
public String getName() { return name; }
在前面代碼反射修改了 name 屬性后,getName()
方法也仍然是返回 "Mike"。
那么 Java 會對什么類型的 final 值進行內(nèi)聯(lián)編譯呢?它們基本類型 byte, char, short, int, long, float, double, boolean; 再加上 Literal String 類型(直接雙引號字符串)。只要是不被編譯器內(nèi)聯(lián)優(yōu)化的 final 屬性都可以通過反射有效的進行修改(修改后能使用到新的值)
String 類型比較特殊, 如果把 Person 類 name 屬性改成用 new String("Mike")
public final String name = new String("Mike");
就能夠有效的使用上面的反射代碼修改 name 的值,最后
modify(person, "name", "Michael"); System.out.println(person.name) //輸出就是 Michael 了
正如基本類型有相應的包裝類型,可以把 new String("Mike")
想像為 "Mike" 的包裝類型。也確實是基本類型的 final 包裝類型可以被反射有效的修改,new String("Mike")
也可以。
但我們要是在 IDE 中寫成 new String("Mike")
, 可能被告知 new String("")
這種格式是冗余的,IDE 又會把它改成 "Mike",重而反射行為變得不正確。
還有,如果 final 屬性值是通過構(gòu)造函數(shù)傳入的能不能有效的被修改,當然可以,因為它也不會被編譯器內(nèi)聯(lián)優(yōu)化。
總之一句話:只要不會被編譯器內(nèi)聯(lián)優(yōu)化的 final 屬性就可以通過反射有效的進行修改 -- 修改后代碼中可使用到新的值
為加深印象,我們最后作一個較全面的測試
public class TestFinal { public static void main(String[] args) throws Exception { Person jordan = new Person("Chicago"); modify(jordan , "firstName", "Michael"); System.out.println(jordan .firstName); //Mike modify(jordan , "lastName", "Michael"); System.out.println(jordan.lastName); //Michael modify(jordan , "age", 51f); System.out.println(jordan .age); //50.5 modify(jordan , "height", 1.98f); System.out.println(jordan.height); //1.98 modify(jordan, "address", new Address("ccc", "ddd")); System.out.println(jordan.address.line1); //ccc modify(jordan , "city", "Miami"); System.out.println(jordan.city); //Miami } } class Person { public final String firstName = "Mike"; public final String lastName = new String("Jordan"); //可被有效修改 public final float age = 50.5f; public final Float height = 1.99f; //可被有效修改 public final Address address = new Address("aaa", "bbb"); //可被有效修改 public final String city; //可被有效修改 public Person(String city) { this.city = city; } } final class Address { public final String line1; public final String line2; public Address(String line1, String line2) { this.line1 = line1; this.line2 = line2; } }
我以前也有一人誤區(qū): 就是總以為加了 final 關(guān)鍵值,該屬性就會被編譯器內(nèi)聯(lián)優(yōu)化,就不能用反射有效的進行修改。通過今天的梳理終于清晰的明白了:final 屬性,只要不是基本類型和字面 String,就可以正常使用反射修改它的值。以前曾為了想反射修改某個 final 值還特意把 final 關(guān)鍵字給去掉,完全不用這么做。所以對于基本類型和字面 String, final 只是預示著它的值不能被正常的代碼修改。
因此我們在聲明 log 時
private static Logger log = LoggerFactory.getLogger(TestFinal.class);
和
private static final Logger log = LoggerFactory.getLogger(TestFinal.class);
性能上不會有什么差異,也不會因為多一個 final 而在任何使用到了 log 的地方內(nèi)聯(lián)它。只要留意基本類型和字面 String 就行了。
看完上述內(nèi)容,你們對Java中final的屬性值怎么利用反射機制進行修改有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。
分享標題:Java中final的屬性值怎么利用反射機制進行修改
轉(zhuǎn)載注明:http://www.muchs.cn/article30/ihehso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機、企業(yè)建站、電子商務(wù)、網(wǎng)站設(shè)計公司、建站公司、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)