[英]How to avoid unsafe cast warnings with Java Generics
我是Java Generics的新手。 但我已经阅读了很多摘要链接和示例。 但是我无法找到最简单的方法。 希望有人能提供帮助:
我想创建一个将一个未定义对象映射到另一个对象的HashMap。 两个对象都可以是String或Integer之一。
所以我这样写:
private final HashMap<L, R> left2Right = new HashMap<L, R>();
Extractor<?> extLeft = Extractor.getInstance(0);
Extractor<?> extRight = Extractor.getInstance(1);
L leftVal = extLeft.extract(d, i);
R rightVal = extRight.extract(d, i);
this.left2Right.put(leftVal, rightVal);
到目前为止一切顺利……但是我在实现提取器对象方面遇到问题。 它们通过工厂模式进行实例化。 我做到了(简化):
abstract class Extractor<E> {
abstract E extract(DTable source, int row);
static <E> Extractor<E> getInstance(int type) {
if(type == 0)
return new IntExtractor();
else
return new StringExtractor();
}
}
class IntExtractor extends Extractor<Integer> {
@Override
Integer extract(DTable source, int row) {
int value = 5;
return new Integer(value);
}
}
class StringExtractor extends Extractor<String> {
@Override
String extract(DTable source, int row) {
String retVal = "hello";
return retVal;
}
}
它可以编译,但是在将Integer / String转换为E时收到Unsave强制转换警告。我在做什么错? 我知道,我可以简单地禁止警告。 但是我认为这正是Java泛型的优势吗? 我无法保存此演员表,因为我不知道哪种类型的“ E”真正“是” ...
还是我做的事情基本上是错误的?
注意:在使用第一个答案中的一些信息后,我将代码编辑为“新”问题。
您的提取器根本不是通用的。 听起来您想要这样的东西:
public interface Extractor<P> {
P extract(DTable source, int row);
}
但随后使实现变得非通用:
class IntExtractor implements Extractor<Integer> {
Integer extract(DTable source, int row) {
int value = 5;
return new Integer(value);
}
}
从根本上来说,您当前的代码已损坏,因为我可以这样写:
IntExtractor<String> extractor = new IntExtractor<String>();
String x = extractor.extract(...);
...这显然会失败,但仅限于执行时。
我会说您做的事情基本上是错误的。 如果它是IntExtractor和StringExtractor,则不需要泛型。 只需定义方法
Integer extract(DTable source, int row)
和
String extract(DTable source, int row)
问题不是您的代码本身。 没有不安全的转换,任务本身无法解决。 再次阅读自己的句子:
我想创建一个将一个未定义对象映射到另一个对象的HashMap。 两个对象都可以是String或Integer之一。
Java泛型无法为您解决此问题,因为您必须事先知道类型,否则必须进行强制转换。
老实说,我不知道您要使用发布的代码实现什么,但是如果您要使用HashMap,则可以这样做:
private final HashMap<String, Integer> left2Right = new HashMap<String, Integer>();
left2Right.put("one", 1);
int numberOne = left2Right.get("one");
在这种情况下,您不必强制转换值,因为HashMap具有String键和Integer值。 如果要将不同的类型用作值,则必须使用所有值的超类型。 此超类型可能是对象,即层次结构的根。 但是在这种情况下,您必须强制转换-因为您不知道该值是哪种对象。
private final HashMap<String, Integer> left2Right = new HashMap<String, Object>();
left2Right.put("one", 1);
left2Right.put("two", new Date());
// Because the compiler cannot know that type "one" might be, this isn't allowed and you have to cast the value. It might be anything - in this example Date or Integer.
int numberOne = left2Right.get("one");
希望对您有所帮助。
P
和E
似乎都没有用于提取器的输入,所以为什么还要使用它们呢? 只需返回int
和String
并完成它即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.