91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java Integer等號判斷怎么使用

發布時間:2021-12-18 11:23:01 來源:億速云 閱讀:265 作者:iii 欄目:大數據

這篇文章主要講解了“java Integer等號判斷怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“java Integer等號判斷怎么使用”吧!


面試題

先來看一道常見的面試題,對照上面的結論,看看能夠答對幾項。下面代碼中打印結果為true的有幾項?

@Test
public void test2() {
	Integer i1 = 64;
	int i2 = 64;

	Integer i3 = Integer.valueOf(64);
	Integer i4 = new Integer(64);

	Integer i5 = 256;
	Integer i6 = Integer.valueOf(256);

	System.out.println("A:" + (i1 == i2));
	System.out.println("B:" + (i1 == i3));
	System.out.println("C:" + (i3 == i4));
	System.out.println("D:" + (i2 == i4));
	System.out.println("E:" + (i3.equals(i4)));
	System.out.println("F:" + (i5 == i6));
}

執行上面的程序,打印結果為:

A:true
B:true
C:false
D:true
E:true
F:false

只有C和F項打印為false。你是否疑惑為什么i1等于i2,i1等于i3,i2等于i4,都為true,那么根據等號的傳遞性,i3應該等于i4啊?

為什么i1和i3相等,但i5和i6卻不相等呢?

先保留疑問。下面,我們從int及Integer在JVM中的存儲結構來進行分析。掌握了底層存儲結構,你會發現無論題面如何變化,都萬變不離其宗。

變量在JVM中的存儲

在徹底弄清楚上問題之前,我們先來了解一下基礎類型變量、引用類型變量在JVM中的存儲。

通常變量分為局部變量和全局(成員)變量。局部變量是聲明在方法內的變量;全局變量是聲明在類中的成員變量。

基礎類型的變量和值在分配的時候是在一起的,都在方法區或棧內存或堆內存。而引用類型的變量和值不一定在一起。

局部變量存儲在方法棧中

當方法被調用時,Java虛擬機都同步創建一個棧幀,局部變量便存儲在其中。當方法結束虛擬機會釋放方法棧,其中聲明的變量隨著棧幀的銷毀而結束。因此,局部變量只能在方法中有效。

此過程中,基礎類型和引用類型的存儲有所區別:

(1)基本類型:變量和對應的值存放在JAVA虛擬機的棧中;

(2)引用類型:變量存儲在棧中,是一個內存地址,該地址值指向堆中的對象。

java Integer等號判斷怎么使用

棧屬于線程私有的空間,局部變量的生命周期和作用域一般都很短,為了提高gc效率,所以沒必要放在堆里面。

全局變量存儲在堆中

全局變量存放在堆中,不會隨著方法結束而銷毀。同樣在類中聲明的變量也是分為基本類型和引用類型。

(1)基本類型:變量名和值存放在堆內存中。

(2)引用類型:變量是一個引用地址,該地址指向所引用的對象。此時,變量和對象都在堆中。

舉個簡單的例子,如下代碼:

public class Person {
	int age = 10;
	String name = "Tom";
}

對應的age和name的存儲結構如下圖: java Integer等號判斷怎么使用

結合上面的理論,我們通過一段代碼來分析一下各種類型所存儲的位置。

public class DemoTest {

 int y; // 變量和值均在堆上
 
 public static void main(String[] args) {

     int x = 1; // 變量和值分配在棧上
     
     String name = new String("cat"); // 數據在堆上,name變量的指針在棧上
     
     String address = "北京"; // 數據在常量池,屬于堆空間,指針在棧上
     
     Integer price = 4; // 包裝類型為引用類型,編譯時會自動裝拆箱,數據在堆上,指針在棧
 }
}

基礎類型的棧內存儲

通過上面的實例,基本了解了不同類型的值的內存分配情況。下面我們重點討論局部變量。

下面先來看看在同一棧幀中,針對int類型的處理模式。

int a = 3;
int b = 3;

