简体   繁体   中英

How to use a generic result as a generic parameter when the type is a wildcard?

[UPDATE] The real situation was a bit more complicated than my initial question made it seem. I've changed the code a bit to reflect that.[/UPDATE]

I'm a bit stumped by the following behavior. Given code like:

interface Inter<T> {
  T makeT();
  void useT(T t);
}

public class Foo {
  public void bar(Qux q) {
    Inter<?> x = getInterForQux(q);
    x.useT(x.makeT());
  }

  Inter<?> getInterForQux(Qux q) {
    if( someTest(q) ) {
      return (Inter<Integer>) mkAnInterInt();
    } else {
      return (Inter<Double>) mkAnInterDouble();
    }
  }
}

Javac gives me the error:

useT(capture#478 of ?) in Inter<capture#478 of ?> cannot be applied to (java.lang.Object)

Whereas Eclipse gives me:

The method useT(capture#1-of ?) in the type Inter<capture#1-of ?> is not applicable for the arguments (capture#2-of ?)

Obviously, no matter what T is the result type of makeT() is the same as the parameter type of useT() . Why can't I do this? Is there a workaround?

When you use wildcard, compiler can't see that the return type of x.makeT() and the parameter type of x.useT() are the same. In order to guarantee that they are the same, you should use generic method here:

public class Foo { 
    public <T> void bar(Inter<T> x) { 
        x.useT(x.makeT()); 
    } 
} 

This is logical, since Inter<?>.makeT() can return anything, and Inter<?>.useT(..) consumes anything, but the two anythings can be different.

That would fix it:

public <T> void bar(Inter<T> x) {
    x.useT(x.makeT());
}

Use a capture helper:

public void bar(Qux q) {
    Inter<?> x = getInterForQux(q);
    barPrivate(x);
}
private <T> void barPrivate(Inter<T> x) {
    x.useT(x.makeT());
}

This gives you the same signature for bar as you want

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM