我是Java Generics的新手。但我已经阅读了很多摘要链接和示例。但我无法获得最简单的方法。我希望somenoe可以提供帮助:
我想创建一个HashMap,它将一个未定义的Object映射到另一个。两个对象都可以是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;
}
}
它编译,但是我在将整数/字符串转换为E时得到Unsave强制警告。我做错了什么?我知道,我可以简单地压制警告。但我认为这应该是Java泛型的优势?我不能让这个演员保存,因为我不知道,'E'真正“是”哪种类型......
或者我做的事情基本上是错的?
注意: 在我使用了第一个答案中的一些信息之后,我将我的代码编辑成了一个“新”问题......
答案 0 :(得分:2)
你的提取器根本不是通用的。这听起来像你想要的东西:
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(...);
......这显然会失败,但仅限于执行时间。
答案 1 :(得分:1)
我会说你做的事情基本上是错的。如果它是IntExtractor和StringExtractor,则不需要泛型。只需定义方法
Integer extract(DTable source, int row)
和
String extract(DTable source, int row)
答案 2 :(得分:1)
问题不在于您的代码本身。没有不安全的演员阵容,任务本身就无法解决。再读一遍你的句子:
我想创建一个HashMap,它将一个未定义的对象映射到 另一个。两个对象都可以是String或Integer之一。
Java Generics无法为您解决此问题,因为您必须事先知道该类型,否则您必须进行强制转换。
说实话,我不知道你想用你发布的代码实现什么,但是如果你想使用HashMap,你可以这样做:
private final HashMap<String, Integer> left2Right = new HashMap<String, Integer>();
left2Right.put("one", 1);
int numberOne = left2Right.get("one");
在这种情况下,您不必转换值,因为HashMap具有String键和Integer值。如果要将不同类型作为值,则必须使用所有值的超类型。此超类型可能是Object,即层次结构的根。但是在那些情况下你必须施放 - 因为你不知道这个价值是什么类型的对象。
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");
我希望有所帮助。
答案 3 :(得分:0)
P
和E
似乎都没有用于提取器的输入,那你为什么要使用它们呢?只需返回int
和String
即可完成。