不,这个问题不是关于它们之间的区别吗?和T;这是关于我如何转向< ? >参数命名为< T>。 请考虑以下示例代码:
import java.io.Serializable;
class A<T extends Serializable> {
<S extends Serializable> void bar(S arg) { }
void bar2(T arg) { }
}
public class B {
A<? extends Serializable> myA = null;
<T extends Serializable> void foo(T arg) {
myA.bar(arg);
myA.bar2(arg);
}
}
我的问题是以上事实并没有编译;对bar2()的调用给了我
The method bar2(capture#2-of ? extends Serializable) in the type
A<capture#2-of ? extends Serializable> is not applicable for the arguments (T)
我想&#34;原因&#34;因为那是myA是&lt; ?扩展Serializable&gt; ;但B.foo中的T ......很好,一个名叫T;而不是通配符?。
解决问题的一种方法&#34;这将是&lt; T扩展了Serializable&gt; 类B的类型参数......但这基本上与我对该类的其他用法冲突。含义:我最终写下了B及其成员myA,这完全是因为我不想参数化B类。所以,我开始只使用bar2()方法;然后在以后添加了bar()......但这并没有真正帮助。
那么 - 有没有办法让我的班级B使用A.bar2()作为&#34;意图&#34;在我的示例代码中?
编辑:而且确切地说 - bar()方法对我没有帮助;作为&#34; S&#34;那里......并不与&#34; T&#34;我真正在A班使用。
答案 0 :(得分:2)
你走到了尽头。
A<? extends Serializable> myA = ...;
所以myA
是未知的A
。它可以是A<String>
,也可以是A<Integer>
或A<Banana>
。你只是不知道。我们假设它是A<Banana>
。
<T extends Serializable> void foo(T arg) {
所以foo()
接受任何可序列化的:String,Integer,Banana,Apple,等等。假设它以Integer
作为参数调用。
myA.bar2(arg);
因此,基于上述假设,虽然bar2()
是myA
,但会以{\ n}为参数调用A<Banana>
。编译器无法接受这一点:它显然不是类型安全的。 B
必须是通用的。
答案 1 :(得分:1)
@JBNizet已经解释了为什么不能这样做。这个答案旨在解释你可能有的选择(在你的问题中正确地指出了其中一个,但这不是唯一的选择)。
让B采用类型参数
class B<T extends Serializable> {
A<T> myA = null;
void foo(T arg) {
myA.bar(arg);
myA.bar2(arg);
}
}
使B从A延伸(如果B通过A的a-a测试)
class B extends A<String> {
public void foo(String arg) {
bar2(arg);
bar(1);
}
}
两个选项之间的区别在于:1)bar
和bar2
都需要传递相同的类型,其中2 bar
和bar2
可以传递不同的类型,因为bar2
由为A
声明的类型参数绑定,其中bar
由为方法声明的类型参数绑定。