I realized today that this compiles and runs fine:
public class Test {
public static <T> T handle(T val) {
System.out.println("T");
return val;
}
public static <T extends String> T handle(T val) {
System.out.println("T extends String");
return val;
}
}
The two handle
methods has the same name, and same number and type (?
) of parameters. The only difference is that the second handle
method has a stricter generic bound. IDE does not complain at all, and the code compiles fine. At run time method is selected as expected - e.g. Test.handle("this is a string")
will call into the second method and Test.handle(10)
will invoke the first one.
Is generics bound considered part of the method signature? or is it a method overload resolution magic?
Generics offer compile-time type-safety; At runtime, your methods erase to the following:
public static Object handle(Object val) {
System.out.println("T");
return val;
}
public static String handle(String val) {
System.out.println("T extends String");
return val;
}
Due to method overloading, handle(String)
will be called when passing a String
, and handle(Object)
will be called when passing any other Object
(keep in mind String
is final and can have no children).
The bound of the generics is considered.
In the first case, the bound is Object; in the second case, the bound is String.
When types are erased, the bound is used in place of the type variable, so these become simply an overload taking (and returning) Object and String parameters, respectively.
Nothing wrong with that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With