Java - 通用类型和集合

Java - Generic types and collections

我正在尝试了解泛型类型的使用,但在试验某些代码行时发现了一些奇怪的事情。

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

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

第二段代码在不同的class,在main函数里面:

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, a string]

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

希望得到一些澄清,也许它会帮助我更好地理解泛型类型这个主题。谢谢!

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

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

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

由于 List 没有提供任何类型参数,因此它使用 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。根据您的编译器设置,警告将被忽略。 最好使用 (bound/unbound) 个通配符。

出现这种输出的原因是您将 List 作为参数传递给 func( int k , List list ) . list in func 方法是非通用的,它允许你添加字符串,所以你得到这样的输出。

 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");
        }

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);