问题
A friend of mine found this tidbit in the Java API (https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html),
Class Enum<E extends Enum<E>>
and by reading the following article https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html I could understand what the aforementioned line entailed syntactically but from the examples given I could not figure out a use case for this beyond the Enum class (reviewed the source).
I'd like to learn more about possible problems where the above may present a solution.
回答1:
It's for example useful to to allow subclasses to use their own type
Imagine a class like
class Node {
Node next;
}
if you extend that class, you're stuck with Node
.
class SpecialNode extends Node {
void foo() {
// euwww
SpecialNode nextNode = (SpecialNode) this.next;
}
}
You also can't just define it like
class Node<T> {
T next;
}
because that would allow anything for T
. You really want a T
that extends Node
or you can no longer use T as Node
from within Node
without casting. It would work for child classes though.
By using recursive bounds like
class Node<T extends Node<T>> {
T next;
}
You limit T to yourself or subclasses of yourself which then allows you to do
class SpecialNode extends Node<SpecialNode> {
void foo() {
SpecialNode nextNode = this.next; // type-safe!
}
}
That way both parent and child class can access everything on their abstraction level fully typesafe.
回答2:
This idiom almost always means 'E should be the type of the subclass'. For example, you might notice that Enum implements Comparable<E>
.
When the class is extended, you get to something like:
// E extends Enum<E> ┐
class AnEnum extends Enum<AnEnum> {...}
Now AnEnum is also a Comparable<AnEnum>
and getDeclaringClass returns a Class<AnEnum>
.
I've seen this idiom related to the curiously recurring template pattern. The intent is that the superclass can refer to the subclass generically.
(Due to the fact that the subclass of Enum is generated by the compiler, I don't think there is actually a reason Enum in particular needed to be declared this way. It could have just been Enum<E>
.)
回答3:
Generally it's useful for defining some behavior in a superclass (e.g. in Enum
) which depends on type information specific to a subtype of the class in question (I actually asked a similar question a wee while ago).
来源:https://stackoverflow.com/questions/27177106/uses-of-recursive-type-bounds