Java基礎精選,你答對了幾道?
沒有技術深度是大多程式設計師的一種常態。
但是當你成為一個資深的工程師的時候,很多公司並不希望你還是那樣平庸,沒有深度。雖然你會納悶,我就算有深度你們也不一定用得上呀?然而到了這個級別的人需求量並不像初中級開發那麼多,公司更理性和穩妥的做法是選擇有深度的人,不是嗎?
Integer比較
看下面這段有意思的程式碼,對數字比較敏感的小夥伴有沒有發現異常?
public static void main(String[] args) { Integer a = 128,b=128; Integer c = 127,d=127; System.out.println(a==b); System.out.println(c==d); }
如果你的回答是false,false,可能你有一定的基礎,知道Integer是一個封裝類。當然如果你的答案是true,true的話,也在一定的認知範圍之內,但是基礎知識掌握的不夠好。
好了,我們執行main方法,正確答案應該是false,true。前幾年這道題出現在很多面試題中,當然你也會說了,我會做專案就ok了,用到查就是了,何必要知道,這我沒話說。
其實當我們給一個Integer物件賦一個int值的時候,會呼叫Integer類的靜態方法valueOf,讓我們看下原始碼是怎麼實現的。
IntegerCache方法有明確的註釋,快取範圍,如何修改等等。
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the -XX:AutoBoxCacheMax=<size> option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
神奇不神奇,其實程式碼描述的很清晰,如果整型字面量的值介於-128到127之間,就不會new一個新的Integer物件,而是直接引用常量池中的Integer物件,所以上面的執行結果是a==b=false,而c==d=true。
String比較
接下來這道題,相對來說應該比較簡單了。
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
}
小夥伴們看了是不是很熟悉?可能有的人一眼就掃出了答案true,false。當然沒有掃出正確答案的小夥伴們也不要氣餒,下面跟大家分析分析為毛是這麼一個答案。
按照==的語法來看, 首先s1、s2、s3是三個不同的物件,常理來說,輸出都會是false。然而程式的執行結果確實true、false。第二個輸出false可以理解,第一個輸出true就又讓人費解了。
我們知道一些基本型別的變數和物件的引用變數都是在函式的棧記憶體中分配,而堆記憶體中則存放new 出來的物件和陣列。然而除此之外還有一塊區域叫做常量池。
像我們通常想String s1 = "abc";這樣申明的字串物件,其值就是儲存在常量池中。當我們建立String s1 = "abc"這樣一個物件之後,"abc"就儲存到了常量池(也可叫做字串池)中。
當我們建立引用String s2 = "abc" 的時候,Java底層會優先在常量池中查詢是否存在"abc",如果存在則讓s2指向這個值,不會重新建立,如果常量池中沒有則建立並新增的池中。這就是為什麼答案是true 和false的原因。
Integer與int比較
public static void main(String[] args) {
Integer a = new Integer(128);
int b = 128;
Integer c = new Integer(6);
Integer d = new Integer(6);
System.out.println(a == b);
System.out.println(c == d);
}
相信又有不少小夥伴懵比了吧,ture還是false?還是直接公佈答案吧,true,false。
c == d=false,我覺得沒什麼好說的,可能有的小夥伴要問了不是-128-127被快取起來了麼?但是我們這裡的Integer是new出來的,並不是用的快取,所以結果是false。
a == b=true,大家注意一下這裡的b是int型別,當int和Integer做==比較的時候,Integer型別會自動拆箱,也就是把Integer轉成int型別,所以這裡進行比較的是int型別的值,所以結果即為true。