上述代碼中a和b均為局部變量。假設編譯器先處理int a=3,此時會在棧中創建a的引用變量,然后查找棧中是否存在3這個值,如果沒有就將3存放進來,然后將a指向3。

接著處理int b=3,創建完b的引用變量后,同樣進行查找。因為在棧中已經有3這個值,便將b直接指向3。

此時,a與b同時指向3這個值,自然是相等的。

關于基礎類型與引用類型的底層比較,可稍微延伸一下:對于“==”操作符號,JVM會根據其兩邊相互比較的操作數的類型,在編譯時生成不同的指令:

(1)對于boolean,byte、short、int、long這種整形操作數會生成if_icmpne指令。該指令用于比較整形數值是否相等。

(2)如果操作數是對象的話,編譯器則會生成if_acmpne指令,與if_icmpne相比將i(int)改成了a(object reference)。

回歸正題

學習了上面的底層理論知識,我們基本上可以得出如下結論:(1)兩個int類型比較,直接使用雙等號即可;(2)int的包裝類Integer對象比較時,使用equals進行比較即可。

但上面的結果只能說E項目是正確的。其比較項還涉及到整形的裝箱拆箱操作、Integer的緩存。我們下面逐一分析。

不同創建形式的比較

先看Integer的初始化,根據Integer的內部實現,創建Integer有三種,分別是:

Integer a = new Integer(1); //創建新的類

Integer b = Integer.valueOf(2);  

Integer c = 3; //自動包裝,會調用valueOf方法

其中直接賦值底層會調用valueOf方法進行操作的,因此這兩種操作效果是一樣的。

因為通過new和valueOf創建的是完全兩個對象,那么針對題目中的C項,直接比較兩個對象的引用肯定是不相等的,因此結果為false。但B項為什么為true呢?后面我們會講到。

比較中的拆箱

在題目中,我們發現A、D都為true,而且它們的比較格式都是基礎類型與包裝類型的對比。

針對這種形式的對比,包裝類型會進行自動拆箱,變成基礎類型(int)。很顯然,結果是相等的。

Integer的緩存

為什么i1和i3相等,但i5和i6卻不相等呢?對應題目中的B和G項。這里就涉及到Integer的緩存機制。

我們上面已經知道,Integer直接賦值和valueOf是等效的,那先看一下valueOf及相關的方法。

public static Integer valueOf(int i) {
    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) {
                try {
                    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);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

valueOf方法判斷數字是否大于low(-128)并且小于high(127),如果滿足條件,則直接從IntegerCache中返回對應數字。

IntegerCache用于存儲一些常用的數,防止重復創建,在Integer類裝入內存時通過靜態代碼進行初始化。

所以只要是用valueOf或者Integer直接賦值的方式創建的對象,其值小于127且大于-128的,無論對其進行==比較還是equals 比較,都是true。

上面的源碼及原理也解釋了阿里Java開發手冊中所說明的原因。

為什么equals可以規避問題

對于不滿足-128到127范圍的數,無論通過什么方式創建,都會創建一個新的對象,只能通過equals進行比較。接下來我們再看看equals方法。

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

equals實現比較簡單,先比較類型是否一致,如果不一致,直接返回false;否則,再比較兩者的值,相同則返回true。

感謝各位的閱讀,以上就是“java Integer等號判斷怎么使用”的內容了,經過本文的學習后,相信大家對java Integer等號判斷怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

安平县| 昆明市| 建水县| 长沙县| 房产| 新民市| 繁昌县| 商水县| 镇平县| 舞钢市| 义乌市| 金寨县| 玉屏| 勐海县| 庆安县| 开原市| 洛川县| 大余县| 扎兰屯市| 灵山县| 化隆| 新邵县| 奎屯市| 定远县| 灵川县| 沧源| 友谊县| 安阳县| 惠东县| 乃东县| 九龙城区| 鄂尔多斯市| 樟树市| 兴国县| 荥阳市| 巫山县| 叙永县| 平原县| 勃利县| 陇南市| 连州市|