| The type signature for Session.getReference is inherited from EntityManager and promises to return a T. The User Guide contains an example snippet where this guarantee is violated. Since this behavior is surprising, it should be documented at the Javadoc of that method. Is this surprise also the reason that the unit test uses the complicated Identifiable.class.isInstance(book) instead of the simpler book instanceof Identifiable? When I write the latter in IntelliJ, it warns me that the expression is always true (which it is). It also warns me that book instanceof Book is always true because of the method's type signature. But that warning is wrong since the JVM does not ensure the correct type in this situation. Minimal example:
public class TypeInferenceDemo {
interface HasId {
Long getId();
}
static class Entity implements HasId {
public Long getId() {
return 1L;
}
}
interface Session {
<T> T getReference(Class<T> clazz, Object id);
}
static class SessionImpl implements Session {
public <T> T getReference(Class<T> clazz, Object id) {
return (T)(HasId)(() -> 1L);
}
}
static class Application {
public static void main(String[] args) {
Session session = new SessionImpl();
HasId entity = session.getReference(Entity.class, 1L);
System.out.println(entity);
}
}
}
Almost every Java developer and also the IDE developers assume that a method declared as returning a T indeed returns a T. Since Session.getReference violates this assumption in an actual documented use case, this should be documented. |