為什麼 Java 中「1000==1000」為false,而」100==100「為true?

2021-03-02 Hollis

來自: 碼農網

譯文連結:http://www.codeceo.com/article/why-java-1000-100.html

英文原文:https://dzone.com/articles/why-1000-1000-returns-false-but-100-100-returns-tr

為什麼 Java 中「1000==1000」為false,而」100==100「為true? 這是一個挺有意思的討論話題。

如果你運行下面的代碼:

Integer a = 1000, b = 1000;  
    System.out.println(a == b);//1
    Integer c = 100, d = 100;  
    System.out.println(c == d);//2

你會得到

false
true

基本知識:我們知道,如果兩個引用指向同一個對象,用==表示它們是相等的。如果兩個引用指向不同的對象,用==表示它們是不相等的,即使它們的內容相同。

因此,後面一條語句也應該是false 。

這就是它有趣的地方了。如果你看去看 Integer.java 類,你會發現有一個內部私有類,IntegerCache.java,它緩存了從-128到127之間的所有的整數對象。

所以事情就成了,所有的小整數在內部緩存,然後當我們聲明類似——

Integer c = 100;

的時候,它實際上在內部做的是:

Integer i = Integer.valueOf(100);

現在,如果我們去看valueOf()方法,我們可以看到

public static Integer valueOf(int i) {
      if (i >= IntegerCache.low && i
          return IntegerCache.cache[i + (-IntegerCache.low)];
      return new Integer(i);
    }

如果值的範圍在-128到127之間,它就從高速緩存返回實例。

所以…

Integer c = 100, d = 100;

指向了同一個對象。

這就是為什麼我們寫

System.out.println(c == d);

我們可以得到true。

現在你可能會問,為什麼這裡需要緩存?

合乎邏輯的理由是,在此範圍內的「小」整數使用率比大整數要高,因此,使用相同的底層對象是有價值的,可以減少潛在的內存佔用。

然而,通過反射API你會誤用此功能。

運行下面的代碼,享受它的魅力吧

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

      Class cache = Integer.class.getDeclaredClasses()[0]; //1
      Field myCache = cache.getDeclaredField("cache"); //2
      myCache.setAccessible(true);//3

      Integer[] newCache = (Integer[]) myCache.get(cache); //4
      newCache[132] = newCache[133]; //5

      int a = 2;
      int b = a + a;
      System.out.printf("%d + %d = %d", a, a, b); //
    }

直面Java第329期:哪個命令可以監控虛擬機各種運行狀態信息?

深入並發第013期:拓展synchronized——鎖優化

如果你喜歡本文,

請長按二維碼,關注 Hollis.

