当类型为通配符时,如何使用泛型结果作为泛型参数?

发布于 2024-08-19 16:47:00 字数 883 浏览 2 评论 0原文

[更新] 真实情况比我最初的问题看起来要复杂一些。我对代码做了一些更改以反映这一点。[/更新]

我对以下行为有点困惑。给定如下代码:

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 给我错误:

在 Inter中使用 T(capture#478 of ?)无法应用于 (java.lang.Object)

而 Eclipse 给了我:

类型Inter中的方法useT(capture#1-of ?)是 不适用于参数 (捕获#2-of?)

显然,无论T是什么,makeT()的结果类型与useT()的参数类型相同。为什么我不能这样做?有解决方法吗?

[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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦在深巷 2024-08-26 16:47:00

当您使用通配符时,编译器无法看到x.makeT()的返回类型和x.useT()的参数类型是否相同。为了保证它们是相同的,你应该在这里使用泛型方法:

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

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()); 
    } 
} 
孤独岁月 2024-08-26 16:47:00

这是合乎逻辑的,因为 Inter.makeT() 可以返回任何内容,而 Inter.useT(..) 会消耗任何内容,但是两者任何事情都可以不同。

这样就可以解决这个问题:

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());
}
守不住的情 2024-08-26 16:47:00

使用捕获助手:

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

这为您提供了与您想要的 bar 相同的签名

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文