有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

如果是,我可以访问另一个泛型参数的泛型参数,而不指定它吗

下面的例子是根据我目前的情况简化的。省略所有成员和方法,因为它们与情况无关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> {}

如果可能的话,不在AbstractRepository上指定Long,写什么来代替两个?????


出于问题范围的考虑,请回答有关泛型的问题,而不是如何以更好的方式实现spring存储库。不过,我很高兴在评论中得到有关这方面的提示


共 (2) 个答案

  1. # 1 楼答案

    也许这正是您试图避免的,但我认为您应该将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的泛型参数进行类型检查

  2. # 2 楼答案

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

    关于泛型的一种(特别有用的)思考方式是它们将类型链接在一起。如果您声明了一个新的typevar并只在一个地方使用它,由于擦除,这实际上是无用的。在两个地方使用它,现在您已经告诉编译器您使用T的两个地方是链接的:它们可以是任何东西,只要它们是相同的东西

    这种思维方式在这里也提供了一些见解:很明显,你希望你的第一个?????链接到你的第二个?????:使它们相等

    这样做的方法是声明一个新的typevar并使用它:

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

    不幸的是,这意味着AbstractRepository现在获得了一个类型变量,我想您不希望发生这种情况

    不幸的是,如果没有类型变量,java无法链接类型

    作为一般的经验法则,如果混合使用类层次结构(扩展事物实现事物的事物)和大量泛型,那么最终会出现大量泛型参数,其中一些参数会感觉像是干巴巴的违规行为。解决方案是要么接受它,要么不做这两件事中的一件(使用组合而不是继承,或者减少正在使用的类型变量,或者将它们移到方法中),或者使用一系列骇人的反射和“警告强制转换”(将内容强制转换为typevar,实际上不会进行任何类型检查,并且往往会在奇怪的地方导致ClassCastException的错误:在行中任何地方都没有强制转换,而不是有错误代码的地方。这导致了漫长而艰巨的错误查找练习