冗余通用参数

sin*_*pop 9 java generics

我有这两个接口和类:

public interface Identifiable<T> {
    T getId();
}

public interface GenericRepository<T extends Identifiable<K>, K> {
    T get(K id);
}

public class MyEntity implements Identifiable<Long> {

    private Long id;

    public Long getId() {
        return id;
    }
}

public class MyService {
    private GenericRepository<MyEntity, Long> myEntityRepository;
}
Run Code Online (Sandbox Code Playgroud)

一切都按预期工作.但在我看来,GenericRepository(K)中的第二个泛型参数是多余的.因为我知道MyEntity是一个可识别的,我认为如果我最终能像这样使用它会很棒:

public class MyService {
    private GenericRepository<MyEntity> myEntityRepository;
}
Run Code Online (Sandbox Code Playgroud)

但是我没有成功就尝试了不同的事情.可能吗?如果没有,为什么不呢?

更新:回答一些回复.我认为编译器知道MyEntity中哪种类型是通用的.例如:

public class MyEntityGenericRepository implements GenericRepository<MyEntity, Long> {
    // compiles...
}

public class MyEntityGenericRepository implements GenericRepository<MyEntity, String> {
    // compiler says: "Bound mismatch: The type MyEntity is not a valid substitute for the bounded parameter <T extends Identifiable<K>> of the type GenericRepository<T,K>"
}
Run Code Online (Sandbox Code Playgroud)

Pét*_*rök 7

我认为你不能省略它.随着T extends Identifiable<K>你想说的是,泛型类型参数必须是Identifiable.由于Identifiable是泛型类,您还需要提及其泛型类型参数(如果您希望按照规则进行播放 - 如果省略它GenericRepository,则由于向后兼容性规则,您将失去所有泛型类型安全性).另请注意,K它实际上用作参数类型GenericRepository.get.由于该类型可能不同T,您需要通过将其声明为另一个泛型类型参数来满足编译器GenericRepository.否则编译器无法知道是什么K.

  • @sinuhepop,当然编译器可以检查`K`的实际类型是否与`Identifiable <K>`中的type参数匹配.但是,您需要*声明*K为泛型类型参数(因此,在实例化时传递其实际值).这就是语言的工作原理.你是对的,这个知识*理论上可以由编译器来推断,但它现在还不是,而且多年来......如果有的话(不幸的是,Java的发展只是非常缓慢地向这个方向发展). ..). (3认同)