加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java泛型与工厂

发布时间:2020-12-14 06:04:00 所属栏目:Java 来源:网络整理
导读:建立: 我有一些格式化程序的接口: interface FormatterT extends AbstractItem { String format(T item);} 我有一个工厂创建这样的格式化程序: public class Factory { public static Formatter? extends AbstractItem create() { switch (something) { c
建立:

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

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: }

项列表仅包含格式化程序能够处理的AbstractItem子类型.

问题:

我收到两个警告:

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是抽象的,所以我传递给格式化程序的项目总是某种类型扩展AbstractItem …

我该如何向编译器解释这个?现在我的解决方案是使用@SuppressWarnings ……

解决方法

通过声明方法
public static Formatter<? extends AbstractItem> create()

你声明这个方法的调用者永远不会知道Formatter的确切类型;调用者只会知道它是格式化程序< X>.其中X是AbstractItem或它的子类.因此,您无法将任何实例传递给返回的Formatter,因为您永远不知道格式化程序可以处理哪个X.

在这里取消警告绝对是错误的,编译器告诉你正确的事情:你的代码是不安全的.给定AbstractItem,Foo和Bar的两个子类,工厂可以返回Formatter< Foo>并且您可以将Bar的实例传递给其格式方法.

存在语义问题,没有指示您的工厂将返回什么格式化程序以及原因.要么让它成为一个具体工厂,要么返回Formatter< X>其中X是具体类型而不是?扩展…或者您必须添加一个参数以向工厂提供提示,需要哪种格式化程序,例如

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

或者你把它变成了

public static Formatter<AbstractItem> create()

指定返回的Formatter可以处理各种AbstractItem.请记住,您仍然可以将AbstractItem的任何子类传递给Formatter< AbstractItem>因为AbstractItem的子类的每个实例也仍然是AbstractItem的一个实例,就像在Generics之前的时代一样.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读