一、序言
今天發現了一個很有趣的問題,在群里和朋友們討論的也比較激烈,我現在給大家闡述一下問題。
二、發現問題
上代碼。。。
package com.hzwealth.test.question; public class IntegerTest { public static void main(String[] args) { //Integer Integer a=10,b=10,c=150,d=150; System.out.println(a==b); System.out.println(c==d); System.out.println(a.equals(b)); System.out.println(c.equals(d)); //String String str=new String("AB"); String str1 ="A"; String str2 = str1+"B"; String str3="AB"; System.out.println(str==str3); System.out.println(str==str2); System.out.println(str2==str3); } }
三、解決問題
1、Integer的問題,首先我們先看上面代碼的 a==b會輸出什么呢,答案是true,這個毋庸置疑,但是c==d會輸出什么呢,答案是false,為什么呢?
(1)Integer是基本數據類型的int的引用類型,官方語言叫做裝箱類型,我們來看一下Integer的源碼
//Integer的取值 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); } 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)); } 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() {} }
從源碼我們可以看出,Integer的值為-128-127之間的時候就會自動的從Integer的緩存(IntegerCache)中去取,如果超過這個范圍就會新建一個Integer的對象。
所以a==b(a=10,b=10)為true,c==d(c=150,d=150)為false。
2、我們來看一下String的這個問題
(1)str==str3 為false,因為,str新建了一個對象,str3是常量池中的對象,所以這兩個為false。
(2)str2==str3,這個解釋引用我群友 成都-119-EbranHan-Java 的解釋:

new 了一個 StringBuilder,然后調用了append方法,對應的就是:String str2 = str1+"B";
這里還提到了字面量和引用,String str3="AB",這就是字面量,而引用就是,String str=new String("AB");我們自己定義的。
字面量 jvm 優化過,直接就扔到常量池去了。
下面是StringBuilder的toString方法,這里也是新建了一個String方法

綜上所述,str2==str3也為false。
補充:這里的“+”不是用的String 的concat的方法,而是用的是StringBuilder來寫的。而且,就算是用concat的方法也是new了一個String的對象。下面是concat的源碼:
public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }
(3)str==str2,這個也毋庸置疑的為false了,因為str是new出來的String對象,str2也是相當於new出來的一個對象。所以為false。
四、評語
以上是我根據自己查閱資料以及和群友的交流下寫出的總結,如果有不正確的地方,還望大牛指正!
