Does int.class autobox to Class<Integer>
Asked Answered
P

3

13

I am sure my question doesn't make sense, but it's because I don't know what I am seeing or how to describe it...

The following code compiles fine, but it shouldn't because int is not the same type as Integer. Shouldn't this give a compiler error? And if the compiler expects the type of Class<Integer> how at runtime does it get resolved to Class<int>? Is this some magic where the compiler lets it go on primitives? And if the compiler relaxes validation on primitives doesn't this lead to bugs where method writers expect the type to be the EXACT type Class<Integer> and instead is delivered Class<int>.

In short, why does this compile and produce the correct or wrong (depending on perspective) result at runtime.

public static void main(String[] args) {

    printClass("int     ", int.class);
    printClass("Integer ", Integer.class);
    System.out.printf("AreEqual", int.class == Integer.class);
}

private static void printClass(String text, final Class<Integer> klazz) {
    System.out.printf("%s: %s%s", text, klazz, "\n");
}

output:

int     : int
Integer : class java.lang.Integer
AreEqual: false

For the control group, this code does NOT COMPILE as I would expect

public static void main(String[] args) {

    printClass("Person  ", Person.class);
    printClass("Employee", Employee.class);
    System.out.printf("AreEqual: %s", Person.class == Employee.class);
}

private static void printClass(String text, final Class<Person> klazz) {
    System.out.printf("%s: %s%s", text, klazz, "\n");
}


public class Employee extends Person {
}
public class Person {
}

Errors:

Error:(8, 40) java: incompatible types: java.lang.Class<com.company.Employee> cannot be converted to java.lang.Class<com.company.Person>
Pickaxe answered 2/3, 2016 at 7:45 Comment(2)
Always mention errors when providing an minimal reproducible example, there are 2 errors when compiling: Main.java:13: error: incompatible types: Class<Ideone.Employee> cannot be converted to Class<Ideone.Person> printClass("Employee", Employee.class); and Main.java:14: error: incomparable types: Class<Ideone.Person> and Class<Ideone.Employee> System.out.printf("AreEqual: %s", Person.class == Employee.class);Lifegiving
Because it doesn't compile in the case of objects (see the person example). Why do primitives work differently than objects? specifically the type passed to the method must match EXACTLY for ALL other cases except the primitive case i described with int.Pickaxe
B
15

What you observed is a direct result of the way generics handle primitives, it is not auto-boxing. To be consistent in cases where class-information will be used (like generics or reflection), primitive types in certain cases need to return with something when examining their type.

When dereferencing anyprimitivetype.class, the TYPE field from the enclosing wrapper class will be returned. In your case it is:

 int.class -> public static final Class<Integer> TYPE

You can find the full list here for all the primitive type plus void: primitives

They are part of the language spec since 1.1 .

Burnedout answered 2/3, 2016 at 8:4 Comment(1)
Thank you!! I was just typing up another example to show that it was not autoboxing (at least in the traditional sense), because autoboxing converts at compile time, so my runtime output would have not said int, but instead it would have said IntegerPickaxe
H
3

Because there is implicit autoboxing since Java 5 of primitive types. For other types you need to use an other syntax to achieve your goal: search for Generics.

Try this:

private static void printClass(String text, final Class<? extends Person> klazz) {
    System.out.printf("%s: %s%s", text, klazz, "\n");
}
Hafnium answered 2/3, 2016 at 8:0 Comment(2)
The Class objects are not being autoboxed.Ishtar
@dimo414: the accepted answer is a way better than mine (I've upvoted it). But for beginners it may be difficult to understand.Hafnium
I
3

That's because this is the way java generics work. If you want to allow all classes that inherit from Person you may use:

private static void printClass(String text, final Class<? extends Person> klazz) {
Inflame answered 2/3, 2016 at 8:1 Comment(1)
This doesn't answer the question.Ishtar

© 2022 - 2024 — McMap. All rights reserved.