Java name clash error, despite different method signatures
Asked Answered
A

2

11

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();
    }
}
Aguila answered 21/5, 2014 at 14:13 Comment(4)
Hm I'm not getting an error there. I am getting an error with the put(key, new ArrayList<>()) call, though. (Edit: I tried this with Java 7.)Afternoons
Interesting. Perhaps the version matters? I'm running Java 8.Aguila
@Aguila I think that it matters. I've seen already a couple of compile strange behaviours on SO.Fading
RT[f]M: docs.oracle.com/javase/8/docs/api/java/util/Map.htmlHas
A
16

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.

Afternoons answered 21/5, 2014 at 14:18 Comment(0)
I
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

Ionia answered 21/5, 2014 at 19:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.