从当前版本(Java
12)开始,基本类型无法用Java泛型表示。更具体地说,我们不能提供原始类型作为类型参数。(例如,我们不能这样做
Foo<int>。)我们也不能将类型变量用作
new表达式中的类型,因此不能
newT[n]创建数组。因此,没有理想的方法来执行此操作。
这 是
可能做到这一点合理的使用一些反射(
java.lang.reflect.Array),但我们需要提供一个
Class作为参数。这是一个可能如何完成的示例:
public static <P> P toPrimitiveArray(List<?> list, Class<P> arrayType) { if (!arrayType.isArray()) { throw new IllegalArgumentException(arrayType.toString()); } Class<?> primitiveType = arrayType.getComponentType(); if (!primitiveType.isPrimitive()) { throw new IllegalArgumentException(primitiveType.toString()); } P array = arrayType.cast(Array.newInstance(primitiveType, list.size())); for (int i = 0; i < list.size(); i++) { Array.set(array, i, list.get(i)); } return array;}示例调用:
List<Integer> list = List.of(1, 2, 3);int[] ints = toPrimitiveArray(list, int[].class);
请注意,这
Array.set将执行扩展的原始转换,因此可以进行以下工作:
List<Integer> list = List.of(1, 2, 3);double[] doubles = toPrimitiveArray(list, double[].class);
但是它不会执行缩小的转换,因此以下内容引发异常:
List<Integer> list = List.of(1, 2, 3);byte[] bytes = toPrimitiveArray(list, byte[].class); // throws
如果您愿意,该代码还可用于简化复制:
public static int[] toIntArray(List<Integer> list) { return toPrimitiveArray(list, int[].class);}public static double[] toDoubleArray(List<Double> list) { return toPrimitiveArray(list, double[].class);}...(不过,具有多个类似方法并不是真正的 通用 。)
您有时会看到地点的一种解决方案如下所示:
public static <P> P toPrimitiveArray(List<?> list) { Object obj0 = list.get(0); Class<?> type; // "unbox" the Class of obj0 if (obj0 instanceof Integer) type = int.class; else if (obj0 instanceof Double) type = double.class; else if (...) type = ...; else throw new IllegalArgumentException(); Object array = Array.newInstance(type, list.size()); for (int i = 0; i < list.size(); i++) { Array.set(array, i, list.get(i)); } return (P) array;}但是,有很多问题:
- 如果列表为空,我们不知道要创建哪种类型的数组。
- 如果列表中的对象类型不止一种,则无法使用。
- 未经检查的将结果数组强制转换为
P
,因此存在堆污染的危险。
最好只传入a
Class作为参数。
另外,虽然可以编写许多重载来取消数组装箱:
public static int[] unbox(Integer[] arr) {...}public static long[] unbox(Long[] arr) {...}public static double[] unbox(Double[] arr) {...}...由于类型擦除的影响,不可能编写将许多不同类型的拆箱的重载,
List如下所示:
public static int[] unbox(List<Integer> list) {...}public static long[] unbox(List<Long> list) {...}public static double[] unbox(List<Double> list) {...}...那不会编译,因为在同一个类中,我们不允许有多个具有相同名称和擦除的方法。这些方法必须具有不同的名称。
附带说明一下,这是一些非通用解决方案:
从Java 8中,我们可以拆箱
List
第Integer
,Long
并Double
使用Stream
API:List<Long> list = List.of(1L, 2L, 3L);
long[] longs = list.stream().mapToLong(Long::longValue).toArray();
Google Guava has
Collection
unboxing methods in theircom.google.common.primitives
classes, for exampleDoubles.toArray
:List<Double> list = List.of(1.0, 2.0, 3.0);
double[] doubles = Doubles.toArray(list);


设置为? 如何转换清单 使用通用方法将数组t [](对于基本类型)设置为?](http://www.mshxw.com/aiimages/31/516047.png)
