问题
For fun, I'm trying to implement a "MultiMap" collection, like what already exists in the Apache Commons library. I'm getting an interesting error with my "remove(K key, V value)" method. The compiler says that there is a name clash - that it has the same erasure as "remove(Object, Object) of type Map". But there is no such method defined in the java.util.Map interface! Only a "remove(Object)" method - with one parameter, as opposed to my two parameter version. What's even more interesting is that if you manually remove the type information by replacing my "remove(K key, V value)" with "remove(Object key, Object value)", it compiles fine. Can anyone explain this phenomenon?
I'm running Java 8, in case that matters.
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MultiMap<K, V> extends AbstractMap<K, Collection<V>>
{
private Map<K, Collection<V>> map;
public MultiMap()
{
super();
map = new HashMap<>();
}
//Fine
public void clear(K key)
{
get(key).clear();
}
//Fine
public boolean add(K key, V value)
{
if(!containsKey(key))
put(key, new ArrayList<>());
return get(key).add(value);
}
//KABOOM!!
//"Name clash: The method remove(K, V) of type MultiMap<K,V> has the same erasure as remove(Object, Object) of type Map<K,V> but does not override it"
public boolean remove(K key, V value)
{
if(!containsKey(key))
return false;
return get(key).remove(value);
}
@Override public Collection<V> put(K key, Collection<V> values)
{
return map.put(key, values);
}
@Override public Set<java.util.Map.Entry<K, Collection<V>>> entrySet()
{
return map.entrySet();
}
}
回答1:
But there is no such method defined in the java.util.Map interface!
There is a Map#remove(Object, Object) method in the Map
interface; it was added in Java 8. Hence the error.
回答2:
This is due type erasure process when a java generic type is translated to bytecode.
At runtime the default boolean remove(Object key, Object value)
(this method is new in Java 8) in Map is the same than your method at MultiMap class public boolean remove(K key, V value)
.
The compiler sees this, and hence shows the error :
Name clash: The method remove(K,V) of type MultiMap has the same erasure as remove(Object, Object) of type AbstractMap but does not override it.
See this: http://docs.oracle.com/javase/tutorial/java/generics/genTypes.html
来源:https://stackoverflow.com/questions/23785807/java-name-clash-error-despite-different-method-signatures