返回泛型类型的Java方法需要@SuppressWarnings(“unchecked”)和(T)new Result()

时间:2014-02-14 14:17:27

标签: java android generics

我用这种方法来获取片段,

abstract <T extends Fragment & IMyItem> T createFragment();

public <T extends Fragment & IMyItem> T getFragment() {
    return createFragment();
}

@Override
<T extends Fragment & IMyItem> T createFragment() {
    return new MyPageFragmentImpl();
}

在eclispe上,这种方法说

类型不匹配:无法从MyPageFragmentImpl转换为T

但是MyPageFragmentImpl的定义是

public final class MyPageFramgmentImpl extends Fragment implements IMyItem

我认为任何课程

extends Fragment implements IMyItem

必须没问题
<T extends Fragment & IMyItem> 

有什么问题?

1 个答案:

答案 0 :(得分:5)

  

我认为“扩展Fragment实现IMyItem”的任何类都必须正常

任何此类都是类型参数T的有效替代,这就是问题所在。现在假设您有另一个类:

class AnotherFragment extends Fragment implements IMyItem { }

然后你将这种方法称为:

AnotherFragment anotherFragment = createFragment();

此调用将在编译时传递。但是假设编译器允许您从方法返回new MyPageFragmentImpl();,那么赋值将在运行时失败ClassCastException,因为MyPageFragmentImpl不是AnotherFragment

您必须从该方法返回类型T的结果,并且类型参数T将从您为其分配结果的引用类型推断出来。那么,重点是,您将如何创建T的实例?你不能直接这样做。一种可能性是将Class实例传递给该方法,并将签名更改为:

@Override
<T extends Fragment & IMyItem> T createFragment(Class<T> clazz) {
    return clazz.newInstance();
}

现在,无论您希望该方法返回什么实例,只需将该类的Class实例传递给此方法,如下所示:

MyPageFragmentImpl pageFragment = createFragment(MyPageFragmentImpl.class);

在这种情况下,类型参数T将被推断为MyPageFragmentImpl,如上所述的分配现在是安全的。

如果您的类没有0-arg构造函数,则可能会失败。为此,您可以使用Class#getConstructor()方法为该类获取适当的构造函数,然后使用Constructor#newInstance()方法返回实例。