如何改變String類的值,保證地址不變!


一、String是一個不可變類

  我們都知道String是一個不可變類,因為它的源碼內部維護着一個final修飾的char數組,final修飾的變量不可以被改變,修飾的方法不可以被重寫,修飾的類不可以被繼承:(簡要源碼)

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
}

也就是說:String對象一旦創建,就不可改變。拼接、截取或者重新賦值都是在重新建對象。

做一下代碼演示:

/**
 * @Author 程Sir
 * @Version 2020年3月26日上午11:20:51
 * @description 描述:字符串不可以被改變
 */
public class Demo {

    public static void main(String[] args) throws IOException {
        String str = "不變的字符串";
        System.out.println("1. " + str +" : " + str.hashCode());
        
        str = str.substring(2);
        System.out.println("3. " + str +" : " + str.hashCode());
        
        str = str+1;
        System.out.println("2. " + str +" : " + str.hashCode());
    }

}

輸出的結果是:

  1. 不變的字符串 : 83361354
  3. 的字符串 : 927327327
  2. 的字符串1 : -1317623886

通過演示表明:hashcode值每次都是不一樣的。說明操作的不是同一對象,再次過程中有新的對象被創建。

二、應用Java中的反射機制

  我們學習了反射機制,了解到:反射是在運行期能夠對類的屬性、方法進行操作。即:運行期綁定。那么我們是不是可以在String運行期對它的值進行一個完美操作了,答案是肯定的,完全可以的,看以下代碼:

/**
 * @Author 程Sir
 * @Version 2020年3月26日上午11:20:51
 * @description 描述:字符串不可以被改變
 */
public class Demo {

    public static void main(String[] args) throws IOException {
        String str = "不變的字符串";
        System.out.println("1. " + str +" : " + str.hashCode());
        
        try {
            //反射通過屬性拿到值,Sting類的屬性char數組的屬性名為:value
            Field field = str.getClass().getDeclaredField("value");
            //設置該屬性為可操作
            field.setAccessible(true);
            //改變該屬性的值:改變char數組
            field.set(str, new char[]{'程','s','i','r'});
            
            System.out.println("2. " + str+" : " + str.hashCode());
                                        
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
輸出的結果是:

  1. 不變的字符串 : 83361354
  2. 程sir : 83361354

從演示結果中,我們發現,字符串str的hashcode值兩次相等,並沒有發生改變,說明是同一對象,但前后的值(內容)完全是發生了改變。即達到了我們的目的:String類的值是可以通過Java的反射機制進行改變的。

三、總結

  最后,我們做一個總結:

  String類是用final關鍵字修飾的,那值就是不可以改變,值不可以改變,導向到結果是這個值的引用地址在內存中是不可被改變。再String類的本質是內部維護這一個char類型的數組,明確這點后,我們既可以通過Java反射機制的特性,在運行期對其內部的char數組內容進行操作,從而達到改變String類內容的目的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM