7
public void run(){
    setFont("Courier-24");
    //Define list as ArrayList<Integer>
    ArrayList<Integer> list = new ArrayList<Integer>();
    readList(list);
}

private void readList(ArrayList list){
    list.add("Hello");
    list.add(2);
    println("list = "+list);
    println("Type of list = "+list.get(0).getClass());
    println("Type of list = "+list.get(1).getClass());
}

结果:

列表 = [你好,2]
列表类型 = 类 java.lang.String
列表类型 = 类 java.lang.Integer

这是我的代码和结果。我的问题是,Integer 类型的 ArrayList 怎么可能存储 String 对象?现在的列表类型是什么?这是什么机制?

4

5 回答 5

6

Java 的泛型实际上并没有改变底层的类或对象,它们只是围绕它们提供(大部分)编译时语义。

通过将 an 传递ArrayList<Integer>给期望 an ArrayList(可以保存任何东西)的方法,您绕过了编译器为您提供该类型安全的能力。

Java 泛型教程解释了这一点,以及为什么 Java 以这种方式实现泛型。此页面特别关注它:

泛型被引入 Java 语言以在编译时提供更严格的类型检查并支持泛型编程。为了实现泛型,Java 编译器将类型擦除应用于:

  • 如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或 Object。因此,生成的字节码只包含普通的类、接口和方法。
  • 必要时插入类型转换以保持类型安全。
  • 生成桥方法以保留扩展泛型类型中的多态性。

类型擦除确保不会为参数化类型创建新类;因此,泛型不会产生运行时开销。

这并不是说这还允许使用泛型编写的代码(例如 your )与没有泛型编写的代码(例如 your run)进行交互,这在向具有庞大库的非常完善的语言添加功能时很重要base (就像在向 Java 中添加泛型时一样)。readList

于 2015-05-27T21:31:10.483 回答
3

当您声明:

 private void readList(ArrayList list)

您没有为此指定任何类型,ArrayList因此默认情况下它是 type Object

StringInteger(实际上是 java 中的所有类)都是Object. 因此可以将它们添加到列表中。

有关没有类型的泛型的更多信息,请阅读此处。简而言之,泛型类型仅用于编译时检查,因此您不会添加错误的类型(这可能会导致异常。在这种情况下,您的操作是兼容的,所以幸运的是没有错误)StringInteger

于 2015-05-27T21:34:52.957 回答
1

在您的readList方法的参数中,您没有将其限制为仅Integer值类型,因此list无法获得编译时检查的好处,并且必须求助于运行时类型检查。

于 2015-05-27T21:30:32.460 回答
1

宣言

ArrayList list

在方法 readList 等价于

ArrayList<Object> list

很明显,String 是 Object,也是 Integer。当传递给 println 时,两者都将使用自己的方法进行 toString 化。

于 2015-05-27T21:32:00.570 回答
1

我认为没有作为参数传递的泛型规范的 ArrayList 类型被假定为 ArrayList。String 和 Integer 都继承了 Object,因此它们都可以添加到列表中。但是 ArrayList 元素是 Objects 类型的。

于 2015-05-27T21:34:59.037 回答