Ответ лежит в байт-коде. Однако, если мы хотим просмотреть его, сначала нужно его скомпилировать, поэтому замените последний пример следующим образом:
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
, которая похожа, но не совсем точно, она используется для загрузки константы из пула констант, это может быть stati c или dynamic c.
( Последнее может быть причиной того, что он не компилируется в первую очередь. )
Вы также видите, что компилятор автоматически помещает значения, помещенные в стек с соответствующим методом класса Wrapper. (например, 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
Больше чтения: