Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java name clash error, despite different method signatures

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();
    }
}
like image 813
TheBrownMotie Avatar asked May 21 '14 14:05

TheBrownMotie


2 Answers

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.

like image 92
arshajii Avatar answered Sep 30 '22 05:09

arshajii


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

like image 27
masinger Avatar answered Sep 30 '22 05:09

masinger