class Holder<T> {
private T value;
public Holder() {}
public Holder(T val) { value = val; }
public void set(T val) { value = val; }
public T get() { return value; }
public boolean equals(Object obj) {
return value.equals(obj);
}
}
public class Wildcards {
static <T> T exact2(Holder<T> holder, T arg) {
holder.set(arg);
T t = holder.get();
return t;
}
// 有界 extends 通配符的参数:
static <T> T wildSubtype(Holder<? extends T> holder, T arg) {
// holder.set(arg); // 编译错误,不能写操作
T t = holder.get();//只可以读操作
return t;
}
// 有界 super 通配符的参数:
static <T> void wildSupertype(Holder<? super T> holder, T arg) {
holder.set(arg);//只可以写操作
// T t = holder.get(); // 编译错误,不能读操作
// 本来是不能读操作的,但 super 有上限 Object,所以这是唯一合法的读操作:
Object obj = holder.get();
}
public static void main(String[] args) {
Holder raw = new Holder<Long>();
// 上下两行都一样,反正泛型是伪泛型,重要的还是引用的类型
raw = new Holder();
Holder<Long> qualified = new Holder<Long>();
Holder<?> unbounded = new Holder<Long>();
Holder<? extends Long> bounded = new Holder<Long>();
Long lng = 1L;
Long r5 = exact2(raw, lng); // unchecked 警告:
// 类型推断为了 Long,所以第一个参数会有 unchecked 的警告
Long r6 = exact2(qualified, lng);
//Long r7 = exact2(unbounded, lng); // 编译错误
//Long r8 = exact2(bounded, lng); // 编译错误
Long r9 = wildSubtype(raw, lng); // unchecked 警告
Long r10 = wildSubtype(qualified, lng);
// 只能返回给 Object。因为传递进入的实参类型是无界通配符
Object r11 = wildSubtype(unbounded, lng);
Long r12 = wildSubtype(bounded, lng);
wildSupertype(raw, lng); // unchecked 警告
wildSupertype(qualified, lng);
//wildSupertype(unbounded, lng); // 编译错误
//wildSupertype(bounded, lng); // 编译错误
}
} ///:~
此例来自于 java 编程思想,在主函数中 exact2 和 wildSupertype 的两处调用都会有编译错误,看了提示,感觉不是特别理解。而且相对的,wildSubtype 函数却可以执行成功?
两个报错都说了,Long 不能转换为?。这个该怎么理解,就是说,一个形参推断出来为 Long,一个形参推断出来为?,就不可以呗? exact2 函数还多说了句,两个形参推断出来的边界不一样。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.