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]
这让我很困惑,因为 arr
是 Integer
类型的 ArrayList
,它怎么能包含 boolean
和 String
类型的对象?函数 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);
我正在尝试了解泛型类型的使用,但在试验某些代码行时发现了一些奇怪的事情。
第一段代码在名为“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]
这让我很困惑,因为 arr
是 Integer
类型的 ArrayList
,它怎么能包含 boolean
和 String
类型的对象?函数 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);