Java Generics Wildcard混淆

foo*_*ger 7 java generics

我最近正在学习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)

谢谢

hqt*_*hqt 7

Box<?> box = new Box<String>("abc");
box.put("xyz");     // error 
String s = box.take();  // error 
Run Code Online (Sandbox Code Playgroud)
  1. 在OOP中,您使用的是多态性.所以在编译时,box对象的类型是Box<?>

  2. 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通配符

希望这有帮助:)


Jef*_*rey 5

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)


S.D*_*.D. 5

  • Box<?> 是“未知的盒子”。
  • Box<? extends String> 将会是“一盒至少是字符串的东西”
  • Box<String>绝对是“一盒弦”。
  • 因此,如果我们有一个“未知的盒子”,我们尝试在其中放入一个类型(例如字符串)。编译器不确定。它是一盒未知数。如果它实际上只接受Integers怎么办?
  • 我们可以null放入“未知盒子”吗?当然。
  • 我们如何从“未知盒子”中“获取()”?至少一个对象。

鉴于,

Box<?> box = new Box<String>("abc");
Run Code Online (Sandbox Code Playgroud)

它要求编译器忘记<String>并假设box是“未知的盒子”。您看到的错误表明编译器无法再对参数进行类型检查。它无法检查给定类型是否属于未知类型(null除外)。