I asked:
Is autoboxing/unboxing is done at runtime (JVM) or compile time (compiler)?
I received this answer:
Autoboxing is achieved by the insertion of method calls and casts by the compiler, into the code. These calls and casts are handled at runtime.
Please explain in more detail.
From Java Specification
Chapter 5. Conversions and Promotions
Every expression written in the Java programming language has a type
that can be deduced from the structure of the expression and the types
of the literals, variables, and methods mentioned in the expression.
It is possible, however, to write an expression in a context where the
type of the expression is not appropriate. In some cases, this leads
to an error at compile time. In other cases, the context may be able
to accept a type that is related to the type of the expression; as a
convenience, rather than requiring the programmer to indicate a type
conversion explicitly, the Java programming language performs an
implicit conversion from the type of the expression to a type
acceptable for its surrounding context.
From here, we know compiler will accept particular expression even if the programmer does not indicate a type conversion. That's why following code does not raise an error at compile time.
int i = new Integer(3);
Integer j = 3;
Chapter 5. Conversions and Promotions 5.1.7. Boxing Conversion
... At run time, boxing conversion proceeds as follows:
If p is a value of type boolean, then boxing conversion converts p
into a reference r of class and type Boolean, such that
r.booleanValue() == p ...
Chapter 5. Conversions and Promotions 5.1.8. Unboxing Conversion
... At run-time, unboxing conversion proceeds as follows:
If r is a reference of type Boolean, then unboxing conversion converts
r into r.booleanValue() ...
and this is what happens exactly in run-time.
Autoboxing and unboxing are compile time processes.
We can verify with a small test as described below:
Create a Java project, say, with name 'Crap'. Inside that, create a .java file with below contents:
public class Crap {
private Boolean crap;
public Boolean getCrap() {
return crap;
}
public void setCrap(Boolean crap) {
System.out.println("lol.. this is crap!!");
this.crap = crap;
}
}
Build this project and export as a jar file, say crap.jar.
Now create one more Java project, say, with name 'Junk'. Add crap.jar file into the classpath of this project and then create a .java file with below contents:
public class Junk {
public static void main(String[] args) {
Crap crap = new Crap();
crap.setCrap(true);
}
}
Now, build Junk project, and run Junk.java as Java application. It will run successfully and the output will be
lol.. this is crap!!
Now, modify Crap.java, modify the Boolean crap to boolean and also the corresponding getters and setters. Code will look like as below:
public class Crap {
private boolean crap;
public boolean getCrap() {
return crap;
}
public void setCrap(boolean crap) {
System.out.println("lol.. this is crap!!");
this.crap = crap;
}
}
Again build this project and export it as crap.jar. Put this crap.jar file into the classpath of Junk project (and remove the earlier jar file from its classpath).
Now if you try to run Junk.java as java application, you will get below stacktrace:
Exception in thread "main" java.lang.NoSuchMethodError: crap.Crap.setCrap(Ljava/lang/Boolean;) at junk.Junk.main(Junk.java:9)
Well, it says the compiler does it. So it happens at compile time.
This is necessary to ensure the static type safety of Java.