Reputation: 23490
Why does the below code fail to compile? Can this example be simplified (to fewer classes) to demonstrate equivalent error?
The error message produced is:
func(capture of ? extends A) in ... cannot be aplied to B
private static interface A {}
private static class B implements A {}
private static class C<T> {
private final T t;
private C(T t) {
this.t = t;
}
private void func(T t) {}
}
@Test
public void doTest() {
B b = new B();
C<? extends A> c = new C<B>(b);
c.func(b); // fails here
}
Upvotes: 0
Views: 241
Reputation: 523724
That line must fail, otherwise this obviously-wrong code can compile:
private static interface A {}
private static class B implements A {}
private static class B2 implements A {}
@Test
public void doTest() {
B b = new B();
B2 b2 = new B2();
C<? extends A> c = new C<B2>(b2); // B2 extends A, ok.
c.func(b); // B extends A, but B is not B2, and it should fail.
}
Upvotes: 3
Reputation: 1503519
The problem is that C<? extends A>
means "It's a C<T>
for some type T
, but I don't know which type it is - only that it's something which extends A
."
That means you can't assume that T = B
, or that there's a conversion from B
to T
. But that's exactly what you do try to assume here:
c.func(b);
To demonstrate why it's invalid, suppose we make a change to your code:
private static class X implements A {}
B b = new B();
C<? extends A> c = new C<X>(new X());
c.func(b);
Now it's more obvious that it shouldn't compile - if you've got a C<X>
, you don't expect to be able to call func(b)
where b
is a B
, do you? So given that I've only changed the right-hand side of the assignment (not the declared type of c
) it would be very odd for your example to compile but mine not to. Does that help?
As ever, see the Java Generics FAQ for more information, particularly the part about wildcards.
Upvotes: 5