While the definition involving interface Comparable
class B <T extends Comparable<T>>
is well known and instantiable, the same usage does not work in the same manner when extending a class instead of an interface. Here's an example
class G <T extends Box<T>> {
T val;
G(T val) {
this.val = val;
}
}
The above class compiles, but I am unable to find a way to instantiate G. It seems to require an infinite nesting of Box.
G<Box<Box<..>>>
Here is my definition of class Box
class Box <T> {
T val;
Box(T val) {
this.val = val;
}
}
To aid in discussion, here are a few similar examples. I tested all of my code.
The meaning of the following class is clear to me
class D <T extends Box<String>> {
T val;
D(T val) {
this.val = val;
}
}
we can instantiate using
D<Box<String>> d = new D<>( new Box<String> ("hello") );
We can generalize this so that the Box can contain anything
class F <S, T extends Box<S>> {
T val;
F(T val) {
this.val = val;
}
}
we can instantiate using
F<String,Box<String>> f = new F<>( new Box<String> ("hello") );
Back to the original question, what does the following mean and how/can it be instantiated?
class G <T extends Box<T>> {
T val;
G(T val) {
this.val = val;
}
}
This class G was my first attempt to generalize the class D above so that Box can hold any type, not just String. I later came up with class F as the solution to my problem, but I am left wondering what does G mean and why is it different from when T extends SomeInterface<T>
.
If Box
class doesn't have constructor with T
, then you can create a class that extends Box
. For example:
class NewBox extends Box<NewBox> {
...
}
Then you can instantiate G
like:
G<NewBox> g = new G<>(new NewBox());
But in your case Box has constructor Box(T val){...}
, then NewBox
required constructor matching super
like:
class NewBox extends Box<NewBox> {
NewBox(NewBox val) {
super(val);
}
}
To instantiate this you should end up with null, otherwise it will lead to infinite nesting :
G<NewBox> g = new G<>(new NewBox(new NewBox(new NewBox(null))));
Update: to answer your original question: G <T extends Box<T>>
means that T
must be type of Box
or any descendant of Box
. As you correctly mentioned it will lead to infinite nesting. But you still can instantiate this without creating extra class (as above with NewBox
) using Wildcard and null
as a parameter to the constructor of class G
like:
G<?> tg = new G<>(null);