- 今天刷技術文章,遇到了一個問題,用 Java 反射機制去修改 String 變量的值,出於深刻研究,就發現了一個問題,即,用初始值比較修改後的值,用 == or .equals() 方法,出現了相等的狀況
文字描述看起來比較難受,咱們直接看代碼java
//建立字符串"Hello World", 並賦給引用 s String s = "Hello World"; System.out.println("s = " + s); //Hello World //獲取String類中的value字段 Field valueFieldOfString = String.class.getDeclaredField("value"); //改變value屬性的訪問權限 valueFieldOfString.setAccessible(true); //獲取s對象上的value屬性的值 byte[] value = (byte[]) valueFieldOfString.get(s); //改變value所引用的數組中的第5個字符 value[5] = '_'; System.out.println("s = " + s); //Hello_World System.out.println("Hello World".toString()); System.out.println(s == "Hello World"); // true System.out.println(s.equals("Hello World")); // true
如上方代碼所示,咱們定義了一個 String 變量 s ,而且賦值給它 "Hello World",而後經過 Java 的反射機制去修改第五個字符的值,在輸出結果的時候,理所固然的結果是 "Hello_World",可是我在這個狀況之上多了一手,把被修改後的值與初始值比較看看,會發生什麼狀況,結果一試就出現了問題,居然與初始值相等且返回了 true .數組
因而,打算好好深究一下,咱們知道 String 的變量是存放在 JVM 的常量池中的,同時指向 "Hello World" 的引用 s1 是 String 對象,存放在堆區,咱們經過反射區修改的值並非常量池中的 "Hello World" ,而是 堆區中的對象 s1 的值,因此咱們輸出 s1 的時候就是 "Hello_World" ,那麼爲何初始值比較修改後的值的時候會出現 true 呢?.net
咱們看看 System.out.println("Hello World".toString());
這行代碼,輸出結果是 Hello_World
,這是由於 "Hello World".toString() 的時候,會去常量池中去找 "Hello World"的引用,它的引用就是 s1 ,因此輸出的是 s1 的值,即 "Hello_World",因此,到這裏,咱們就知道了,爲何 s == "Hello World" 和 s.equals("Hello World") 返回 true 了 .3d