設有兩個賦值語句:
a = Integer.parseInt("1024");
b = Integer.valueOf("1024").intValue();
這裏的a和b都是整數類型變量並且他們的值相等。
intValue()是把Integer對象類型變成int的基礎數據類型; parseInt()是把String變成int的基礎數據類型; Valueof()是把String轉化成Integer對象類型;(現在JDK版本支持自動裝箱拆箱了),在這串代碼中:parseInt得到的是基礎數據類型int,valueof得到的是裝箱數據類型Integer,然後再通過valueInt轉換成int,所以得到這個結果。
現在對於包裝類和基本數據的比較總結如下:
Integer n1 = new Integer(1000);
Integer n2 = new Integer(1000);
int value =1000;
String a = "1000";
Integer n3=2000,n4=2000;
Integer n5=47,n6=47;
int n1_int = n1.intValue();
Integer a_integer = Integer.valueOf(a);
System.out.println(value==n1); //true
System.out.println(n1_int==n2); //true 把n1轉成了n1_int爲int型,和Integer的n2比較拆箱,比較值
System.out.println(n1 == n2); //false 引用類型比較的是地址
System.out.println(n3==n4); //false
System.out.println(n5==n6); //true
System.out.println(n1.equals(n2)); //true equals內部都轉換成了基本數據類型
System.out.println(a_integer.equals(n2)); //true
-
System.out.println(valuen1)
輸出是true,因爲value是Int型,n1是Integer型,兩者在進行比較的時候,Integer會自動拆箱爲int型,而int屬於基本數據類型,基本數據類型的比較是比較的值,因此都是1000爲true。 -
System.out.println(n1_intn2)
輸出是true,因爲n1_int是把n1轉成了int類型(intValue方法是把Integer類型轉成int類型),所以還是變成了①的情況int和Integer的比較,拆箱後變成值得比較爲true。 -
System.out.println(n1n2)
輸出是false,因爲n1和n2都是Integer是包裝類型,且n1和n2都new了一個對象,則聲明是在棧中,而對象在堆中,這個時候包裝類型進行比較比較的就是地址,而n1和n2這是兩個在java堆中的不同的對象,所以返回false。 -
System.out.println(n3n4)
輸出是false,因爲這裏n3和n4還是對象(類比String a = “abc”),n3和n4在虛擬機棧的局部變量表中,但是他們的2000是在常量池裏面的兩個不同的常量,所以n3和n4的比較比較的是地址,因此返回的是false。 -
System.out.println(n5n6)
輸出的是true,雖然n5和n6都是對象,但是因爲他們對應的值是[-128,127]之間,所以當n5創立好後開始創建n6的時候,他會去緩存中找對應的值,然後把這個值給n6,所以這裏是同一個地址,因此返回的是true。 -
System.out.println(n1.equals(n2))
輸出的是true。在講爲什麼之前先說一下對於Object的equals的源碼:
public boolean equals(Object obj) {
return (this == obj);
}
我們可以看到,對於object類型他的equals其實就是號比較,的比較規則是:如果傳入的是引用類型,則比較的是地址,如果傳入的是基本數據類型,則比較的是值。
而我們的Integer的equals對上面的equals進行了重寫,當然String也對上面的equals進行了重寫,下面給出Integer的重寫的代碼:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
這裏的value是我們的n1的值。他會做以下幾件事:
①首先他會判斷我們括號的n2是不是Integer類型(或者是子類),如果是則進入if,不是就返回false。
②接着讓value和((Integer)obj).intValue()進行比較,value是我們n1的值,是int類型(源碼中是private final int value),右邊是把我們傳參傳進來的obj(n2)轉成Integer類型,然後調用intValue()方法把Integer類型轉成int類型。
所以我們的equals方法其實實質性的比較是比較兩個int基本數據類型,也就是值的比較,因此這裏n1.equals(n2)中n1和n2值都是1000,返回true。
如果是String類型,下面我們給出String類型重寫的equals:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
他主要完成了以下幾件事:
①先比較我們的調用者對象和傳入的參數的anObject對象是不是同一個地址(==),如果是則直接返回true。這個相當於就是自己和自己進行equals了,返回當然就是true。
②然後判斷我們傳入的anObject對象是不是String類型或者是String類型的子類,如果是則進入if,對調用者的值(也就是字符串)和參數的值(anObject對象的字符串)進行挨個比較,如果都相等則返回true,否則返回false。
所以這裏對於String,也相當於是值得比較。
- System.out.println(a_integer.equals(n2))
返回的是true,原理和上面的⑥