冗余通用参数
我有这两个接口和类:
public interface Identifiable { T getId(); } public interface GenericRepository<T extends Identifiable, K> { T get(K id); } public class MyEntity implements Identifiable { private Long id; public Long getId() { return id; } } public class MyService { private GenericRepository myEntityRepository; }
这一切都按预期工作。 但在我看来,GenericRepository(K)中的第二个generics参数是多余的。 因为我知道MyEntity是一个可识别的,我认为如果我最终能像这样使用它会很棒:
public class MyService { private GenericRepository myEntityRepository; }
但是我没有成功就尝试了不同的事情。 可能吗? 如果没有,为什么不呢?
更新:回答一些回复。 我认为编译器知道MyEntity中哪种类型是通用的。 例如:
public class MyEntityGenericRepository implements GenericRepository { // compiles... } public class MyEntityGenericRepository implements GenericRepository { // compiler says: "Bound mismatch: The type MyEntity is not a valid substitute for the bounded parameter <T extends Identifiable> of the type GenericRepository" }
我认为你不能省略它。 使用T extends Identifiable
您想要说generics类型参数必须是可Identifiable
。 由于Identifiable
是generics类,因此您还需要提及其generics类型参数(如果您希望按照规则进行播放 – 如果省略它,则由于向后兼容性规则,您将失去GenericRepository
所有generics类型安全性)。 另请注意, K
实际上用作GenericRepository.get
的参数类型。 由于该类型可能与T
不同,因此您需要通过将其声明为GenericRepository
另一个generics类型参数来满足编译器。 否则编译器无法知道K
是什么。
从GenericRepository类的角度来看,这并不是多余的。 当它有像T get(K id)
,它无法知道它可以接受哪种类型的id
参数。 你可以写下面的内容:
interface GenericRepository> { T get(Object id); }
现在您不必将Long
作为类型参数编写,但是您无法检查在编译时是否正确使用了get
方法。 因此类型变量用于特定目的。
至于字段声明,当你有generics类型时,你必须指定它使用的所有类型变量。 当然,如果语言能够理解其中一个参数值可以从另一个参数值中推断出来,那么你可以说它会很整洁,但这是值得商榷的。
除了引入只改进GenericRepository的接口之外,你无能为力
public interface LongKeyedRepository> extends GenericRepository { { //No new methods need to be defined }
然后你就可以拥有
private LongKeyedRepository myEntityRepository;
等等
如果我没有弄错,那么generics将被编译为好像它们只是Object
。 现在语法被(硬)检查以确保你没有把苹果与橘子一起使用,因为在Java的初始设计之后添加了generics。 这就是为什么generics如此受限……
它可以使用(即编译)
public interface GenericRepository { T get(T id); }
但它仍然说可识别是一种原始类型,它应该是参数化的。
希望能帮助到你。
为什么你不能删除第二个K,
public interface GenericRepository, K> {
因此,我们不应该像上面那样拥有它
public interface GenericRepository> {
通过这个我们可以做你想做的事。