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

[UPDATE] The real situation was a little more complicated than my original question. I modified the code a bit to reflect this. [/ UPDATE]

I am a little puzzled by the following behavior. Based on the code:

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 an error:

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

While Eclipse gives me:

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

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

+4
source share
3 answers

When you use a wildcard, the compiler cannot see that the return type x.makeT() and the parameter type x.useT() match. To ensure that they are the same, you should use the general method here:

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

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

This will be fixed:

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

Use the capture assistant:

 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,

0
source

Source: https://habr.com/ru/post/1299693/


All Articles