如果可以,我如何访问另一个泛型参数的泛型参数,而不指定它?
下面的例子是根据我目前的情况简化的。所有成员和方法都被省略,因为它们与情况无关。 LibraryRepository
jpa/spring类型是否需要 ENTITY
和一个 ID
.
abstract class AbstractEntity<ID> {}
class ConcreteEntity extends AbstractEntity<Long> {}
interface AbstractRepository<ENTITY extends AbstractEntity<?????>> extends LibraryRepository<ENTITY, ?????> {}
//Desired declaration:
interface ConcreteRepository extends AbstractRepository<ConcreteEntity> {}
未指定 Long
在 AbstractRepository
,写什么代替这两个 ?????
,如果可能的话?
出于问题范围的考虑,请回答关于泛型的问题,而不是如何更好地实现spring存储库。不过,我很高兴在评论中得到一些提示。
2条答案
按热度按时间nzk0hqpo1#
也许这正是您试图避免的,但我认为您应该指定
AbstractEntity
作为中的参数AbstractRepository
,类似于:我不知道如果不是这样,编译器如何才能对泛型参数进行类型检查
LibraryRepository
.qvtsj1bj2#
interface AbstractRepository<ENTITY extends AbstractEntity<?????>> extends LibraryRepository<ENTITY, ?????> {}
关于泛型的一种(特别有用的)思考方式是它们将类型链接在一起。如果您声明了一个新的typevar并且只在一个地方使用它,由于擦除的原因,这实际上是无用的。在两个地方使用它,现在您已经告诉编译器T
链接:它们可以是任何东西,只要它们是相同的东西。这种思维方式在这里也提供了一些见解:显然你想要你的第一个
?????
与你的第二个?????
:使它们相等。这样做的方法是声明一个新的typevar并使用它:
不幸的是,这意味着
AbstractRepository
现在得到了一个类型变量,我想你不希望这样。不幸的是,如果没有类型变量,java无法链接类型。
一般的经验法则是,如果混合使用类层次结构(扩展实现对象的对象)和大量的泛型,那么最终会得到大量的泛型参数,其中一些参数会让人觉得完全违反了规则。解决方法是要么接受它,要么不做这两件事中的任何一件(使用组合而不是继承,或者减少正在使用的类型变量,或者将它们移到方法中),或者使用一堆hacky反射和“警告强制转换”(在这种情况下,您将事情强制转换到typevar,而typevar实际上并不进行任何类型检查,而且往往会导致错误
ClassCastException
在一些奇怪的地方:那些甚至没有强制转换的地方,而不是那些有错误代码的地方。导致了漫长而艰巨的猎虫演习。