Java泛型与工厂

向量

建立:

我有一些格式化程序的接口:

interface Formatter<T extends AbstractItem> {
  String format(T item);
}

我有一家工厂创建此类格式化程序:

public class Factory {
  public static Formatter<? extends AbstractItem> create() {
    switch (something) {
      case SOMETHING: return new Formatter<SomeItem>() { String format(SomeItem item) {...}};
      case SOMETHING_ELSE: return new Formatter<OtherItem>() { String format(OtherItem item){...}};
    }

现在,我使用这个工厂来获取格式化程序并使用它:

1: Formatter formatter = Factory.create();
2: for (AbstractItem item : items) {
3:   formatter.format(item);
4: }

items列表仅包含能够处理的AbstractItem子类型formatter

问题:

我收到两个警告:

Line 1: Formatter is a raw type. References to generic type Formatter<T> should be parameterized.
Line 3: Type safety: The method format(AbstractItem) belongs to the raw type Formatter. References to generic type Formatter<T> should be parameterized.

好的,所以我尝试修复第一个:我知道工厂返回了以下内容AbstractItem

1: Formatter<? extends AbstractItem> formatter = Factory.create();

现在,第1行的警告消失了,但是第3行出现了新的错误:

Line 3: The method format(capture#3-of ? extends AbstractItem) in the type Formatter<capture#3-of ? extends AbstractItem> is not applicable for the arguments (AbstractItem).

因此,如果我理解正确,那就抱怨它AbstractItem不是AbstractItem(根据类型约束中的要求)的子类型<? extends AbstractItem>足够公平,但是AbstractItem很抽象,所以item我传递给的formatter总是某种扩展AbstractItem...

我该如何向编译器解释?目前,我的解决方案是使用@SuppressWarnings...

霍尔格

通过声明方法

public static Formatter<? extends AbstractItem> create()

您声明此方法的调用者永远不会知道的确切类型Formatter主叫方将只知道它是一些Formatter<X>地方XAbstractItem或它的子类。因此,您无法将任何实例传递给返回的对象,Formatter因为您永远不知道X格式化程序可以处理哪个实例

在这里取消警告是绝对错误的,编译器会告诉您正确的事情:您的代码不安全。鉴于两个子类AbstractItemFooBar工厂可以返回Formatter<Foo>,你可以通过实例Barformat的方法。

语义上存在一个问题,即没有指示Formatter您的工厂将返回什么以及原因的指标。您是将其设为具体工厂Formatter<X>,而不是返回X是具体类型,? extends …还是必须添加参数以向工厂提供提示,即需要哪种格式化程序,例如

public static <T extends AbstractItem> Formatter<T> create(Class<T> forItemType)

或者你把它变成

public static Formatter<AbstractItem> create()

指定返回的Formatter可以处理所有类型的AbstractItem只需记住,您仍然可以将的任何子类传递AbstractItem给,Formatter<AbstractItem>因为的子类的每个实例AbstractItem也仍然是的实例AbstractItem,就像在泛型时代之前一样。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章