Java中的集合

Jak*_*ake 3 java

快速问题... Java中的集合可以包含多种类型吗?或者他们都必须是同一类型?

谢谢

Gre*_*Cat 7

简单回答

是.

更详细的答案

您可以使用没有<T>值的泛型集合,例如:

ArrayList a = new ArrayList();
a.add(2);
a.add("String");
Run Code Online (Sandbox Code Playgroud)

不使用集合<T>是一个坏习惯,大多数IDE /编译器在这里发出警告.你可以通过使用一个集合来规避它Object,即:

ArrayList<Object> a = new ArrayList<Object>();
Run Code Online (Sandbox Code Playgroud)

或者你可以找到这些元素必须具有的一些通用接口或超类型,例如ArrayList<Number>- 你可以存储具有共同Number超类的各种对象,即BigDecimal,BigInteger,Byte,Double,Float,Integer,Long,Short:

ArrayList<Number> a = new ArrayList<Number>();
a.add(2); // integer
a.add(42L); // long
a.add(123.45d); // double
System.out.println(a.toString()); // => [2, 42, 123.45]
Run Code Online (Sandbox Code Playgroud)

请注意,它本质上意味着a元素属于Number类 - 即您不能要求执行特定于子类的方法(例如,Double#isInfinite(),这在Number超类中不存在),尽管您可以在运行时进行类型转换如果你以某种方式知道对类型转换是安全的:

a.get(2).isInfinite()          // compile-time error
((Double) a.get(2)).isInfinite() // => false
((Double) a.get(1)).isInfinite() // run-time error (ClassCastException)
Run Code Online (Sandbox Code Playgroud)

运行时类型转换通常也不受欢迎,因为它有效地规避了正确的编译时类型安全性.

还要注意,不可能分配(或使用)ArrayList<Number>代替,ArrayList<Integer>反之亦然,即这将无法编译:

public void printNumbers(ArrayList<Number> list) {
    list.forEach(System.out::println);
}
ArrayList<Integer> a = new ArrayList<Integer>();
printNumbers(a); // "incompatible types"
Run Code Online (Sandbox Code Playgroud)

以及:

public void printIntegers(ArrayList<Integer> list) {
    list.forEach(System.out::println);
}
ArrayList<Number> a = new ArrayList<Number>();
printIntegers(a); // "incompatible types"
Run Code Online (Sandbox Code Playgroud)

要声明变量能够接受它们的两个ArrayList<Number>或任何子类,可以使用ArrayList<? extends Number>ArrayList<? super Number>语法.extends通常在您要从方法中的对象使用(即读取)super时使用,在您要生成(即写入)时使用.鉴于打印输出正在消耗,使用安全extends:

public void printNumbers(ArrayList<? extends Number> list) {
    list.forEach(System.out::println);
}

ArrayList<Integer> listInt = new ArrayList<Integer>();
printNumbers(listInt); // works
ArrayList<Double> listDbl = new ArrayList<Double>();
printNumbers(listDbl); // also works
Run Code Online (Sandbox Code Playgroud)

<?之间的差异有一个很好的答案 超级T>和<?在Java中扩展T>以获得更深入的解释.