Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why doesnt this type wildcard work?

Tags:

java

generics

interface A {
    String n();
}
class B implements A {
    @Override
    public String n() { return "asdf"; }
}
interface C<T extends A> {
    T m(T t);
}
class D implements C<B> {
    @Override
    public B m(B b) {
        return b;
    }
}

Class<C<? extends A>> x = D.class;

there is an error on the last line

Type mismatch: cannot convert from Class<D> to Class<C<? extends A>>

this looks perfectly fine to me, but maybe i am missing some subtlety on how type wildcards work. Is there a way i can change the type on the last line? i need this reference because i plan on doing this later:

B b = new B();
A y = x.newInstance().m(b);

this also has an error

The method m(capture#1-of ? extends A) in the type C<capture#1-of ? extends A> is not applicable for the arguments (B)

however, if i use it without the wildcards and capture, it works fine:

A z = D.class.newInstance().m(b);

unfortunately im kinda stuck with this for now, any help would be appreciated.

edit: removed this. references

edit: changed x to be

Class<? extends C<? extends A>> x = D.class;

and it works. however still getting errors on x.newInstance().m(b)

The method m(capture#2-of ? extends A) in the type Test.C<capture#2-of ? extends A> is not applicable for the arguments (B)
like image 409
aepurniet Avatar asked Nov 18 '12 09:11

aepurniet


1 Answers

Right, focusing just on the last part:

however still getting errors on x.newInstance().m(b)

The method m(capture#2-of ? extends A) in the type
Test.C<capture#2-of ? extends A is not applicable for the arguments (B)

Indeed - and that makes perfect sense. Because nothing in your code indicates that you've actually got a C<B>. All the compiler knows is that newInstance has returned an instance of some type which implements C<X> for some type X which implements A. How would it know that that's B?

If you want to call m(b), you'll need a C<B>, which means that your declaration would need to be

Class<? extends C<B>> x = D.class;

At that point, the method invocation compiles cleanly. It's not really clear what you're trying to achieve, or whether this will be good enough for you - but hopefully it explains why you're getting the error you're getting...

like image 100
Jon Skeet Avatar answered Oct 05 '22 09:10

Jon Skeet