About Question enthuware.ocpjp.v21.2.3343 :

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
n199a_
Posts: 8
Joined: Wed Jan 08, 2025 9:43 am
Contact:

About Question enthuware.ocpjp.v21.2.3343 :

Post by n199a_ »

Autoboxing

I encountered a very interesting question where it was required to identify examples of autoboxing:

Code: Select all

Long l = Long.valueOf(200)
Integer i = 10;
Integer getValue() { return 2; }
Long getValue() { return 2; }
System.out.println(2 + "");
Initially, I did not select the option

Code: Select all

System.out.println(2 + "");
, but the author gave the following explanation:
Whenever only one operand of the + operator is a String, the other operand is converted into a String using a string conversion. If the other operand is a numeric primitive type, then it is first converted to a reference type using the boxing conversion and then the boxed reference is used to produce a String. Thus, in this case, 2 will first be boxed into an Integer object and then the Integer object will be used to produce the String "2", which will then be concatenated with "". Hence, this is also a valid example where autoboxing occurs. Note that, no autoboxing occurs in System.out.println(2); because the println(int) method is invoked in this case.
This explanation means that

Code: Select all

2
is first boxed into an

Code: Select all

Integer
wrapper, and then the

Code: Select all

Integer
is converted into a

Code: Select all

String
.

To confirm or disprove this statement, we need to write code that contains all of the above cases, compile the class using the command:

Code: Select all

$ javac Test.java
Then disassemble it using the javap command (https://www.ibm.com/docs/de/i/7.3?topic=programs-javap):

Code: Select all

$ javap -c Test
Preparing the class with the answer options:

Code: Select all

public class Main {
    public static void main(String[] args) {
        Long l = Long.valueOf(200);
        Integer i = 10;
        System.out.println(2 + "string");

        // Not compile:
        // String s = (String) (1 + 2);
    }

    static Integer getInteger() {
        return 2;
    }

    static Long getLong() {
        // Not compile:
        // return 2;
        return 2L;
    }
}
Disassembler output:

Code: Select all

PS W:\testspace\untitled> javap -c W:\testspace\untitled\build\classes\java\main\l3\Main.class
Compiled from "Main.java"
public class l3.Main {
  public l3.Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc2_w        #7                  // long 200l
       3: invokestatic  #9                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
       6: astore_1
       7: bipush        10
       9: invokestatic  #15                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      12: astore_2
      13: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
      16: ldc           #26                 // String 2string
      18: invokevirtual #28                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      21: return

  static java.lang.Integer getInteger();
    Code:
       0: iconst_2
       1: invokestatic  #15                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       4: areturn

  static java.lang.Long getLong();
    Code:
       0: ldc2_w        #34                 // long 2l
       3: invokestatic  #9                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
       6: areturn
}
PS W:\testspace\untitled>
Your code and the corresponding bytecode demonstrate several important things about the use of primitive types, wrapper objects, and conversions in Java.

1. Initializing the Long variable:

-

Code: Select all

ldc2_w #7
loads the value

Code: Select all

200L
(type

Code: Select all

long
) from the constant pool.
-

Code: Select all

invokestatic #9
calls the static method

Code: Select all

Long.valueOf(long)
to create a

Code: Select all

Long
object.
-

Code: Select all

astore_1
stores the reference to the

Code: Select all

Long
object in a local variable.

2. Initializing the Integer variable:

-

Code: Select all

bipush 10
pushes the integer value

Code: Select all

10
onto the stack.
-

Code: Select all

invokestatic #15
calls the static method

Code: Select all

Integer.valueOf(int)
to create an

Code: Select all

Integer
object.
-

Code: Select all

astore_2
stores the reference to the

Code: Select all

Integer
object in a local variable.

3. String concatenation and printing:

-

Code: Select all

getstatic #20
loads the static field

Code: Select all

System.out
, which is an instance of

Code: Select all

PrintStream
.
-

Code: Select all

ldc #26
loads the string

Code: Select all

"2string"
from the string pool.
-

Code: Select all

invokevirtual #28
calls the method

Code: Select all

println(String)
to print the string.

4. Returning an Integer from a method:

-

Code: Select all

iconst_2
pushes the value

Code: Select all

2
onto the stack.
-

Code: Select all

invokestatic #15
calls

Code: Select all

Integer.valueOf(int)
to convert

Code: Select all

int
to

Code: Select all

Integer
.
-

Code: Select all

areturn
returns the object reference.

5. Returning a Long from a method:

-

Code: Select all

ldc2_w #34
loads the value

Code: Select all

2L
(type

Code: Select all

long
).
-

Code: Select all

invokestatic #9
calls

Code: Select all

Long.valueOf(long)
to convert

Code: Select all

long
to

Code: Select all

Long
.
-

Code: Select all

areturn
returns the object reference.

These examples show how Java uses

Code: Select all

valueOf
methods for autoboxing of primitive values into their corresponding wrapper classes.

It’s also clear that the concatenation of

Code: Select all

2 + "string"
is performed at compile time, so no actual boxing or runtime conversion happens there. The compiler directly inserts the

Code: Select all

"2string"
literal into the bytecode using

Code: Select all

ldc
, which means this is not a case of runtime autoboxing.

In other words, converting a number to a string or joining it with a string (concatenation) is not autoboxing, because

Code: Select all

String
is not a wrapper class for primitive types.

admin
Site Admin
Posts: 10384
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v21.2.3343 :

Post by admin »

What you have described is correct but you are overlooking the fact that it is a compiler optimization technique and is not guaranteed. Here is what section 15.18.1 of JLS 21 says:
If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run time.
and further in the same section, it clearly says:
For primitive types, an implementation may also optimize away the creation of a wrapper object by converting directly from a primitive type to a string
String conversion is explained In section 5.1.11 and there it says:
A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression.
So, to summarize, theoretically, it is autoboxing but behind the scene the compiler my implement is differently. A JVM is free to not optimize it this way.

Post Reply

Who is online

Users browsing this forum: No registered users and 9 guests