2

I'm trying to go for 1Z0-815. This code I was making:

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*/
    }    
}

I understand the primitives part also, and I understand that I cannot do this.

  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*/

Because 10 is a literal int a 2 process needs to made first promoted to float,long and double and later boxed to the respective wrappers.

But this is compiling.

 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.*/    

What is the process here? 10 is getting promoted to byte and later boxed into a Byte is that a 2 process right? but is not working for a Long what is the diff between Long and Byte,Character,Short in this process.

In summary: I want to understand why can a literal int can be boxed into a Byte,Character,Short and not into a Long.

halfer
  • 18,701
  • 13
  • 79
  • 158
chiperortiz
  • 4,313
  • 6
  • 40
  • 68
  • I want to understand why can a literal int can be boxed into a Byte,Character,Short and not into a Long. Tha'ts all. – chiperortiz Feb 13 '20 at 20:00
  • 1
    Related: [How java auto boxing/unboxing works](https://stackoverflow.com/questions/22648627/how-java-auto-boxing-unboxing-works) and [Why do we use autoboxing and unboxing in Java?](https://stackoverflow.com/questions/27647407/why-do-we-use-autoboxing-and-unboxing-in-java) – Lino Feb 13 '20 at 20:08

1 Answers1

1

The answer lies in the bytecode. If we want to view it though, we have to make it compile first, so change your last example to this:

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)

Then when viewing the bytecode we see this:

   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;

Note that for every 10 up until Integer we use the BIPUSH instruction (you can see all at wikipedia) which means that it pushes a byte as an integer onto the stack.

Whereas with 10L, 10.0f and 10.0d we use the LDC instruction, which is similar but not exactly, it is used to load a constant from the constant pool, it may be static or dynamic.

(The later may be the cause that it doesn't compile in the first place.)

You also see that the compiler autoboxes the values pushed onto the stack with the corresponding Wrapper-class method. (e.g. Byte.valueOf())

Also when analyzing a simple example:

long l = 10;
Long l2 = l;

You can see the same, this time it just makes it in two steps:

   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

More reading:

Lino
  • 17,873
  • 4
  • 40
  • 57