Danstahr
Danstahr

Reputation: 4319

Java Generics - calling specific methods from generic-typed ones

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

Answers (3)

michal.z
michal.z

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

Misha
Misha

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

amalloy
amalloy

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

Related Questions