Reputation: 118
I have following code:
public class A {}
public class B extends A {}
public class C <T extends A> {
private final T data;
public C(final T data) {
this.data = data;
}
}
public class D<T extends B> extends C<T> {
public D(T data) {
super(data);
}
public D() {
this(new B());
}
public static D<B> create() {
return new D(new B());
}
}
There is a compile error in the class D:
error: no suitable constructor found for D(B)
this(new B());
constructor D.D() is not applicable
(actual and formal argument lists differ in length)
constructor D.D(T) is not applicable
(actual argument B cannot be converted to T by method invocation conversion)
where T is a type-variable:
T extends B declared in class D
What is confusing me is the fact, that the static method D.create() that does basically the same is compiled without any errors. Can anyone explain this error? And the difference between D() and D.create()?
Upvotes: 3
Views: 155
Reputation: 51343
Because generic type T
of class D
is not bound
This will work
public class E extends D<B> {
public E() {
super(new B()); // call to D's constructor public D(T data)
}
}
normally you would call the constructor of D
in this way:
new D<B>(new B());
but you CAN NOT do this
public D() {
this<B>(new B());
}
Another example.
Change the code a little bit and you will see the problem.
class BBB extends B {
}
class C<T extends A> {
protected final T data;
public C(final T data) {
this.data = data;
}
}
class D<T extends B> extends C<T> {
public D() {
this(new B());
}
public T getData(){
return data;
}
}
D<BBB> dOfBBB = new D<BBB>();
BBB data = dOfBBB.getData(); // So if this(new B()) would work
// how can the data then be returned?
// Because BBB is returned but it would be
// initialized with only a B instance
Upvotes: 1
Reputation: 424983
The error is there because for class D
it is not known that the type will be B
, only that the generic type will extend B
- you have assumed it's going to be B
because there are no other classes (yet) in your class hierarchy (a fact that the compiler must consider may change in the future).
Note that in the factory method you are instantiating the raw type for D
(one without a generic parameter). Instead, provide a type:
You should change:
public static D<B> create() {
return new D(new B());
}
to:
public static D<B> create() {
return new D<B>(new B()); // Note: Added generic parameter <B>
}
Upvotes: 4