I have this two interfaces and classes:
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;
}
It all works as desired. But in my opinion second generic parameter in GenericRepository (K) is redundant. Because I know that MyEntity is an Identifiable, I think it would be great if I can finally use it like this:
public class MyService {
private GenericRepository<MyEntity> myEntityRepository;
}
But I'm trying different things without succeeding. Is it possible? If not, why not?
UPDATE: Answering some responses. I think compiler knows something about which type is the generic in MyEntity. For example:
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>"
}
K
matches that of the type parameter inIdentifiable<K>
. Still, you need to declare K to be a generic type parameter (and consequently, pass its actual value at the point of instantiation). This is just how the language works. You are right that this knowledge could in theory be inferred by the compiler, but it is not for now, and for many years yet... if ever (unfortunately, the development of Java is moving only very slowly to that direction...). – Waxman