Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics name clash , has the same erasure

Tags:

java

generics

I have superclass Foo. And a class Bar extending it.

public class Bar extends Foo 

Function in Foo:

protected void saveAll(Collection<?> many) 

Function in Bar:

public void saveAll(Collection<MyClass> stuff) {    super.saveAll(stuff); } 

Getting error :

 Name clash: The method saveAll(Collection<MyClass>) of type Bar has the same erasure as saveAll(Collection<?>) of type Foo but does not override it. 

What am I doing wrong?

like image 650
Jaanus Avatar asked Aug 13 '12 12:08

Jaanus


People also ask

How generics works in Java What is type erasure?

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.

What is method Erasure?

Method Type Erasure. For method-level type erasure, the method's type parameter is not stored but rather converted to its parent type Object if it's unbound or it's first bound class when it's bound.

What are generics stack overflow?

Generics allow you to create a single method that is customized for the type that invokes it. T is substituted for whatever type you use.


2 Answers

You are overriding the saveAll method with an incompatible type. Perhaps you want to do something like:

public class Bar extends Foo<MyClass> 

Function in Foo<E>

protected void saveAll(Collection<E> many) 

and function in Bar:

public void saveAll(Collection<MyClass> stuff) {    super.saveAll(stuff); } 
like image 67
Mathias Schwarz Avatar answered Sep 16 '22 21:09

Mathias Schwarz


Due to the type erasure feature of Java, the JVM will not be able to know whether it is the method that has the parametrized type MyClass or the first one that should be called.

If possible or applicable, the most commonly used pattern I've seen to avoid this is to change the class Foo to have a parametrized type as well:

public class Foo<T> {     protected void saveAll(Collection<T> many) {} } 

and then have Bar simply implement Foo for your specific type:

public class Bar extends Foo<MyClass> {     public void saveAll(Collection<MyClass> many) {         super.saveAll(many);     } } 
like image 24
Joel Westberg Avatar answered Sep 17 '22 21:09

Joel Westberg