ОПИСАНИЕ ОТВЕТА
На основе ответов @Ruslan
и @Some Name
и комментариев на вопрос, здесь приводится краткий обзор различий между
class G <T extends SomeClass<T>>
class B <T extends SomeInterface<T>>
class Enum<E extends Enum<E>>
. Я обнаружил, что написаниепомогает проверенные примеры.
1.class G <T extends SomeClass<T>>
Класс G
требует, чтобы тип T
был определен как
class T extends SomeClass<T> {}
Вот пример класса, подобного T
class RussianBox extends Box<RussianBox> {
RussianBox(RussianBox box) {
super(box);
}
}
где класс Box
определяется как
class Box <T> {
T value;
Box(T value) {
this.value = value;
}
public String toString() {
return this.getClass().getSimpleName()+" containing {"+this.value+"}";
}
}
Вот пример класса, подобного G
class RussianBoxContainer <T extends Box<T>> {
T value;
RussianBoxContainer(T value) {
this.value = value;
}
public String toString() {
return this.getClass().getSimpleName()+" containing {"+this.value+"}";
}
}
В следующем коде создаются эти три класса
Box<String> box = new Box<>("Gold");
out.println("box = " + box );
RussianBox russianBox = new RussianBox( new RussianBox(null) );
out.println("russianBox = " + russianBox );
RussianBoxContainer<RussianBox> containerForARussianBox = new RussianBoxContainer<>(russianBox);
out.println("containerForARussianBox = " + containerForARussianBox );
и выдает следующий вывод
box = Box containing {Gold}
russianBox = RussianBox containing {RussianBox containing {null}}
containerForARussianBox = RussianBoxContainer containing {RussianBox containing {RussianBox containing {null}}}
2.class B <T extends SomeInterface<T>>
Класс B
требует, чтобы тип T
был определен как
class T extends SomeClass implements SomeInterface<T> {}
Класс java.lang.Integer
является примером класса, подобного T
class Integer extends Number implements Comparable<Integer>
Таким образом, этот шаблон ведет себя очень по-разному при обращении к интерфейсу вместо класса.
3.class Enum<E extends Enum<E>>
Теперь создайте класс , например Enum
.Вот пример
class RussianBoxContainer2 <T extends RussianBoxContainer2<T>> {
RussianBoxContainer2<T> value;
RussianBoxContainer2(RussianBoxContainer2<T> box) {
this.value = box;
}
public String toString() {
return this.getClass().getSimpleName()+" containing {"+this.value+"}";
}
}
Как и Enum
, нам нужно создать подкласс RussianBoxContainer2
, прежде чем мы сможем использовать RussianBoxContainer2
.Вот пример подкласса
class RussianBox2 extends RussianBoxContainer2<RussianBox2> {
RussianBox2(RussianBox2 box) {
super(box);
}
}
В следующем коде создаются экземпляры этих двух классов
RussianBox2 russianBox2 = new RussianBox2(new RussianBox2(null));
out.println("russianBox2 = " + russianBox2 );
RussianBoxContainer2<RussianBox2> containerForARussianBox2 = new RussianBoxContainer2<>(russianBox2);
out.println("containerForARussianBox2 = " + containerForARussianBox2 );
и выдается следующий вывод
russianBox2 = RussianBox2 containing {RussianBox2 containing {null}}
containerForARussianBox2 = RussianBoxContainer2 containing {RussianBox2 containing {RussianBox2 containing {null}}}