相關焦點

  • 問號臉為什麼 Java 中1000==1000 為 false而 100==100 為 true
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫為什麼 Java 中「1000==1000」為false,而」100==100「
  • 為什麼Java中1000==1000為false而100==100為true?
    如果你運行下面的代碼Integer a = 1000, b = 1000;System.out.println(a == b);System.out.println(c == d);你會得到:falsetrue基本知識:我們知道,如果兩個引用指向同一個對象,用==表示它們是相等的。
  • 為什麼Java中1000==1000為false,而100==100為true?
    如果你運行下面的代碼:Integer a = 1000, b = 1000; System.out.println(a == b);//1Integer c = 100, d = 100; >System.out.println(c == d);//2你會得到falsetrue基本知識:我們知道,如果兩個引用指向同一個對象,用 == 表示它們是相等的。
  • 漲姿勢:為什麼Java中「1000==1000」為false,而」100==100「為true?
    來源:程式設計師曉夢為什麼 Java 中「1000==1000」為false,而」100==100「為true?
  • 為什麼 Java 中 100==100 為 true?
    如果你運行下面的代碼:Integer a = 1000, b = 1000;  System.out.println(a == b);//1Integer c = 100, d = 100;  System.out.println(c == d);//2你會得到
  • 談一談Java中100==100為true?
    Integer c = 100, d = 100; System.out.println(c == d);// true }}然後輸出結果如下圖所示:原因是 在這裡聲明 的 a、b、c、d 四個變量為 Integer 對象 ,使用 == 比較的是 變量指向的對象內容地址,或者說 使用 == 號比較的是 Integer 對象的 hash 值 。
  • 四道Java基礎題,你能對幾道?
    一、==符的使用首先看一段比較有意思的代碼Integer a = 1000,b=1000; Integer c = 100,d=100; public void mRun(final String name){ new Runnable() { public void run() { System.out.println(name); } };
  • 1000不等於1000?
    100 == 1001000 == 1000通過代碼,我們可以看到,這是很簡單的「100==100」、「1000==1000」,但是為什麼一個是「true」,一個是「false」,難道真的是bug?Integer是什麼,怎么正確比較我們先看看Integer的定義,打開Integer的原始碼文件:class Ineger通過截圖中的代碼,我們可以看到,Integer是class,所以Integer是對象。我們都知道對象的「==」比較,是比較的兩引用對象的指針(內存地址)是否相等,也就是是否指向同一對象。
  • Java 版 C 語言經典 100 例(11 - 15)
    實例 111.1 題目古典問題(兔子生崽):有一對兔子,從出生後第 3 個月起每個月都生一對兔子,小兔子長到第三個月後每個月又生一對兔子,假如兔子都不死,問每個月的兔子總數為多少?(輸出前 40 個月即可)1.2 思路兔子的規律為數列 1,1,2,3,5,8,13,21....
  • 老杜帶你學Java【第十課】
    int i = 100; System.out.println(i); 什麼是字面量,怎麼理解的? 1 2 3 4 -100 100 整數型字面量 3.14 浮點型的字面量。 true false 布爾型字面量 'a' '中' 字符型字面量 "abc" "a" 字符串型的字面量 字面量其實本質上就是「數據」。
  • Java反射機制,速度提高1000倍
    原文:Java Reflection, 1000x Faster作者:aka Nicolas Laurent譯者:Teixeira10譯者註:在本文中,作者例舉了幾個版本的代碼,利用java發射機制,逐步提高代碼運行速度,同時將Github上的代碼進行展示。
  • 跟我學java編程—Java邏輯運算符
    在數學中,表示一個數值的範圍時,經常用不等式來表述。例如:假設一個數值取值範圍為0到100,設該數值為x,不等式0<x<100給出了x的取值範圍,在Java程序語言中,邏輯運算符可以實現類似數學中的不等式。下表列出了Java語言支持的邏輯運算符,表中假設布爾變量A為真,變量B為假。
  • java之小小的基礎知識點
    指的為某一種數據類型定義的名字 ,在Java中用來存放的數據而借用的空間就是變量或常量。(隱式轉換)long l = 100; --- Java中整數默認為int,所以10就是int類型,int可以自動提升為long類型,如果一個整數在int的範圍內,那麼在賦值給long類型的時候可以不加L;int i = 100;float f = i;
  • 10.Java基礎知識-If語句
    還是false如果是true就執行語句體如果是false就不執行語句體10.1.2 if語句格式1執行流程圖代碼還是false* B:如果是true,就執行語句體* C:如果是false,就不執行語句體*/publicclassIfDemo {
  • 重新認識JavaScript中的true和false
    導讀:跟其他大多數的計算機語言一樣,JavaScript也支持Boolean類型的數據,這些值可以被設置為true
  • java中的for循環
    關於java的for循環想必大家已經有所了解了,for循環是學習java常用的語句之一。for語句是最靈活也是最常用的循環結構。它的結構是這樣的,大家可以看圖。這就是for循環的基本結構。【2】求解條件表達式,若值為true,則執行循環體語句區塊,然後在執行第3步;若值為false,則跳出循環體語句。【3】求解循環過程表達式,然後轉去執行第2步。
  • 【Excel函數】True與False
    周二 · 函數    關鍵詞:true、false1語法
  • 為什麼阿里巴巴Java開發手冊強制整型包裝類對象值用equals比較?
    Integer 緩存問題分析先看下面的示例代碼,並思考該段代碼的輸出結果:通過運行代碼可以得到答案,程序輸出的結果分別為: true , false。那麼為什麼答案是這樣?我們對上述指令進行解讀:偏移為 0 的指令為:bipush 100 ,其含義是將單字節整型常量 100 推入操作數棧的棧頂;偏移為 2 的指令為:invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 表示調用一個 static
  • Java中volatile關鍵字概覽
    (1000);} catch (InterruptedException e) { e.printStackTrace();}// 將flag的值更改為true this.flag = true ;System.out.println("flag=" + flag);}}public class VolatileThreadDemo {// 測試類public static void main(String
  • 神人1000倍投福彩3D擊中100萬 上個月剛擒20萬
    國慶長假結束後,上班第一天,省福彩中心兌獎室即傳來陣陣爽朗的笑聲,旁邊來兌獎偶遇的彩民則讚不絕口:「單選,中100萬元,倍投真厲害,你應該算是今年我省3d彩民單人中取的最高獎金啊」。原來,黔南一位彩民以1000倍單選投注3D,中取了100萬元大獎。