Reputation: 4319
I try to dive deeply into the Java Generics and I've come across a problem described by the following sample code.
public static void test(Object o) {
System.out.println("Hello Object!");
}
public static void test(Integer i) {
System.out.println("Hello Integer!");
}
public static <T> void test(Collection<T> col) {
for (T item : col) {
System.out.println(item.getClass().getSimpleName());
test(item);
}
}
public static void main (String[] args) throws java.lang.Exception
{
Collection<Integer> ints = new ArrayList<>();
ints.add(1);
test(ints);
}
The output of the sample is
Integer
Hello Object!
All the types are obviously known at compile time. As far as I understand, Java holds only a single compiled copy of each method (unlike C++) and because no other constraints are given about the parameter T, it's forced to call the generic Object implementation.
My question is - is there any way to call the "Hello Integer" method for integers without overloading the test method for Collection<Integer>
and without using runtime type checking?
Upvotes: 5
Views: 113
Reputation: 2075
It cannot be done. Due to type erasure type Collection<T>
will be resolved to type Collection<Object>
. Erasure of Generic Methods
Upvotes: 3
Reputation: 28133
You can observe the same behavior without generics.
Object o = new Integer(5);
test(o); // will output "Hello Object!"
Overloaded methods are resolved using compile-time rather than run-time type information. See JLS: https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.9
Upvotes: 2
Reputation: 91857
No, you can't do what you ask for, for the reasons you gave. Type erasure means that the overload is resolved once for all type variables, and it has to resolve to Object.
Upvotes: 1