I am extending a class defined in a library which I cannot change:
我正在扩展一个我无法改变的库中定义的类:
public class Parent
{
public void init(Map properties) { ... }
}
If I am defining a class 'Child' that extends Parent and I am using Java 6 with generics, what is the best way to override the init method without getting unchecked warnings?
如果我正在定义一个扩展Parent的类'Child'而我正在使用带有泛型的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) { }
}
If I add generic parameters, I get:
如果我添加通用参数,我得到:
// 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<?,?>) { ... }
This error occurs regardless of whether I use a specific type, a bounded wildcard, or an unbounded wildcard. Is there a correct or idiomatic way to override a non-generic method without warnings, and without using @SuppressWarnings("unchecked")?
无论我使用特定类型,有界通配符还是*通配符,都会发生此错误。是否有正确或惯用的方法来覆盖非通用方法而没有警告,并且没有使用@SuppressWarnings(“unchecked”)?
4 个解决方案
#1
12
Yes, you have to declare the overriding method with the same signature as in the parent class, without adding any generics info.
是的,您必须使用与父类相同的签名声明覆盖方法,而不添加任何泛型信息。
I think your best bet is to add the @SuppressWarnings("unchecked")
annotation to the raw-type parameter, not the method, so you won't squelch other generics warnings you might have in your own code.
我认为你最好的办法是将@SuppressWarnings(“unchecked”)注释添加到raw-type参数中,而不是方法中,这样你就不会压制自己代码中可能有的其他泛型警告。
#2
2
Short answer: no way to do that.
简短回答:没办法做到这一点。
Unsatisfying answer: disable the (specific) warnings in your IDE/build.xml.
不满意的答案:禁用IDE / build.xml中的(特定)警告。
If you cannot change the library, alas, you have to stick with non-generic methods.
如果您无法更改库,唉,您必须坚持使用非泛型方法。
The problem is that, despite after type erasure both init() have the same signature, they may in fact be different methods -- or the same(*). Compiler cannot tell should it do override or overload, so it's prohibited.
问题在于,尽管在类型擦除之后,init()都具有相同的签名,但实际上它们可能是不同的方法 - 或者相同(*)。编译器无法判断它是否应该覆盖或超载,因此禁止它。
(*) Suppose the library developer meant init(Map<String,Integer>). Now you are implementing init(Map<String,String>). This is overloading, and two methods should exist in the vtable of Child class.
(*)假设库开发人员的意思是init(Map
But what if the library developer meant init(Map<String,String>)? Then it's overriding, and your method should replace original init in Child class, and there would be only one method in the vtable of Child.
但是如果库开发人员的意思是init(Map
P.S. I hate how Generics implemented in Java :-(
附:我讨厌Generics如何在Java中实现:-(
#3
2
I think above answer meant to say @SuppressWarnings("rawtypes") instead.
我认为上面的答案意味着代替@SuppressWarnings(“rawtypes”)。
#4
0
You have to declare the method with the same signature as the parent, and therefore you will get warnings when you compile. You can suppress them with @SuppressWarnings("unchecked")
您必须使用与父项相同的签名声明方法,因此在编译时将收到警告。您可以使用@SuppressWarnings(“未选中”)来抑制它们
The reason why there is no way to get rid of this is that the warnings are there to let you know that it's possible to create Collections with invalid types in them. The warnings should only go away when all code that might allow that has been removed. Since you are inheriting from a non-generic class it will always be possible to create a Collection with invalid contents.
无法摆脱这种情况的原因是警告是为了让您知道可以在其中创建包含无效类型的集合。只有当可能允许的所有代码都被删除时,警告才会消失。由于您从非泛型类继承,因此始终可以创建具有无效内容的Collection。
#1
12
Yes, you have to declare the overriding method with the same signature as in the parent class, without adding any generics info.
是的,您必须使用与父类相同的签名声明覆盖方法,而不添加任何泛型信息。
I think your best bet is to add the @SuppressWarnings("unchecked")
annotation to the raw-type parameter, not the method, so you won't squelch other generics warnings you might have in your own code.
我认为你最好的办法是将@SuppressWarnings(“unchecked”)注释添加到raw-type参数中,而不是方法中,这样你就不会压制自己代码中可能有的其他泛型警告。
#2
2
Short answer: no way to do that.
简短回答:没办法做到这一点。
Unsatisfying answer: disable the (specific) warnings in your IDE/build.xml.
不满意的答案:禁用IDE / build.xml中的(特定)警告。
If you cannot change the library, alas, you have to stick with non-generic methods.
如果您无法更改库,唉,您必须坚持使用非泛型方法。
The problem is that, despite after type erasure both init() have the same signature, they may in fact be different methods -- or the same(*). Compiler cannot tell should it do override or overload, so it's prohibited.
问题在于,尽管在类型擦除之后,init()都具有相同的签名,但实际上它们可能是不同的方法 - 或者相同(*)。编译器无法判断它是否应该覆盖或超载,因此禁止它。
(*) Suppose the library developer meant init(Map<String,Integer>). Now you are implementing init(Map<String,String>). This is overloading, and two methods should exist in the vtable of Child class.
(*)假设库开发人员的意思是init(Map
But what if the library developer meant init(Map<String,String>)? Then it's overriding, and your method should replace original init in Child class, and there would be only one method in the vtable of Child.
但是如果库开发人员的意思是init(Map
P.S. I hate how Generics implemented in Java :-(
附:我讨厌Generics如何在Java中实现:-(
#3
2
I think above answer meant to say @SuppressWarnings("rawtypes") instead.
我认为上面的答案意味着代替@SuppressWarnings(“rawtypes”)。
#4
0
You have to declare the method with the same signature as the parent, and therefore you will get warnings when you compile. You can suppress them with @SuppressWarnings("unchecked")
您必须使用与父项相同的签名声明方法,因此在编译时将收到警告。您可以使用@SuppressWarnings(“未选中”)来抑制它们
The reason why there is no way to get rid of this is that the warnings are there to let you know that it's possible to create Collections with invalid types in them. The warnings should only go away when all code that might allow that has been removed. Since you are inheriting from a non-generic class it will always be possible to create a Collection with invalid contents.
无法摆脱这种情况的原因是警告是为了让您知道可以在其中创建包含无效类型的集合。只有当可能允许的所有代码都被删除时,警告才会消失。由于您从非泛型类继承,因此始终可以创建具有无效内容的Collection。