Java 推广 Primitives 和 Wrappers + 盒装!什么进程在这里做 JVM
Java Primitives and Wrappers promoted + boxed! What process is doing JVM here
我正在尝试购买 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,然后装箱到各自的包装器。
但这是编译。
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 被提升为字节,然后装箱为字节,这是一个 2 进程吗?但不适用于 Long 在此过程中,Long 和 Byte、Character、Short 之间的区别是什么。
总而言之:我想了解为什么文字 int 可以装箱成 Byte,Character,Short 而不是 Long。
答案就在字节码中。如果我们想查看它,我们必须先编译它,所以将您的最后一个示例更改为:
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
for the sake of readability I removed the LINENUMBER
and ASTORE
instructions)
然后在查看字节码时我们会看到:
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;
请注意,对于 Integer
之前的每个 10
,我们都使用 BIPUSH
指令(您可以在 wikipedia 处看到所有指令),这意味着它会推送一个 字节作为一个整数到堆栈上。
而对于 10L
、10.0f
和 10.0d
我们使用 LDC
指令,它类似但不完全相同,它用于加载 constant来自常量池,可以是静态的也可以是动态的。
(后面可能是当初编译不通过的原因)
您还看到编译器使用相应的 Wrapper-class 方法自动装箱压入堆栈的值。 (例如 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
更多阅读:
- How java auto boxing/unboxing works?
- Why do we use autoboxing and unboxing in Java?
- How does bipush work in JVM?
我正在尝试购买 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,然后装箱到各自的包装器。
但这是编译。
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 被提升为字节,然后装箱为字节,这是一个 2 进程吗?但不适用于 Long 在此过程中,Long 和 Byte、Character、Short 之间的区别是什么。
总而言之:我想了解为什么文字 int 可以装箱成 Byte,Character,Short 而不是 Long。
答案就在字节码中。如果我们想查看它,我们必须先编译它,所以将您的最后一个示例更改为:
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
for the sake of readability I removed the
LINENUMBER
andASTORE
instructions)
然后在查看字节码时我们会看到:
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;
请注意,对于 Integer
之前的每个 10
,我们都使用 BIPUSH
指令(您可以在 wikipedia 处看到所有指令),这意味着它会推送一个 字节作为一个整数到堆栈上。
而对于 10L
、10.0f
和 10.0d
我们使用 LDC
指令,它类似但不完全相同,它用于加载 constant来自常量池,可以是静态的也可以是动态的。
(后面可能是当初编译不通过的原因)
您还看到编译器使用相应的 Wrapper-class 方法自动装箱压入堆栈的值。 (例如 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
更多阅读:
- How java auto boxing/unboxing works?
- Why do we use autoboxing and unboxing in Java?
- How does bipush work in JVM?