Why is it not legal to have the following two methods in the same class?
class Test{ void add(Set<Integer> ii){} void add(Set<String> ss){} }
I get the compilation error
Method add(Set) has the same erasure add(Set) as another method in type Test.
while I can work around it, I was wondering why javac doesn't like this.
I can see that in many cases, the logic of those two methods would be very similar and could be replaced by a single
public void add(Set<?> set){}
method, but this is not always the case.
This is extra annoying if you want to have two constructors
that takes those arguments because then you can't just change the name of one of the constructors
.
- Erasure is a type of alteration in document. It can be classified as chemical erasure and physical erasure. - There are many chemicals which are able to invisible the ink such as oxalic acid, sodium hydrochlorite etc.
Type erasure is a process in which compiler replaces a generic parameter with actual class or bridge method. In type erasure, compiler ensures that no extra classes are created and there is no runtime overhead.
Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to: Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded.
This answer is not useful. Show activity on this post. At runtime, the parameter types are replaced by Object . So saveAll(Collection<?>) and saveAll(Collection<MyClass>) are transformed to saveAll(Collection) . This is a name clash.
This rule is intended to avoid conflicts in legacy code that still uses raw types.
Here's an illustration of why this was not allowed, drawn from the JLS. Suppose, before generics were introduced to Java, I wrote some code like this:
class CollectionConverter { List toList(Collection c) {...} }
You extend my class, like this:
class Overrider extends CollectionConverter{ List toList(Collection c) {...} }
After the introduction of generics, I decided to update my library.
class CollectionConverter { <T> List<T> toList(Collection<T> c) {...} }
You aren't ready to make any updates, so you leave your Overrider
class alone. In order to correctly override the toList()
method, the language designers decided that a raw type was "override-equivalent" to any generified type. This means that although your method signature is no longer formally equal to my superclass' signature, your method still overrides.
Now, time passes and you decide you are ready to update your class. But you screw up a little, and instead of editing the existing, raw toList()
method, you add a new method like this:
class Overrider extends CollectionConverter { @Override List toList(Collection c) {...} @Override <T> List<T> toList(Collection<T> c) {...} }
Because of the override equivalence of raw types, both methods are in a valid form to override the toList(Collection<T>)
method. But of course, the compiler needs to resolve a single method. To eliminate this ambiguity, classes are not allowed to have multiple methods that are override-equivalent—that is, multiple methods with the same parameter types after erasure.
The key is that this is a language rule designed to maintain compatibility with old code using raw types. It is not a limitation required by the erasure of type parameters; because method resolution occurs at compile-time, adding generic types to the method identifier would have been sufficient.
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