java - 为什么这个通配符有效?

标签 java generics

我对这段代码感到困惑,它应该不起作用(我猜),但它似乎可以正常工作。

当我输入 <T>在 Person 类旁边,Arraylist 中的通配符并不像定义的那样运行,在下面的代码中,通配符应该只适用于 super。 Person 类,但带有 <T>在类 Person 旁边,它接受所有种类的类型(在这个例子中它是 String )。并且为了使它起作用,Human 在定义时不应具有指定的类型。这是代码:

import java.util.ArrayList;

public class Person {
    public static void main(String[] args) {
        Human h = new Human();
        h.al(new ArrayList<String>()); // this should give an error no ?
    }
}

class Human<T>{ //Human is a generic class, but above I created an instance without specifying the T
    public void al(ArrayList<? super Person> a){ //the type passed should be a super of Person

    }
}

谢谢你:)

最佳答案

这在 Java 泛型常见问题解答中得到了回答:Can I use a raw type like any other type?

答案是:

Methods or constructors of a raw type have the signature that they would have after type erasure.

在英语中,这意味着因为您将h 声明为原始类型Human,所以编译器将执行type erasurehal 方法的有效签名实际上是类型删除之后的签名!因此,就编译器而言,您的代码是健全的。

另请参阅此问题的答案:Java generics - type erasure - when and what happens 更多示例。

维基百科也有一个很好的部分介绍 Problems with Type erasures这可能很难捕捉。

更新

下面的代码片段将在运行时抛出 ClassCastException。

import java.util.ArrayList;
import java.util.Iterator;

class Human<T>{
  public void al(ArrayList<? super Person> a){
    Iterator<? super Person> iter = a.iterator();
    while (iter.hasNext()) {
      Person h = (Person) iter.next(); // unsafe cast
    }
  }
}

public class Person {
  public static void main(String[] args) {
    Human h = new Human();

    ArrayList<String> arr = new ArrayList<String>();
    arr.add("deadbeef");

    h.al(arr); // valid, since h is raw
  }
}

关于java - 为什么这个通配符有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23331108/

相关文章:

java - Android - 光标结果搜索字符串错误,需要搜索 DISPLAY_NAME 进行匹配

java - 更改字节数组中的位

c# - 通过传递 Expression<Func<T, object>> 使用反射调用方法

java泛型方法

c# - 如何使用约束将 T 限制为值类型?

java - 从通配符列表中删除每个第 N 个元素 - Java

java - AbstractList 源代码中的奇怪代码行

java - 在扑克程序中测试两对

java - 从 selenium webdriver 中的消息中获取特定值

c# - 将一个对象同时转换为两个接口(interface),调用泛型方法