【问题标题】:Java - Generic types and collections [duplicate]Java - 泛型类型和集合
【发布时间】:2017-12-24 10:24:25
【问题描述】:

我正在尝试了解泛型类型的使用,当我在尝试一些代码行时发现了一些奇怪的东西。

第一段代码在一个名为“A”的类中:

public void func(int k, List list) {
    list.add(9);
    list.add(true);
    list.add("a string");
    }

第二段代码在另一个类中,在主函数内部:

List<Integer> arr = new ArrayList<Integer>();
        arr.add(14);
        System.out.println(arr.toString());
        a.func(8, arr);
        System.out.println(arr.toString());

运行代码会打印以下行:

[14]

[14, 9, true, 一个字符串]

这让我很困惑,因为arrInteger 类型的ArrayList,它怎么能包含booleanString 类型的对象?函数func 中的列表是否转换为原始类型(这意味着它变为泛型类型Object)?如果是这样,怎么可能,因为你不能这样做,例如:List&lt;Integer&gt; arr = new ArrayList&lt;Object&gt;();?

希望对此进行一些澄清,也许它会帮助我更好地掌握泛型类型这一主题。谢谢!

【问题讨论】:

标签: java collections generic-collections


【解决方案1】:

Java 不允许创建泛型数组。 Java 集合类主要使用Object 数组实现。 ArrayList 类可能如下所示

public class ArrayList<T> implements List<T>, Serializable {
    private transient Object[] data;
    // more content...
}

在创建ArrayList 的新实例时,会创建一个新的Object[] 数组,该数组可以容纳任何类型的对象。类型安全只能通过使用泛型类型参数来实现。

由于 List 没有提供任何 Type 参数,它使用 rawtype 并且可以将任何内容添加到列表中。因此,请务必确保推断模板参数以保持类型安全。

public void func(int k, List<Integer> list) {
    list.add(9);      // works
    list.add(true);   // compile error
    list.add("a string");  // compile error
}

你不应该使用rawtypes。根据您的编译器设置,将省略警告。 最好使用(绑定/未绑定)通配符。

【讨论】:

    【解决方案2】:

    这种输出背后的原因是您将List 作为参数传递给func( int k , List list ) . func 方法中的 list 是非泛型的,它也允许您添加字符串,以便获得这样的输出。

     List<Integer> arr = new ArrayList<Integer>();
                    arr.add(14);
                    System.out.println(arr.toString());
                    a.func(8, arr); // here you are passing a list 
                    System.out.println(arr.toString());
    
        public void func(List list) { // here List in non-generic 
            list.add(9);
            list.add(true);
            list.add("a string");
            }
    

    【讨论】:

      【解决方案3】:

      Java 中通用代码的全部意义在于在实际代码编译之前提供类型安全。编译后的代码没有类型,这就是为什么我们在代码中不会遇到任何问题,因为当实际调用func() 方法时,List arr 没有任何类型。

      当我们调用System.out.println(arr.toString()) 时,我们只是在打印一个对象。这适用于任何类型(即 int、boolean、String 等...)。这就是我们没有遇到任何异常的原因。

      但是,只要尝试从这个列表中分配一个值,我们就会得到java.lang.ClassCastException

      ...
      func(8, arr);
      System.out.println(arr.toString());
      int a = arr.get(2);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多