1.比較

程序員需要一直比較不同的變量。但是,正如您已經看到的,一切都不是那麼簡單。

整數非常容易比較——你只需使用==就可以了。要比較實數,您必須將它們的差異(或者更確切地說,差異的絕對值)與一些非常小的數字進行比較。

比較字符串更加困難。最重要的是,這是因為字符串是對象。更重要的是,程序員通常希望字符串比較根據情況有所不同。


2.字符串是如何排列內存的

正如您已經看到的,字符串在內存中的存儲方式不同於整數和實數:

字符串是如何排列內存的

兩個內存塊用於存儲字符串:一個塊存儲文本本身(其大小取決於文本的大小),而第二個塊(4 個字節)存儲第一個塊的地址。

儘管有經驗的程序員會說類似“String str變量存儲對對象的引用String


3. 分配對字符串的引用

當您需要將一個字符串變量分配給另一個字符串變量時,這種方法的好處就很明顯了。例子:

String text = "This is a very important message";
String message = text;

結果是內存將包含的內容:

分配對字符串的引用

在這種類型的賦值操作之後,String對象保持在原來的位置,只是它的地址(對對象的引用)被複製到變量中message


4. 使用引用和對象

但是,如果您決定將字符串轉換為大寫(大寫字母),Java 機器會做所有正確的事情:您最終會得到兩個String對象,並且text變量message將存儲引用,每個對像都指向自己的對象。

例子:

String text = "This is a very important message";
String message = text.toUpperCase(); 

結果是內存將包含的內容:

使用引用和對象

請注意,該toUpperCase()方法不會更改調用它的字符串。相反,它創建一個新字符串(新對象)並返回對它的引用。

舉一個更有趣的例子怎麼樣。假設您決定將一個字符串傳遞給一個Scanner對象(以便它從該字符串中讀取值)。

例子:

String text = "10 20 40 80";
Scanner console = new Scanner(text);
int a = console.nextInt();
int b = console.nextInt();

您可以在此處詳細了解該Scanner課程的運作方式。

這就是它將全部存儲在內存中的方式:

使用引用和對象。 掃描儀類

在這種情況下,單個String對象保留在內存中,就像它原來一樣——只有對它的引用被傳遞並存儲在變量中。


5.比較對String對象的引用

最後,我們到了有趣的部分:字符串比較。

有兩個運算符可用於比較字符串變量:(==等於)和!=(不等於)。您不能使用“大於”、“小於”或“大於或等於”運算符——編譯器不允許。

但是這裡有一個有趣的細微差別:實際上存儲在字符串變量中的是什麼?沒錯:對象的地址(引用)。將比較這些地址:

String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase(); 

這是內存中的內容:

比較對 String 對象的引用

message變量text引用(存儲地址)同一個對象。但是s1s2變量存儲對非常相似但不同的對象的引用。

如果你在代碼中比較這 4 個變量,那麼你會得到以下結果:

代碼 控制台輸出
String text = "Hi";
String message = text;
String s1 = text.toUpperCase();
String s2 = text.toUpperCase();
System.out.println(text == message);
System.out.println(text == s1);
System.out.println(s1 == s2); 


true  // The addresses are equal
false // The addresses are different
false // The addresses are different