java - 强制 Java 泛型参数为同一类型

标签 java generics

如何在没有错误的情况下实现类似的功能?

class A<K> {
   void f(K x) {}
}

void foo(A<? extends X> a, X x) {
    a.f(x); // AN error: The method f(capture#1-of ? extends X) in the 
            // type A<capture#1-of ? extends X> is not applicable for the 
            // arguments (X)
}

我知道它发生是因为 'a' 可以是 A<"non-X"> 的实例,所以它的 'f' 不能接受 X 的实例作为参数,但我如何强制参数属于同一类型?

这里是更多的代码:

测试类:

class Test {
   <T> void foo(A<T> a, T x) {
   a.f(x); // now it works!
 }
}

在一些类中:

Container<X> container;
public void test() {
    X x = new X();
    new Test().foo(container.get(), x);
}

这是容器类:

public class Container<K> {
    A<? extends K> get() {
    return new A<K>();
    }
}

最佳答案

您可以通过执行以下操作强制参数为同一类型:

// the first class, A<K>:
class A<K> {
  void f(K x) {}
}

// the second class, defining the method with generic type parameters
class Test {
  <T> void foo(A<T> a, T x) {
    a.f(x); // now it works!
  }
}

// a third class, that uses the above two:
class Main {
  public static void main(final String... args) {
    final Test test = new Test();
    final A<String> a = new A<>();
    test.foo(a, "bar");
  }
}

它所做的是:方法 foo定义泛型类型参数 T并用它来强制执行 K类的类型参数 A必须匹配 x 的类型, foo 的第二个参数.

您甚至可以对 <T> 施加限制如果您愿意并且对您的问题有意义,例如 <T extends Bar> void foo(A<T> a, T x) {...} , 或者用 super .如果正如Joni 对问题中的评论提出的那样,您会想要这个 X实际上是一个类型而不是类型参数:你会使用 <T extends X> void foo(...) .


显示更多代码后,问题就会变得清晰。

方法.get()容器返回 A<? extends K> 的一个实例.因此,您从 .get() 获得的实例的类型参数没有完全指定。通常,返回这样一个未指定的类型并不是很好的设计。有关 Effective Java 和 Java 中许多 API 和特性的作者 Joshua Bloch 的视频演示,展示了如何改进此类 API,请查看:http://www.youtube.com/watch?v=V1vQf4qyMXg&feature=youtu.be&t=22m .恰好在 25'36”处,Joshua Bloch 说,“不要尝试在返回值上使用它们 [通配符类型]”,他稍后解释道。基本上,使用它们不会获得更多的灵 active ,只是使API 的用户很难处理它(您只是感受到这样做的效果......)。

要修复,您可以简单地尝试更改 .get() 的签名至 A<K> get() ,所以容器类将是:

public class Container<K> {
  A<K> get() {
    return new A<K>();
  }
}

既然你知道 get()正在返回 A<K> 的实例, 没有理由使用旧签名:它只会让你丢失你已经知道的信息!

如果这仍然不起作用,您的问题可能出在其他地方,您需要显示更多代码……或者更好的是,问其他问题! :)

关于java - 强制 Java 泛型参数为同一类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17390441/

相关文章:

java - 我们可以返回 List<P> 而不是 List<?> 吗?

c# - 基于字典排序 IEnumerable<T> 对象

java - 接口(interface)方法中的泛型被剥离

JAVA:使用 XPath 表达式构建 XML 文档

java - 正则表达式,以便只能输入 'a' ,'A' ,'p' 和 'P' 作为输入

java - 在Java中创建一个返回多个对象的对象

android - 带有可变参数的 kotlin 引用函数并将 Array<out 转换为 List<out

java - 从泛型 T 派生类

java - Hibernate乐观锁方法

java - 如何限制Joptionpane消息对话框条件提示一次?