I would like to know how to write a class in Java that has a nested template parameter. This question describes nested, template parameters, but assumes that wildcards will be used. I would like to name all the types involved, so I don't want to use wildcards. Note that I understand that the wildcards are used for covariance. I am perfectly fine with my templated type being invariant as long as I know the types it's made out of. Below is an example of code that compiles, but doesn't give me all the information I want.
public class Parent<B> {
public B b;
public Parent(B b) {
this.b = b;
}
}
public class Child<B> extends Parent<B> {
public Child(B b) {
super(b);
}
}
public class Foo<ParentType extends Parent, B> {
public ParentType parent;
public B otherItem;
public Foo(ParentType parent, B otherItem) {
this.parent = parent;
this.otherItem = otherItem;
}
}
public class Main {
public static void main(String[] args) {
Parent<String> stringParent = new Parent<>("hello");
Child<Integer> intChild = new Child<>(5);
Foo<Parent, String> foo = new Foo<>(stringParent, "bonjour");
Foo<Child, Integer> childFoo = new Foo<>(intChild, 42);
Object b = foo.parent.b;
System.out.println(b + ", " + b.getClass());
}
}
I am forced to declare the type of foo.parent.b
as an Object
, even though I know it is a String
(and the program knows it too: the output is hello, class java.lang.String
). I would like to write the code more like this:
public class Foo<ParentType extends Parent, B> {
public ParentType<B> parent;
// ^ (5:12)
public B otherItem;
public Foo(ParentType<B> parent, B otherItem) {
// ^ same error here
this.parent = parent;
this.otherItem = otherItem;
}
}
or something along those lines, explicitly forcing parent
's type to be linked to B
, but IntelliJ complains Type 'ParentType' does not have type parameters
and the compiler gives the error:
Error:(5, 12) java: unexpected type
required: class
found: type parameter ParentType
The locations where the error occurs are marked above.