首先明確一點:
「==」 永遠是在比較位址,而equals是比較內容的值。當我們書寫這樣的**:
int a = 10;
int b = 10;
jvm 其實是在棧(棧幀中的操作棧?)中查詢 3 這個常量,如已經存在了,變數 a 的引用就指向存放 3 的位址,如果沒有,就建立乙個。因此給基本資料型別的變數賦值時,若它們的值相等,那它們在記憶體中的位址也相等。a == b
看似是值的比較,實際上也是常量位址的比較。
以integer
舉例,看一下**:
integer n1 = 100;
integer n2 = 100;
integer n22 = integer.valueof(100);
integer n222 = new integer(100);
integer n3 = 1000;
integer n4 = 1000;
system.out.println(n1==n2); // true
system.out.println(n1==n22); // true
system.out.println(n1==n222); // false
system.out.println(n3==n4); // false
從輸出結果可以看到,直接賦值 和使用valueof()
賦值的方式,兩個變數的比較結果都是true
,但是new
乙個新的物件來比較就是false
。這是為什麼呢?
從自動拆裝箱機制中可以了解到,直接給包裝類賦值其實就是執行了valueof()
方法,然後我們又知道==
比較的是兩個物件的引用位址,這說明直接賦值和使用valueof()
方法沒有改變物件的引用位址,因此比較結果是true
。而new
乙個新物件肯定有不同的位址,所以比較結果是false
。看一下integer的原始碼:
private
static
class
integercache
high = h;
cache = new integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new integer(j++);
...省略
}}public
static integer valueof(int i)
這個integercache
是integer
的靜態內部類(巢狀類),而cahce
是乙個陣列,作為乙個常量池,順序儲存了最小值low(-128)
到最大值high(127)
之間的所有整數的integer
物件。從原始碼中可以看出,當i
的值在 [ low, high ] 範圍內時,直接返回陣列中對應值的位址,否則就建立乙個新的物件。
因此前面n1==n2
的結果是true
,而n3==n4
的結果是false
,因為n1
、n2
都是引用陣列cache
中100這個值的位址,而1000超過了範圍,因此建立了新的物件,引用的位址就不一樣了。
有常量池設定的包裝類及其範圍有:
包裝類常量範圍
byte
[ -128, 127 ]
short
[ -128, 127 ]
integer
[ -128, 127 ]
long
[ -128, 127 ]
character
[ 0, 127 ]
而float
、double
因為值是不連續的,所以不設定常量池,boolean
也沒必要設定常量池。
string
類也維護有緩衝池,給物件賦值時,會把字串加入到緩衝池中,下次賦值時,若緩衝池中含有相同內容的字串物件,則直接指向它在緩衝池中的位址。
string s1 = "hello";
string s2 = "hello";
system.out.println(s1==s2); // true
string s3 = "hel";
string s4 = "lo";
string s5 = "hel" + "lo";
string s6 = s4 + s5;
system.out.println(s1==s5); // true
system.out.println(s1==s6); // false
在給s1
賦值後,物件被加入到string
類的緩衝池中,因此在給s2
賦值時,s2
的引用直接指向緩衝池中內容為」hello」的物件位址,因此s1==s2
的結果自然就是true
了。
編譯階段編譯器會把兩個字串合成乙個,因此s1==s5
的結果也是true
。但編譯器不會把兩個物件合併,因此s1==s6
的結果是false
,以為它們的引用位址不相同。
java中的物件比較
public class intergererror private static boolean compare integer num1,integer num2 你的答案是什麼,返回一定是true?哈哈,再思考一下。這段 的返回值為false,這就有些不明白了,為什麼會這樣,既然用的是或,那不...
java 集合類中的物件如何比較
1 list 集合 被比較的物件要重寫equals 方法,呼叫list中contains 方法,就是用equals 方法比較的.list 集合 允許重複元素,允許空值 2 hashset集合 不允許重複元素,允許空值 被比較的物件要重寫hashcode 方法和重寫equals 方法,兩個都要.3 t...
java中物件集合的比較與排序
現種方式。一是物件本身直接實現comparable介面 class student implements comparable 另一種是借助比較器物件,這個比較器物件針對指定的類來定義。並實現comparator介面 class student 最後借助conections.sort 或arrayl...