java原语和 Package 器升级+装箱!这个进程在做什么

wtlkbnrh  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(350)

我想买1z0-815。我正在做的代码是:

public class PromotedPlusBoxed {
    public static void main(String[] args) {
       /*AUTOMATIC PROMOTION*/   
       final byte byteValue = 10;
       final short shortValue = 10;        
       final char charValue = 10;
       final int intValue = 10;
       final long longValue = 10;
       final float floatValue = 10;
       final double doubleValue = 10;
       /**/
       final Byte byteWrapperValue = 10;/*WHAT PROCESS IS HERE? A HIDDEN = (byte)10;? a performing a single boxed process.*/
       final Short shortWrapperValue = 10;/*WHAT PROCESS IS HERE? A HIDDEN = (short)10;? a performing a single boxed process.*/        
       final Character charWrapperValue = 10;/*WHAT PROCESS IS HERE? A HIDDEN = (char)10;? a performing a single boxed process.*/        
       final Integer intWrapperValue = 10;
       final Long longWrapperValue = 10;/*CAN'T PERFORM TWO-PHASE PROCESS 1). PROMOTED + 2).BOXED*/
       final Float floatWrapperValue = 10;/*CAN'T PERFORM TWO-PHASE PROCESS 1). PROMOTED + 2).BOXED*/
       final Double doubleWrapperValue = 10;/*CAN'T PERFORM TWO-PHASE PROCESS 1). PROMOTED + 2).BOXED*/
    }    
}

我也理解原语部分,我明白我不能这么做。

final Long longWrapperValue = 10;/*CAN'T PERFORM TWO-PHASE PROCESS 1). PROMOTED + 2).BOXED*/
  final Float floatWrapperValue = 10;/*CAN'T PERFORM TWO-PHASE PROCESS 1). PROMOTED + 2).BOXED*/
  final Double doubleWrapperValue = 10;/*CAN'T PERFORM TWO-PHASE PROCESS 1). PROMOTED + 2).BOXED*/

因为10是一个文本int,所以2进程首先需要升级为float、long和double,然后装箱到相应的 Package 器中。
但这是在编译。

final Byte byteWrapperValue = 10;/*WHAT PROCESS IS HERE? A HIDDEN = (byte)10;? a performing a single boxed process.*/
 final Short shortWrapperValue = 10;/*WHAT PROCESS IS HERE? A HIDDEN = (short)10;? a performing a single boxed process.*/        
 final Character charWrapperValue = 10;/*WHAT PROCESS IS HERE? A HIDDEN = (char)10;? a performing a single boxed process.*/

这里的过程是什么?10被提升为byte,然后被装箱到一个byte中,这是一个2进程,对吗?但在这个过程中,长和字节、字符、短的区别是什么。
总而言之:我想理解为什么一个literal int可以被装箱成字节、字符、短字符而不是长字符。

w8biq8rn

w8biq8rn1#

答案在于字节码。如果我们想查看它,我们必须先编译它,所以将最后一个示例改为:

final Byte byteWrapperValue = 10;
final Short shortWrapperValue = 10;
final Character charWrapperValue = 10;
final Integer intWrapperValue = 10;
final Long longWrapperValue = 10L;       <-- Added L
final Float floatWrapperValue = 10.0f;   <-- Added .0f
final Double doubleWrapperValue = 10.0d; <-- Added .0d

为了便于阅读,我删除了 LINENUMBER 以及 ASTORE (说明)
当查看字节码时,我们会看到:

L0
    BIPUSH 10
    INVOKESTATIC java/lang/Byte.valueOf (B)Ljava/lang/Byte;
   L1
    BIPUSH 10
    INVOKESTATIC java/lang/Short.valueOf (S)Ljava/lang/Short;
   L2
    BIPUSH 10
    INVOKESTATIC java/lang/Character.valueOf (C)Ljava/lang/Character;
   L3
    BIPUSH 10
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
   L4
    LDC 10
    INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
   L5
    LDC 10.0
    INVOKESTATIC java/lang/Float.valueOf (F)Ljava/lang/Float;
   L6
    LDC 10.0
    INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;

请注意,对于每个 10 直到 Integer 我们使用 BIPUSH 指令(您可以在wikipedia上看到),这意味着它将一个字节作为整数推送到堆栈上。
鉴于 10L , 10.0f 以及 10.0d 我们使用 LDC 指令,类似但不完全相同,它用于从常量池加载常量,它可以是静态的,也可以是动态的。
(后者可能是它最初没有编译的原因。)
您还可以看到编译器使用相应的 Package 类方法自动装箱推送到堆栈上的值(例如 Byte.valueOf() )
在分析一个简单的例子时:

long l = 10;
Long l2 = l;

你可以看到同样的情况,这一次它只是分两个步骤:

L0
    LDC 10 # load the value from the constant pool
   L1
    INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long; # convert the value to the wrapper type with autoboxing

更多阅读:
java自动装箱/拆箱是如何工作的?
为什么在java中使用自动装箱和取消装箱?
bipush在jvm中是如何工作的?
我很好奇ldc在jvm中是什么意思?

相关问题