强制Javagenerics参数具有相同的类型
如何在没有错误的情况下实现类似的function?
class A { void f(K x) {} } void foo(A a, X x) { af(x); // AN error: The method f(capture#1-of ? extends X) in the // type A is not applicable for the // arguments (X) }
我知道它发生是因为’a’可以是A 的一个实例,所以它的’f’不能接受X的一个实例作为参数,但我如何强制参数是相同的类型?
这是更多的代码:
测试类:
class Test { void foo(A a, T x) { af(x); // now it works! } }
在某些课程中:
Container container; public void test() { X x = new X(); new Test().foo(container.get(), x); }
这是容器类:
public class Container { A get() { return new A(); } }
您可以通过执行以下操作强制参数具有相同的类型 :
// the first class, A: class A { void f(K x) {} } // the second class, defining the method with generic type parameters class Test { void foo(A a, T x) { af(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 a = new A<>(); test.foo(a, "bar"); } }
它的作用是:方法foo
定义generics类型参数T
并使用它来强制类A
的K
类型参数必须匹配x
的第二个参数x
的类型。
如果你愿意,你甚至可以对
施加限制,如果它对你的问题有意义,例如
,或者使用super
。 如果Joni在问题中的评论中询问, X
实际上是一个类型而不是类型参数,你会想要这个:你使用
。
在显示更多代码后,问题就变得清晰了。
容器的方法.get()
返回A extends K>
的实例A extends K>
A extends K>
。 因此,未完全指定从.get()
获取的实例的类型参数。 通常,返回这种未指定类型的设计并不是很好。 有关Effective Java的作者Joshua Bloch和Java中的许多API和function的video演示,请展示如何改进此类API,请查看: http : //www.youtube.com/watch?v = V1vQf4qyMXg&feature = youout。 be&t = 22m 。 正好在25’36“,Joshua Bloch说”不要试图在返回值上使用它们[通配符类型]“,他稍后会解释。基本上,你不会通过使用它们获得更多的灵活性,只是制造API的用户很难处理它(你只是觉得这样做的效果……)。
要修复,您可以简单地尝试将.get()
的签名更改为A
,因此容器类将是:
public class Container { A get() { return new A (); } }
既然你知道get()
正在返回A
一个实例,那么没有理由使用旧的签名:它只会让你丢失你已经知道的信息!
如果这仍然不起作用,您的问题可能在其他地方,并且您需要显示更多代码……或者更好,还要问其他问题! 🙂
记住PECS规则 ,并且考虑到使用X的方式,您应该指定为下限而不是上限:
void foo(A super X> a, X x)
这样就不会产生编译器错误,并且您可以使用最常用的签名。