Java中的自引用泛型
我不明白为什么我不能铸造一个自我引用的泛型 在Java中,我有一个自引用泛型。有很多事情(Java中的自引用泛型,java,generics,nested-generics,Java,Generics,Nested Generics,我不明白为什么我不能铸造一个自我引用的泛型 在Java中,我有一个自引用泛型。有很多事情(Intents)和查找(解决)这些事情的策略(ResolutionStrategys) 下面定义了自参考Intent类型。我希望在编译时定义只能接收接受相同意图的ResolutionStrategy的类 public interface Intent<I extends Intent<I, R>, R extends Resolution> { void resolve(Re
Intent
s)和查找(解决)这些事情的策略(ResolutionStrategy
s)
下面定义了自参考Intent
类型。我希望在编译时定义只能接收接受相同意图的ResolutionStrategy
的类
public interface Intent<I extends Intent<I, R>, R extends Resolution>
{
void resolve(ResolutionStrategy<I, R> strategy);
R getResolution();
}
可识别解析
是解析
的一个简单而无趣的实现
到目前为止一切都很好。然后,计划是为这些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);
...
正如zapl在评论中所建议的,泛型没有提供足够强的类型保证来处理您所描述的模式。特别是因为Java泛型是非具体化的,所以JVM无法在转换为更一般的类型(
Intent
)后恢复更具体的类型(OrgIntent
)。由于泛型类型信息在运行时丢失,JVM只能依赖具体的原始类型(Intent
)
这是同样的原因,例如,您不能定义两个具有不同泛型签名但具有相同具体签名的方法-foo(List)
和foo(List)
在运行时都变得简单foo(List)
,因此编译器不允许您在同一类中定义两个这样的方法
从广义上讲(恐怕我对您的用例理解不够透彻,无法更精确地理解),解决方案是通过关联的或。例如,您可以使用以下签名:
R resolve(Class<I> intentClass, I intent);
R解析(类intentClass,I intent);
中提供的建议也应该有帮助:
但是,有时您需要更大的灵活性[比固定数量的类型参数]。。。。其思想是参数化键而不是容器。然后将参数化键提供给容器以插入或检索值。泛型类型系统用于确保值的类型与其键一致
Java的类型系统不够强大,无法表达[键和值之间的类型关系]。但我们知道这是真的,当我们需要取回最喜欢的东西时,我们会利用它
?我看不出它与您的I
和R
中的任何内容有什么关系code@JeremyKato谢谢不,那不行,因为OrgIntent
本身不是泛型的。@zapl谢谢。你是对的;我想将各种不同的Intent
实现添加到directedacycgraph
中。基本上,图表应该包含任何意图。但是我希望每个意图都有编译时安全性,即传递给它的ResolutionStrategy
的类型。这有意义吗?我的意思是:你可以在列表中存储Double
和Integer
,但你不会得到Double
或Integer
。您只能将它们作为Number
,然后进行运行时类型检查,以确定它们是什么。对于您的DAG,除了基本的意图
和分辨率
之外,您可能无法使用所有优秀的泛型类型。谢谢大家的输入。我并没有忘记通用疯狂的程度,我意识到这是一个相当疯狂的代码!
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);
...
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);
R resolve(Class<I> intentClass, I intent);