Pergunta

Could anyone explain to me why this is not allowed in Java? I have these three files (stripped and simplified for StackExchange):

A superclass, in my case for generic graphs. The type parameter indicates how arcs are represented: Either with a specific Arc class, or with Integers indicating unique IDs.

public interface Base<A> {
    public boolean removeArc(A arc);
}

A subclass, with a specific implementation for arc.

public interface Sub<B> extends Base<Arc<B>> {
    @Override
    public boolean removeArc(Arc<B> arc);

    public Arc<B> removeArc(B value); //Removes an arc with this specific value.
}

The arc implementation.

public interface Arc<B> {
}

Netbeans gives me the following compile-time errors in Sub. At @Override:

name clash: removeArc(Arc<B>) in Sub overrides a method whose erasure is the same as another method, yet neither overrides the other
  first method: removeArc(B) in Sub
  second method: removeArc(A) in Base
  where B,A are type-variables:
    B extends Object declared in interface Sub
    A extends Object declared in interface Base

At the second method:

name clash: removeArc(B) in Sub and removeArc(A) in Base have the same erasure, yet neither overrides the other
  where B,A are type-variables:
    B extends Object declared in interface Sub
    A extends Object declared in interface Base

The problem seems to be that removeArc(Arc<B>) and removeArc(B) have the same erasure, but I don't see why this is happening. Removing removeArc(Arc<B>) compiles fine, without warning about the @Override, so it must realise that Arc<B> equals A in Base.

Why is Java unable to differentiate between Arc<B> and B in this case?

Foi útil?

Solução

The compiler removes generic classes at compile time. It will replace the place holder with it's restricted class.

In this case Base will replace any instance of A with Object and Sub will replace any instance of B with Object.

this gives the conflicting methods

in Base public boolean removeArc(Object arc);

and in Sub public Arc removeArc(Object value);

if however you did

public interface Base<A extends Arc<?>> {
    public boolean removeArc(A arc);
}

then the instances of A would be replaced with Arc and the method signatures would no longer conflict.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top