Очень мало ситуаций, когда необходима привязка как class Some<E extends Some<E>>
. Большую часть времени люди пишут это, в действительности код не используется в коде, а class Some<E>
будет работать так же хорошо.
Однако существуют некоторые ситуации, в которых оценка в class Some<E extends Some<E>>
фактически используется. Например:
abstract class Some<E extends Some<E>> {
abstract E foo();
Some<E> bar() {
return foo();
}
}
Что касается вашего вопроса - как насчет class Some<E extends Some>
? Ну, первая наиболее вопиющая проблема заключается в том, что вы используете сырой тип. Необработанные типы никогда не должны использоваться в новом коде. Но вы не уверены.
Необработанный тип с указанным выше классом (class Some<E extends Some>
) компилирует с предупреждением (которое вы можете игнорировать на свой страх и риск). Тем не менее, тип raw означает, что с ним можно делать небезопасные вещи.
Требуется некоторое усилие, чтобы продемонстрировать, что это небезопасно. Вот один из них:
abstract class Some<E extends Some> {
abstract E foo();
Some<E> bar() {
return foo();
}
}
class SomeFoo extends Some<SomeFoo> {
SomeFoo foo() { return this; }
}
class SomeBar extends Some<SomeFoo> {
SomeFoo foo() { return new SomeFoo(); }
}
class SomeBaz extends Some<SomeBar> {
SomeBar foo() { return new SomeBar(); }
}
// then in some method:
Some<SomeBar> a = new SomeBaz();
Some<SomeBar> b = a.bar();
SomeBar c = b.foo();
Код компилируется с предупреждениями, но без ошибок, и выдает ClassCastException
во время выполнения.