2008-10-27 53 views
14

我延长在库中定义的类,我不能改变:使用原始类型参数覆盖方法时可以避免未经检查的警告吗?

public class Parent 
{ 
    public void init(Map properties) { ... } 
} 

如果我定义一个类“儿童”,扩展父母和我使用的Java 6泛型,什么是最好的方式重写init方法而不会收到未经检查的警告?

public class Child extends Parent 
{ 
    // warning: Map is a raw type. References to generic type Map<K,V> should be parameterized 
    public void init(Map properties) { } 
} 

如果我添加泛型参数,我得到:不管我是否使用特定类型,绑定的通配符,或者无界通配符发生

// error: The method init(Map<Object,Object>) of type Child has the same erasure as init(Map) of type Parent but does not override it 
    public void init(Map<Object,Object>) { ... } 
    // same error 
    public void init(Map<? extends Object,? extends Object>) { ... } 
    // same error 
    public void init(Map<?,?>) { ... } 

此错误。有没有一种正确或惯用的方法来覆盖非警告的非泛型方法,并且不使用@SuppressWarnings(“unchecked”)?

回答

12

是的,你必须声明具有相同签名的首要方法,在父类,不添加任何仿制药信息。

我认为最好的方法是将@SuppressWarnings("unchecked")注释添加到原始类型参数中,而不是方法,因此您不会压制在您自己的代码中可能存在的其他仿制药警告

+0

@SuppressWarnings绝对是您在这里最好的选择。吮吸,但是当你试图强制泛型进入不使用它的库时会发生这种情况。 – 2008-10-28 02:52:56

2

简答:没办法做到这一点。

Unsatisfying answer:禁用IDE/build.xml中的(特定)警告。

如果你不能改变库,唉,你必须坚持使用非泛型方法。

问题是,尽管类型擦除后两个init()具有相同的签名,但它们可能实际上是不同的方法 - 或相同的(*)。编译器无法确定它是否应该覆盖或超载,因此它是被禁止的。

(*) 假设库开发人员的意思是init(地图<字符串,整数>)。现在你正在执行init(Map < String,String >)。这是重载,并且在Child类的vtable中应该存在两种方法。

但是,如果库开发人员意味着初始化(地图<字符串,字符串>)呢?然后重写,你的方法应该用代替 Child类中的原始init,并且在Child的vtable中只有一个方法。

P.S.我讨厌泛型在Java中如何实现:-(

+0

您能解释一下为什么具有相同(擦除)签名的方法可能是编译器的不同方法?编译器在编码时不知道开发人员_meant_ ...--) – nrainer 2015-05-28 08:34:44

0

您必须声明与父级相同的签名方法,因此在编译时会得到警告,你可以用@SuppressWarnings(“unchecked”)来压制它们。

为什么没有办法摆脱这种情况的原因是,警告在那里让你知道有可能创建具有无效类型的集合。只有当所有可能允许删除的代码被删除时,警告才会消失。由于您从非泛型类继承,因此始终可以使用无效内容创建集合。

2

我认为上面的答案意味着说@SuppressWarnings(“rawtypes”)。

相关问题