package test; public class Base> { private final T value; private final BACK back; public Base(T value, BACK back) { this.value = value; this.back = back; } public BACK pop() { return back; } public T value() { return value; } public static void main(String[] args) throws Exception { new A<>("a", null) // A .push(Boolean.TRUE) // B,?> .push("a") // A,?>,?> .push(Boolean.TRUE) // B,?>,?>,?> .push("a") // A,?>,?>,?>,?> .pop() // !code completion shows B as type returned by pop() .pop() // !code completion shows BACK as type returned by pop() .pop() // !compiler error: "The method pop() is undefined for the type BACK" .pop() .pop(); } } class A> extends Base { public A(String value, BACK back) { super(value, back); } @SuppressWarnings("unchecked") public B push(Boolean b) { return new B<>(b, (IMPL)this); } } class B> extends Base { public B(Boolean value, BACK back) { super(value, back); } @SuppressWarnings("unchecked") public A push(String s) { return new A<>(s, (IMPL)this); } }