Java Примитивы и Обертки повышены + в штучной упаковке! Какой процесс делает JVM здесь - PullRequest
2 голосов
/ 13 февраля 2020

Я пытаюсь go для 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 процесса to made вначале повышен до 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, Короткий, а не длинный.

1 Ответ

1 голос
/ 13 февраля 2020

Ответ лежит в байт-коде. Однако, если мы хотим просмотреть его, сначала нужно его скомпилировать, поэтому замените последний пример следующим образом:

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

Больше чтения:

...