2016-11-30 131 views
0

下列类型不产生任何编译器警告:泛型类型参数给出了错误,但通配符类型参数不

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

下面的具体方法产生一个unchecked投编译器警告:

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(); 

我想知道如果有一种方法来定义方法头本身,具有泛型类型,而不定义它的类。而且,我很好奇为什么通配符声明不给与警告,而是“等价的”泛型声明。

+0

在通配符示例中,“SubType.class”必须是“类”类型。然而,在泛型中,程序没有办法隐式知道“SubType.class”是否真的扩展了'BaseType',所以它会给出警告。至于避免这种情况的方法,我想不出来。 – Mat

回答

1

这两者是非常不同的。

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

在第二种情况下,该方法是一种通用方法,并且T是该方法的类型变量。这意味着来电者可以选择T以达到任何想要的效果,并希望该方法可以神奇地与T一起使用。值得注意的是,该方法没有收到任何参数,这意味着该方法在运行时没有任何关于什么的信息,并且必须知道如何返回Class<T>。显然,这是不可能的,除非它总是返回null

+0

是不是两个例子擦除到 公共类 getSubclassType(){ return(Class )SubType.class; } – KyleM

+0

@KyleM:两者的擦除都相同:'public class getSubclassType(){ return SubType.class; }',但这是无关紧要的。调用者可以在每种类型签名的泛型中做的事情是非常不同的。 – newacct

+0

实际上是完美的感觉。换句话说(就我的理解而言,你的解释很棒)......在第二个例子中,调用者可以指定他们想要的任何类型,并期望该方法返回该类型。然而,这显然是不可能的,因为它在运行时没有那种类型的信息。相反,在我的第一个例子中,调用者只知道返回的类型扩展了BaseType;并且不能对该类型做出额外的假设。 – KyleM