Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method has the same erasure as another method in type

Tags:

java

generics

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.

like image 326
Omry Yadan Avatar asked Jan 04 '10 09:01

Omry Yadan


People also ask

What are the two 2 types of Erasure?

- 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.

What is type erasure and explain the functionality of type erasure with example?

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.

How does Erasure work in Java?

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.

What is name clashing in Java?

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.


1 Answers

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.

like image 65
erickson Avatar answered Sep 17 '22 12:09

erickson