我用这种方法来获取片段,
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>
有什么问题?
答案 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()
方法返回实例。