0

This may be a dumb question so please excuse my ignorance.

Lets say I have a class:

public class Foo<T extends Base> implements Bar<T> {
    private Bar<T> wrapped;
    public void setWrapped(Bar<T> input) {
        wrapped = input;
    }
}

If I call it with:

//Lets just assume methods getNewVal and getFoo exist
Bar<? extends Base> val = getNewVal();
Foo<? extends Base> foo = getFoo();
foo.setWrapped(val);

The compiler says foo.execute(val) is an error. With a message along the lines of The method setWrapped(Bar<capture#20-of ? extends Base>) in the type Foo<capture#20-of ? extends Base> is not applicable for the arguments (Bar<capture#22-of ? extends Base>).

If I try to change Foo to be

public class Foo<T extends Base> implements Bar<T> {
    private Bar<T> wrapped;
    public void setWrapped(Bar<? extends Base> input) {
        wrapped = input;
    }
}

The call to foo.setWrapped(val) no longer errors. Instead wrapped = input is an error with a message along the lines of Type mismatch: cannot convert from Bar<capture#1-of ? extends Base> to Bar<T>.

What am I doing wrong? Is there not a way to get the compiler to be okay with a call like this without casting?

Mike V.
  • 38
  • 1
  • 8
  • 4
    That is because `?` is not the same as `?`. The compiler cannot verify that the `?` in `Bar extends Base>` is the *same* `?` as in `Foo extends Base>`, so they are not compatible. – Andreas Jan 07 '17 at 02:48
  • There's almost no way to use a wildcard as a return type, which is what you're doing in the second code example. C.f. PECS http://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super Those wildcards are for making generics easier to use with method parameters, not return types. – markspace Jan 07 '17 at 02:55
  • 1
    Example: `getNewVal()` returns `Bar`, and `getFoo()` returns `Foo`. That is perfectly valid for first two statements, but not for `setWrapped()`. – Andreas Jan 07 '17 at 02:55
  • Could we get some more concrete code? – Makoto Jan 07 '17 at 03:16
  • Thanks Andreas. I understand why it doesn't work that way now. Cheers! – Mike V. Jan 12 '17 at 22:48
  • Does this answer you question https://stackoverflow.com/questions/11497020/java-generics-wildcard-extends-number-vs-t-extends-number? – Dr. Java Nov 17 '20 at 20:13
  • Does this answer your question? [Java Generics WildCard: extends Number> vs ](https://stackoverflow.com/questions/11497020/java-generics-wildcard-extends-number-vs-t-extends-number) – Dr. Java Nov 17 '20 at 20:13

1 Answers1

0

It looks like what you want is

public class Foo {
    private Bar<? extends Base> wrapped;
    public void setWrapped(Bar<? extends Base> input) {
        wrapped = input;
    }
}

It's not clear what the Bar interface Foo needs to implement is, though, and why Foo should have a Bar as well as be a Bar.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413