Wildcard and type pameter bounds in java
Asked Answered
H

3

6

Consider this case:

class A {}

class B<T extends A, E extends T> {
    B<?, A> b;
    B<?, ? extends A> b2;
}

As I understand type bounds, in this case effective upper bounds of both T and E is class A. So the question: why javac doesn't accept class A as argument in declaration of field b, but accepts wildcard ? extends A in declaration of field b2?

Hardin answered 28/12, 2018 at 13:37 Comment(6)
I use jdk 1.8.0 161Hardin
Can you share your test code ?Oliverolivera
@xtratic I'm using JDK 11 and Intellij says Type parameter 'Test.A' is not within its bound; should extend '?'. If it compiles for you, then it could potentially be a bug in Intellij.Cooke
Ideone says: error: type argument A is not within bounds of type-variable E worked ok in local (eclipse, jdk1.8.0_171)Parts
I have updated jdk to latest 1.8.0_191. And I get the same problem I described above.Hardin
As @Jacob G. says, I suspect it's a bug that this isn't a compile error for Eclipse JDT compiler (Eclipse 4.9.0 for me). I think this is a valid compile error, I'll try to explain why in an answer.Sausauce
S
1

With the following classes:

class A {}
class C extends A {}
class B<T extends A, E extends T> {}

Think of it like this:

E extends T extends A
With B<?,A> then T -> ? and E -> A
A extends ? extends A
Where the ? could be any subclass of A, let's say C.
A extends C extends A is clearly invalid.
So that's why it's a compile error.


Note for Eclipse users:

Eclipse 4.9.0 compiler disagreed with javac 8u and Intellij and did not emit a compile error for the generic arguments in B<?,A>. I assume this is a bug in the Eclipse compiler but I have not consulted the JLS to confirm this.

class B<T extends A, E extends T> {
    B<?, A> b; // <-- Eclipse does NOT emit a compile error
    B<?, ? extends A> b2;
}

This assumed bug has been reported here.

Sausauce answered 28/12, 2018 at 14:37 Comment(0)
I
1

Your declaration is incorrect. You are missing the point of 'wildcard'-s. They are used for unknown property declaration. For B<?, E> b the E must extend the T and the T must extend the A but you said that the first generic type is ? which is unknown! So you said that an unknown parameter must be extend T and so A. It is incorrect.

Relationship you created is like E -> T -> A. After that you declared as a 1. generic type ? -> E -> T -> A and 2. generic type as A -> E -> T -> ?. So ? must extends ? and A must extends E vs.. It is confusing and unknown for compiler...

Incontestable answered 28/12, 2018 at 14:33 Comment(0)
S
1

With the following classes:

class A {}
class C extends A {}
class B<T extends A, E extends T> {}

Think of it like this:

E extends T extends A
With B<?,A> then T -> ? and E -> A
A extends ? extends A
Where the ? could be any subclass of A, let's say C.
A extends C extends A is clearly invalid.
So that's why it's a compile error.


Note for Eclipse users:

Eclipse 4.9.0 compiler disagreed with javac 8u and Intellij and did not emit a compile error for the generic arguments in B<?,A>. I assume this is a bug in the Eclipse compiler but I have not consulted the JLS to confirm this.

class B<T extends A, E extends T> {
    B<?, A> b; // <-- Eclipse does NOT emit a compile error
    B<?, ? extends A> b2;
}

This assumed bug has been reported here.

Sausauce answered 28/12, 2018 at 14:37 Comment(0)
C
0

In your declaration of field b, type T can be anything that extends A. In turn E must extend T however you are supplying type A for T. A will not be a subclass of something that is the subclass of A.

Cockcrow answered 28/12, 2018 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.