资讯专栏INFORMATION COLUMN

java拆箱装箱理解(以Long long为例)

dinfer / 2087人阅读

摘要:学过的同学或多或少都听过自动装箱拆箱下边通过代码和字节码文件加深下对自动拆箱装箱的理解为什么要有包装类型作为和基本数据类型对应的类类型存在,方便涉及到对象的操作比如泛型必须要求我们是对象数据类型自动装箱拆箱发生在什么时候自动拆箱装箱发生在代

学过Java的同学或多或少都听过自动装箱拆箱,下边通过代码和字节码文件加深下对自动拆箱装箱的理解.

1为什么要有包装类型?

作为和基本数据类型对应的类类型存在,方便涉及到对象的操作,比如泛型必须要求我们是对象数据类型.

2 自动装箱拆箱发生在什么时候?

自动拆箱装箱发生在代码编译期间.

通过例子来看下自动拆箱装箱是怎么做的:

public static void main(String[] args) { 
        Long a = 100L;
        Long b = 100L;
        long c = 100L;
        Long d = new Long(100);

        Long e = 1000L;
        Long f = 1000L;
        
        System.out.println(a == b);
        System.out.println(a == c);
        System.out.println(a == d);
        System.out.println(c == d);
        System.out.println(e == f);
    }

下面先公布答案:
true
true
false
true
false

蒙 a==b为true; 为什么 e==f就是false? a和c是怎么比较的? a和d又是什么情况?

接下来我们通过字节码文件看看到底有什么奥秘:

  public static void main(java.lang.String[]);
    Code:
       0: ldc2_w        #2                  // long 100l
       3: invokestatic  #4                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
       6: astore_1
       7: ldc2_w        #2                  // long 100l
      10: invokestatic  #4                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      13: astore_2
      14: ldc2_w        #2                  // long 100l
      17: lstore_3
      18: new           #5                  // class java/lang/Long
      21: dup
      22: ldc2_w        #2                  // long 100l
      25: invokespecial #6                  // Method java/lang/Long."":(J)V
      28: astore        5
      30: ldc2_w        #7                  // long 1000l
      33: invokestatic  #4                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      36: astore        6
      38: ldc2_w        #7                  // long 1000l
      41: invokestatic  #4                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
      44: astore        7
      46: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      49: aload_1
      50: aload_2
      51: if_acmpne     58
      54: iconst_1
      55: goto          59
      58: iconst_0
      59: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
      62: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      65: aload_1
      66: invokevirtual #11                 // Method java/lang/Long.longValue:()J
      69: lload_3
      70: lcmp
      71: ifne          78
      74: iconst_1
      75: goto          79
      78: iconst_0
      79: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
      82: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      85: aload_1
      86: aload         5
      88: if_acmpne     95
      91: iconst_1
      92: goto          96
      95: iconst_0
      96: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
      99: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
     102: lload_3
     103: aload         5
     105: invokevirtual #11                 // Method java/lang/Long.longValue:()J
     108: lcmp
     109: ifne          116
     112: iconst_1
     113: goto          117
     116: iconst_0
     117: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
     120: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
     123: aload         6
     125: aload         7
     127: if_acmpne     134
     130: iconst_1
     131: goto          135
     134: iconst_0
     135: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
     138: return
}

鬼画符?我们看下这些鬼到底什么意思.

3: invokestatic #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
意思是执行 Long 的valueof()方法 参数为基本类型 返回值为Long类型
看看Long的valueof方法

    public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }

如果传入的基本类型在-128-127之内就,就从LongCache中取数据返回给我们.看下LongCache干了啥

    private static class LongCache {
        private LongCache(){}
        static final Long cache[] = new Long[-(-128) + 127 + 1];
        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }

原来如此,-128-127就直接返回给我们chche中的数据,超出这个范围直接new一个给我们.a==b为true,e==f为false就说得通了.

  65: aload_1
  66: invokevirtual #11                 // Method java/lang/Long.longValue:()J
  69: lload_3
  70: lcmp

拿出变量a,执行Long.longValue()返回一个基本数据类型,在和c比较.看下longValue方法

   /**
     * Returns the value of this {@code Long} as a
     * {@code long} value.
     */
    public long longValue() {
        return value;
    }

这部就是两个基本数据类型比较吗.

      85: aload_1
      86: aload         5
      88: if_acmpne     95

取出a和d直接比较内存地址是否一样.铁定不一样呀.

剩下的大家可以自己看下,有不明白的可以评论问.

3 总结

自动拆箱装箱没有什么神秘的.字节码可以告诉我们很东西.如果某些概念理解不了,试着看看字节码文件.说不定会豁然开朗.

如果发现文章中有不妥之处,希望大家指出,共同进步.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75983.html

相关文章

  • 深入浅出了解“装箱拆箱

    摘要:本章部分内容从源码中解读一些自动装箱与拆箱的原理,以及会出现的一些陷阱已经性能等。例题分析我们通过几个经典的问题,来看看大家到底理解了装箱与拆箱的知识点没。 showImg(https://img-blog.csdnimg.cn/20190426221838971.gif);showImg(https://img-blog.csdnimg.cn/20190426221918208.pn...

    FullStackDeveloper 评论0 收藏0
  • int和Integer深入分析

    摘要:对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说,查找对象的元数据信息并不一定要经过对象本身,这点将在节讨论。 目录介绍 1.关于int和Integer的问题区别分析 2.Integer的值缓存的原理 2.1 Java 5 中引入缓存特性 2.2 Intege...

    Half 评论0 收藏0
  • 源码|jdk源码之Object及装箱类型分析

    摘要:作为条件变量的的不仅可以认为内嵌了一把锁,还内嵌了一个条件变量。操作条件变量的函数将当前线程在条件变量上阻塞,一般是为了等待其他线程的某件事情执行完成。其它装箱类其它装箱类的代码这里就不分析了。重点关注下各装箱类的缓存范围。 jdk源码读到现在这里,重要的集合类也读了一部分了。集合类再往下读的话,就要涉及到两个方向。第一,是比较典型的但是不常用的数据结构,这部分我准备将数据结构复习、回...

    VioletJack 评论0 收藏0
  • Java 性能要点:自动装箱/ 拆箱 (Autoboxing / Unboxing)

    摘要:文章主要介绍通过改进就已存在的骨灰级特性大幅度提高应用性能。在继续解释造成差异的细节之前,让我们仔细回味一下中的这两个概念自动装箱与拆箱。 【编者按】本文作者为 Ali Kemal TASCI,最早于2016年4月9日发布于DZONE社区。文章主要介绍通过改进 Java 1.5 就已存在的骨灰级特性大幅度提高应用性能。 本文系 OneAPM 工程师编译呈现,以下为正文。 如果我告诉你:...

    Jackwoo 评论0 收藏0
  • 深入浅出 Java 中的包装类

    摘要:前阵子,我们分享了中的基本数据类型转换这篇文章,对许多粉丝还是有带来帮助的,今天讲一下包装类的的由来,及自动装箱拆箱的概念和原理。下面是基本数据类型与对应的包装类型。 showImg(https://segmentfault.com/img/remote/1460000016537706); 前阵子,我们分享了《Java中的基本数据类型转换》这篇文章,对许多粉丝还是有带来帮助的,今天讲...

    ytwman 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<