640?wx_fmt=gif

640?wx_fmt=jpeg

作者 | 明明如月小角落

责编 | 屠敏

出品 | CSDN 博客

 

640?wx_fmt=png

背景

 

下面给出一个例子,问输出的结果是多少:

 

public class IntTest {

    public static void main(String[] args) {
        Integer a = 100, b = 100, c = 150, d = 150;
        System.out.println(a == b);
        System.out.println(c == d);
    }
}

很多新手可能非常犹豫,有一些经验的同学可以回答出"标准"答案。

问原因则随口就说”Integer缓存了-128到127之间的整数对象“,为什么会缓存?还有其他答案?可能就不知道了。

what??? 难道这不是标准答案?还想咋地?

 

640?wx_fmt=png

分析

 

运行

想知道答案很容易,直接运行,结果是 true ,false。

源码法

直接看源码, 我们知道声明整数时,会通过 java.lang.Integer#valueOf(int) 构造(不信可以断点)。

 

 /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

通过源码和注释可以看到 如果是-128到127之间的整数,则会使用整数缓存对象,否则就new一个整形对象。

因此第一个是true,第二个是false。

反汇编

前面讲到了,用到了 再问一个问题  为什么调用了   java.lang.Integer#valueOf(int) ?

我们直接反汇编:javap -c IntTest

 

Compiled from "IntTest.java"
public class com.chujianyun.common.int_test.IntTest {
  public com.chujianyun.common.int_test.IntTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: bipush        100
       2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       5: astore_1
       6: bipush        100
       8: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: astore_2
      12: sipush        150
      15: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      18: astore_3
      19: sipush        150
      22: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      25: astore        4
      27: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      30: aload_1
      31: aload_2
      32: if_acmpne     39
      35: iconst_1
      36: goto          40
      39: iconst_0
      40: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
      43: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      46: aload_3
      47: aload         4
      49: if_acmpne     56
      52: iconst_1
      53: goto          57
      56: iconst_0
      57: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
      60: return
}

很明显四个Integer对象的构造使用了java/lang/Integer.valueOf函数。

那么除了上面的回答还有哪些更完善的回答呢?

我们继续看 java.lang.Integer.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 {@code -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[];

// 省略
}

可以看到可以通过设置虚拟机参数:XX:AutoBoxCacheMax=<size>或 -Djava.lang.Integer.IntegerCache.high=<high>

来设置缓存范围的最大值(包含)。

因此如果将最大值设置为150或者以上。则程序的答案就是 true, true。

另外缓存是 《Java语言规范》的要求,具体可以去语言规范里看。

这里提供手册的下载地址:https://docs.oracle.com/javase/specs/index.html

640?wx_fmt=png

640?wx_fmt=png

 

640?wx_fmt=png

总结

 

我们看一些文章的时候,不要止步于文章给出的标准答案,否则总是“背”文章,印象不深刻。

最好自己能够动手DEMO一下,能过亲自去源码里看一看,能够有自己的思考,才能学得更多。

研究Java相关问题除了多看源码外,还可以多反汇编,不要惧怕,一回生两回熟,慢慢就会乐此不疲。

总之希望本文能够给大家一些启发,养成读源码,反汇编等好的学习方法,更快进阶。

声明:本文为 CSDN 博主「明明如月小角落」的原创文章,版权归作者所有,如需转载请联系作者。

原文:https://blog.csdn.net/w605283073/article/details/98475057

【END】

Google:这三个原因让我们死心塌地爱上Python!

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

640?wx_fmt=jpeg

热 文 推 荐 

☞ 快手百度 4.34 亿美元投资知乎;腾讯回应“push团队全部被开”;Android Q Beta 6 发布 | 极客头条

Facebook 研发可穿戴脑机接口,读心术成真?

深度学习图像算法在内容安全领域的应用实践和优化

《乐队的夏天》很酷?程序员式的摇滚才燃爆了!

☞屌!小哥用 12 个月的时间开发了12款比特币Dapp, 0.00000001 BTC就能玩区块链版"蚂蚁庄园"

再见!微服务

☞没看完这11 条,别说你精通Python装饰器

第四范式戴文渊:AI落地,为什么不能照搬教科书?

边看边用!这本 Python 3.6 的书火爆了 IT 圈!

640?wx_fmt=gif点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

 

 

 

 

 

640?wx_fmt=png

你点的每个“在看”,我都认真当成了喜欢640?wx_fmt=png

Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