我正在尝试学习泛型类型的使用,当我尝试使用某些代码时,我注意到了一些奇怪的东西。
第一段代码位于名为“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,a string]
由于arr
是类型为ArrayList
的{{1}},这让我非常困惑,它如何包含Integer
和boolean
类型的对象?是否将函数String
中的列表转换为原始类型(这意味着它变为泛型类型func
)?如果是这样,怎么可能,因为你不能这样做,例如:Object
?
希望对此有所澄清,也许它会帮助我更好地掌握这类泛型类型的主题。谢谢!
答案 0 :(得分:1)
Java不允许创建通用数组。 Java Collection Classes主要使用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
。根据您的编译器设置,将省略警告。
使用(绑定/未绑定)通配符更好。
答案 1 :(得分:1)
此类输出背后的原因是您将List
作为参数传递给func( int k , List list ) .
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");
}
答案 2 :(得分:1)
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);