Domanda

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?

È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top