This is yet another question about methods with signatures using parametrized types in Java.
Say you have the following two methods:
static void f(List<Integer> l) {}
static void f(List<String> l) {}
The compiler will complain that both methods have same signature after type erasure (both argument types are erased to just List
).
Many similar questions on stackoverflow ask why it is so, but always the question is about instance (non static) methods (see Method has the same erasure as another method in type for instance).
Usually half the answers are based on the following (very wrong) argument: the compiler would erase all type parameters in the bytecode and make methods undistinguishable. Ok then, just print the bytecode with javap
and you will see whether everything is erased! (although the bytecode loses a lot of parametrization data, full method signatures are actually kept, which is definitely useful when you want to compile a new class using a dependency containing generic classes and methods).
On the other hand, the best answers usually quote JLS 8.4.2 and explain that, for compatibility with old, pre-generic, Java versions (and raw types in newer versions), methods with override-equivalent signatures are forbidden.
I am ok with the latter argument, except it only means something for instance methods (non static), as static methods cannot be overridden anyway.
Probably there is a similar explanation for static methods, but I fail to pinpoint it. Could somebody help me understand this?
The argument for backwards-compatibility still holds.
If you had this code (not using generics, strongly discouraged, but legal even today, and perfectly normal in Java 1.4 code that is supposed to still compile), which of your two methods should the compiler choose?
List rawList = new ArrayList();
YourClass.f(rawList);
More to the point, assuming you somehow choose one of the two, in the resulting call-site bytecode, the generics are still erased, so at runtime, the JVM does not know which of the two f(List)
you meant. Method calls specify the method name and signature, but that signature does not include generics. That is does not is due to compatibility concerns. Could they have tried to push harder on this with something like a new opcode with an extended call specification? Maybe. But that is how it is now.
On the other hand, the best answers usually quote JLS 8.4.2 and explain that, for compatibility with old, pre-generic, Java versions (and raw types in newer versions), methods with override-equivalent signatures are forbidden.
I am ok with the latter argument, except it only means something for instance methods (non static), as static methods cannot be overridden anyway.
Well, you cannot override static methods, but your two methods are still "override-equivalent", meaning they have a signature that is so close to each other that you can have only one of them at a time (in a subclass situation, one would override the other if inherited because of that --- but it also means that you cannot have two of such methods on the same class).
Note that this does not pose any real issues, as you can always avoid the need for "overloading" by just changing to distinct method names.