Java Generics名称冲突,方法未正确覆盖

时间:2010-03-30 09:02:53

标签: java generics

我已经看到了不同的问题,但我仍然觉得这个话题非常混乱。

我想要做的是,有一个实现接口的抽象类,并且有一个扩展这个抽象类的类,以便硬类需要实现getKommune()setKommune(Kommune kommune),但不是其他方法,因为那是在抽象类中。

我有以下界面。

public interface KommuneFilter {

    <E extends AbstractKommune<?>> void addKommuneFromCurrentUser(E e);

    Kommune getKommune();

    void setKommune(Kommune kommune);
}

这个抽象类

public abstract class AbstractKommune<E extends AbstractKommune<?>> implements KommuneFilter {
    @PrePersist
    void addKommuneFromCurrentUser(E e) {
            Kommune k = e.getKommune();
    }
}

我想像这样使用它

    public class Person extends AbstractKommune<Person> {
        private Kommune kommune;             
        public void setKommune(Kommune kommune) {this.kommune=kommune;}
        public Kommune getKommune() {return kommune;}
    }

但是,我得到了

Name clash: The method of has the same erasure of type but does not override it

为什么不正确覆盖?

更新

感谢@Bozho,解决方案是:

public interface KommuneFilter<E extends AbstractKommune<?>> {
    public void addKommuneFromCurrentUser(E e);
}

public abstract class AbstractKommune<E extends AbstractKommune<?>> implements KommuneFilter<E> 

public class Person extends AbstractKommune<Person>

2 个答案:

答案 0 :(得分:5)

我建议将界面设为通用的,而不仅仅是它的方法:

interface KommuneFilter<E extends AbstractKommune<?>> { .. }

然后

public abstract class AbstractKommune<E extends AbstractKommune<?>> 
     implements KommuneFilter<E> 

答案 1 :(得分:2)

它之所以是名字冲突而不是覆盖是因为它不是。接口指定的方法是通用方法;你的抽象类试图覆盖它不是。

更简洁的代码可以重现您的问题:

interface I {
    <E> void foo(E e);
}

class C<E> implements I {
    public void foo(E e) { // name clash at compile time!
    }
}

这里的问题是interface I指定实现者必须提供通用方法<E>foo(它可以是<Integer>foo<Boolean>foo等,但是,例如, C<String>实际上只有foo(String)

解决此问题的一种方法是使C.foo成为通用方法,以正确@Override interface I的通用方法:

interface I {
    <E> void foo(E e);
}

class C<E> implements I {
    @Override public <T> void foo(T t) {
    }

    public static void main(String args[]) {
        C<String> o = new C<String>();
        o.<Integer>foo(0);
        o.<Boolean>foo(false);
    }
}

您可以在上面的代码中看到它的作用:您的通用类型C<E>包含通用方法<T>foo(您可以使用E代替T,但这不会改变任何东西 - 它仍然是一个带有自己的类型参数的泛型方法。)

现在,C<String>也有<Integer>foo等,由interface I指定。

如果这不是您需要的,那么您可能希望改为interface I<E>通用:

interface I<E> {
    void foo(E e);
}

class C<E> implements I<E> {
    @Override public void foo(E e) {
    }
}

现在类型和方法共享相同的类型参数(例如,I<Boolean>只有foo(Boolean)C<String>只有foo(String),这很可能是什么你最初想要的。