在继承期间获取泛型参数的泛型参数

fcy6dtqo  于 2021-07-08  发布在  Java
关注(0)|答案(2)|浏览(320)

如果可以,我如何访问另一个泛型参数的泛型参数,而不指定它?
下面的例子是根据我目前的情况简化的。所有成员和方法都被省略,因为它们与情况无关。 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> {}

未指定 LongAbstractRepository ,写什么代替这两个 ????? ,如果可能的话?
出于问题范围的考虑,请回答关于泛型的问题,而不是如何更好地实现spring存储库。不过,我很高兴在评论中得到一些提示。

nzk0hqpo

nzk0hqpo1#

也许这正是您试图避免的,但我认为您应该指定 AbstractEntity 作为中的参数 AbstractRepository ,类似于:

interface LibraryRepository<ENTITY, ID> {}

abstract class AbstractEntity<ID> {}

class ConcreteEntity extends AbstractEntity<Long> {}

interface AbstractRepository<ENTITY extends AbstractEntity<ID>, ID>
          extends LibraryRepository<ENTITY, ID> {}

interface ConcreteRepository extends AbstractRepository<ConcreteEntity, Long> {}

我不知道如果不是这样,编译器如何才能对泛型参数进行类型检查 LibraryRepository .

qvtsj1bj

qvtsj1bj2#

interface AbstractRepository<ENTITY extends AbstractEntity<?????>> extends LibraryRepository<ENTITY, ?????> {} 关于泛型的一种(特别有用的)思考方式是它们将类型链接在一起。如果您声明了一个新的typevar并且只在一个地方使用它,由于擦除的原因,这实际上是无用的。在两个地方使用它,现在您已经告诉编译器 T 链接:它们可以是任何东西,只要它们是相同的东西。
这种思维方式在这里也提供了一些见解:显然你想要你的第一个 ????? 与你的第二个 ????? :使它们相等。
这样做的方法是声明一个新的typevar并使用它:

interface AbstractRepository<ENTITY extends AbstractEntity<Q>, Q>
   extends LibraryRepository<ENTITY, Q> {}

不幸的是,这意味着 AbstractRepository 现在得到了一个类型变量,我想你不希望这样。
不幸的是,如果没有类型变量,java无法链接类型。
一般的经验法则是,如果混合使用类层次结构(扩展实现对象的对象)和大量的泛型,那么最终会得到大量的泛型参数,其中一些参数会让人觉得完全违反了规则。解决方法是要么接受它,要么不做这两件事中的任何一件(使用组合而不是继承,或者减少正在使用的类型变量,或者将它们移到方法中),或者使用一堆hacky反射和“警告强制转换”(在这种情况下,您将事情强制转换到typevar,而typevar实际上并不进行任何类型检查,而且往往会导致错误 ClassCastException 在一些奇怪的地方:那些甚至没有强制转换的地方,而不是那些有错误代码的地方。导致了漫长而艰巨的猎虫演习。

相关问题