【问题标题】:Generic type parameter gives error, but wildcard type parameter does not泛型类型参数会出错,但通配符类型参数不会
【发布时间】:2016-11-30 17:34:20
【问题描述】:

以下类型不会产生任何编译器警告:

public abstract Class<? extends BaseType> getSubclassType();
@Override
    public Class<SubType> getSubclassType() {
        return SubType.class;
    }

以下具体方法会产生未经检查的强制转换编译器警告:

public abstract <T extends BaseType> Class<T> getSubclassType();

    @Override
    public  <T extends BaseType> Class<T> getSubclassType() {
        return (Class<T>) SubType.class;
    }

有没有办法用泛型类型参数定义方法(在基类中)并在子类中返回适当的具体类型而不产生编译器警告?显然,我上面给出的两个示例都可以正常工作,我只是想知道是否有更正确的方法来定义该方法。注意:我确实知道我可以执行以下操作:

public abstract class BaseClass <T extends BaseType> 
public abstract Class<T> getSubclassType();

我想知道是否有一种方法可以使用泛型类型定义方法标头本身,而无需在类上定义它。而且,我很好奇为什么通配符声明没有给出警告,但“等效”通用声明却给出了警告。

【问题讨论】:

  • 在通配符示例中,SubType.class 的类型必然是 Class&lt;SubType&gt;。但是,在通用程序中,程序无法隐式知道SubType.class 是否真的扩展了BaseType,因此它会发出警告。至于避免这种情况的方法,我想不出。

标签: java generics


【解决方案1】:

两者有很大的不同。

在第一个中,调用者不知道返回的Class 的类型参数是什么。除了扩展BaseType 之外,调用者不能对该类型参数做出任何假设。该方法可以选择返回一个Class,其类型参数是它想要的BaseType 的任何子类型,调用者不知道。

第二种情况,方法是泛型方法,T是方法的类型变量。这意味着调用者可以选择T 成为它想要的任何东西,并期望该方法能够神奇地与T 一起工作。值得注意的是,该方法不接收任何参数,这意味着该方法在运行时根本没有任何关于T 是什么的信息,并且必须以某种方式找出如何返回Class&lt;T&gt;。显然,这是不可能的,除非它总是返回null

【讨论】:

  • 不是将示例两种类型擦除到 public Class getSubclassType() { return (Class) SubType.class; }
  • @KyleM:两者的擦除是相同的:public Class getSubclassType() { return SubType.class; },但这无关紧要。调用者可以在泛型中使用每种类型签名执行的操作非常不同。
  • 实际上非常有意义。换个说法(只是为了我的理解,你的解释很好)......在第二个例子中,调用者可以指定他们想要的任何类型,并期望该方法返回该类型。然而,这显然是不可能的,因为它在运行时没有该类型信息。相反,在我的第一个示例中,调用者只知道返回的类型为扩展 BaseType;并且不能对类型做出额外的假设。
猜你喜欢
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多