我不知道为什么我不能转换自引用泛型。
在Java中,我有一个自引用泛型。有一堆东西(Intent
用于查找(解决)的那些东西(一个或多个),和战略ResolutionStrategy
S)。
自引用Intent
类型在下面定义。我想在编译时定义只能接受ResolutionStrategy
接受相同意图的类。
public interface Intent<I extends Intent<I, R>, R extends Resolution>
{
void resolve(ResolutionStrategy<I, R> strategy);
R getResolution();
}
因此,解决策略是:
public interface ResolutionStrategy<I extends Intent<I, R>, R extends Resolution>
{
R resolve(I intent);
}
因此,当我使用这些列表时Intent
,我并不在乎它们是什么。但是,我确实想创建表示我的域模型中具体事物的特定类型。这是一个例子:
public class OrgIntent implements Intent<OrgIntent, IdentifiableResolution>
{
public final String name;
public OrgIntent(String name)
{
this.name = name;
}
@Override
public void resolve(ResolutionStrategy<OrgIntent, IdentifiableResolution> strategy)
{
// Do stuff
}
@Override
public IdentifiableResolution getResolution()
{
//Return resolution got from strategy at some point in the past
return null;
}
}
IdentifiableResolution
是的简单无趣的实现Resolution
。
到目前为止一切都很好。然后的计划是为这些Intent
s构建一个漂亮的图形,然后对其进行迭代,然后将它们传递给以ResolutionStrategyFactory
获得解决这些问题的相关策略。但是,我无法投射OrgIntent
任何通用的东西来添加到列表中!
private <I extends Intent<I, R>, R extends Resolution> DirectedAcyclicGraph<Intent<I, R>, DefaultEdge> buildGraph(Declaration declaration) throws CycleFoundException
{
DirectedAcyclicGraph<Intent<I, R>, DefaultEdge> dag = new DirectedAcyclicGraph<>(DefaultEdge.class);
// Does not compile
Intent<I, R> orgIntent = new OrgIntent("some name");
// Compiles, but then not a valid argument to dag.addVertex()
Intent<OrgIntent, IdentifiableResolution> orgIntent = new OrgIntent("some name");
// Compiles, but then not a valid argument to dag.addVertex()
OrgIntent orgIntent = new OrgIntent("some name");
//Then do this
dag.addVertex(orgIntent);
...
有什么想法我应该声明orgIntent
为?
更新
感谢@zapl,我意识到方法定义上的泛型类型参数是一个完整的红色鲱鱼。
这可以编译,但大概意味着我可以以某种方式拥有一个Intent
泛型的泛型,可以将任何旧的废话作为第一个泛型类型?
private DirectedAcyclicGraph<Intent<?, ? extends Resolution>, DefaultEdge> buildGraph(Declaration declaration) throws CycleFoundException
{
DirectedAcyclicGraph<Intent<?, ? extends Resolution>, DefaultEdge> dag = new DirectedAcyclicGraph<>(DefaultEdge.class);
OrgIntent orgIntent = new OrgIntent("some name");
dag.addVertex(orgIntent);
就像zapl在注释中建议的那样,泛型没有提供足够强的类型保证来处理您正在描述的模式。特别是由于Java泛型是非泛型的,因此在将JVMOrgIntent
转换为更通用的类型(Intent<I, R>
)之后,JVM无法恢复更具体的类型()。由于通用类型信息在运行时丢失,因此JVM仅可以依赖于具体的原始类型(Intent
)。
例如,这是相同的原因,即您不能定义具有不同的通用签名但具有相同的具体签名的两个方法,foo(List<String>)
并且foo(List<Integer>)
两者都变得foo(List)
在运行时变得简单,因此编译器不允许您在同一时间定义两个这样的方法班级。
广义上讲(恐怕我不太了解您的用例,更确切地说,解决方案是通过关联的Class
对象或通过显式地将对象与所需的泛型类型关联)TypeToken
。例如,您可能可以使以下签名起作用:
R resolve(Class<I> intentClass, I intent);
有效Java项目29:考虑类型安全的异构容器中提供的建议也应有所帮助:
但是,有时候,您需要更大的灵活性[比固定数量的类型参数]。...的想法是参数化键而不是容器。然后将参数化的密钥提供给容器以插入或检索值。通用类型系统用于确保值的类型与其键一致。
...
Java的类型系统不够强大,无法表达[键和值之间的类型关系]。但是我们知道这是真的,并且当需要检索收藏夹时我们会利用它。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句