It wouldn't call the overload that takes a
String, even if
Java didn't use type erasure. Type erasure affects what the application can do at run time. Method overload resolution is not done at run time, but at compile time.
When a statement contains a method invocation, the compiler determines what method overload is used before the application is run. That means that the compiler must determine which overload of
f() to call from
g(), without knowing the actual runtime type of
T, so it can only use type bounds on
T in its determination.
Since
T has no explicit type bounds, the upper type bound on
T is
Object, so the overload that accepts
Object is called.
Try the following:
Now that
T has an upper bound of
String, the compiler will call the overload that accepts
String.