我最近正在学习Java Generics,并试图通过"Java Generics FAQ".
关于通配符参数化类型的问题(#304)有点困惑我,非常感谢你的帮助.
代码示例:
class Box<T> {
private T t;
public Box(T t) { this.t = t; }
public void put(T t) { this.t = t;}
public T take() { return t; }
public boolean equalTo(Box<T> other) { return this.t.equals(other.t); }
public Box<T> copy() { return new Box<T>(t); }
}
class Test {
public static void main(String[] args) {
Box<?> box = new Box<String>("abc");
box.put("xyz"); // error
box.put(null); // ok
String s = box.take(); // error
Object o = box.take(); // ok
boolean equal = box.equalTo(box); // error {confused}
equal = box.equalTo(new Box<String>("abc")); // error {confused}
Box<?> box1 = box.copy(); // ok
Box<String> box2 = box.copy(); // error
}
}
Run Code Online (Sandbox Code Playgroud)
无法弄清楚为什么下面两个方法调用会失败:
boolean equal = box.equalTo(box);
equal = box.equalTo(new Box<String>("abc"));
Run Code Online (Sandbox Code Playgroud)
谢谢
Box<?> box = new Box<String>("abc");
box.put("xyz"); // error
String s = box.take(); // error
Run Code Online (Sandbox Code Playgroud)
在OOP中,您使用的是多态性.所以在编译时,box对象的类型是Box<?>
Type<?>这称为未知通配符.因为你不知道什么类型的盒键入做的,你只能从对象看,你只能使用读为对象实例的对象.这box.put("xyz")就是收到错误并String s = box.take()收到错误的原因.
其次:
boolean equal = box.equalTo(box);
Run Code Online (Sandbox Code Playgroud)
在equalTo收到Box<T>不Box<?>.正如我上面所解释的,T代表任何类,但?只是意义未知的通配符,这两个术语是不一样的.
还有其他一点,你应该知道.在Java中,泛型是在编译时.与其他如C#相比,泛型是在运行时.
以下是有关通配符的参考链接:Java通配符
希望这有帮助:)
该equalTo方法需要a Box<T>,而不是Box<?>.当你有一个类型的对象时Box<?>,你不能把它Box<String>甚至Box<?>作为参数,equalTo因为T两个盒子的类型可能不一样.
请记住,编译器将在编译时使用对象的静态类型.
所以,这将失败:
Box<?> b = new Box<String>();
b.equalTo(new Box<String>("abc");
Run Code Online (Sandbox Code Playgroud)
但这不会:
Box<String> b = new Box<String>();
b.equalTo(new Box<String>("abc");
Run Code Online (Sandbox Code Playgroud)
Box<?> 是“未知的盒子”。Box<? extends String> 将会是“一盒至少是字符串的东西”Box<String>绝对是“一盒弦”。null放入“未知盒子”吗?当然。鉴于,
Box<?> box = new Box<String>("abc");
Run Code Online (Sandbox Code Playgroud)
它要求编译器忘记<String>并假设box是“未知的盒子”。您看到的错误表明编译器无法再对参数进行类型检查。它无法检查给定类型是否属于未知类型(null除外)。