Это на самом деле не проблема с генериками. Правила наследования JLS не позволяют отображать закрытые поля в подклассах. Поскольку X является закрытым, он не является членом типа O
, даже если он является членом типа Test<O>
, а O
является подтипом Test<O>
. Если вы использовали код как:
public final O withX(int x) {
Test<O> created = clone();
created.x = x;
return (O) created;
}
Это будет работать. Это случай, когда LSP не поддерживается Java, но это только локальная проблема с системой типов, поскольку частные поля доступны только для объектов того же типа. Если бы это не сработало, тогда частные поля не были бы частными. Я не думаю, что иметь специальное исключение из правил для рекурсивных шаблонов - это хорошая идея.
Обратите внимание, это никогда не является ограничением того, что вы можете сделать. Вы всегда можете преобразовать подтип до супертипа, когда хотите внести изменения, как в альтернативном коде.