Java/P5: 如何声明一个包含 FloatLists 的 Arraylists 数组?

Java/P5: How to declare an Array of Arraylists holding FloatLists?

如果我可以声明一个 FloatList 数组:FloatList [][] values = new FloatList[3][3];

为什么像这样声明一个包含 FloatList 的 ArrayList 数组不起作用:ArrayList<FloatList> [][] values = new ArrayList<FloatList>() [3][3];?或者甚至:ArrayList<FloatList> [][] values = new ArrayList<FloatList> [3][3]();

如何实现?很难提到深埋在其坚硬质地下的 floats 吗?

ArrayList<FloatList> [][] values = new ArrayList[3][3];

基本上,您是在声明您想要的对象是 ArrayList 的 3D 数组,而不是生成实际的 ArrayList 对象。

之后,你必须实例化它们中的每一个,例如:

values[0][0] = new ArrayList<>();

等等。

从最内层的类型到最外层的类型工作。您从 FloatList:

开始
FloatList

然后将其包装在 ArrayList:

ArrayList<FloatList>

那么你想要一个这样的数组:

ArrayList<FloatList>[]

或二维数组:

ArrayList<FloatList>[][]

这给了你声明的类型,但是你必须通过给它一个值来初始化变量。从数组开始,给它一个大小:

ArrayList<FloatList>[] array = new ArrayList[10];

这为您提供了一个包含 ArrayList<FloatList> 个对象的数组,但它们以 null 开头。要给它们赋值,您需要遍历数组中的每个索引并使用 new 关键字将索引的值设置为 ArrayList<FloatList>:

的实例
for(int i = 0; i < array.length; i++){
   array[i] = new ArrayList<FloatList>();
}

对于二维数组,您将使用相同的逻辑,只是在嵌套的 for 循环中。

然后在数组的特定索引处将 FloatList 添加到 ArrayList,您可以这样做:

array[i].add(new FloatList());

最后,要将 float 添加到数组索引处 ArrayList 中的 FloatList,您可以这样做:

array[x].get(y).append(0.5);

并且要从 FloatList 中的索引中的 ArrayList 中的索引中获取 float 数组中的索引,您可以这样做:

float f = array[x].get(y).get(z);

把它们放在一起,看起来像这样:

ArrayList<FloatList>[] array = new ArrayList[10];

for(int i = 0; i < array.length; i++){
   array[i] = new ArrayList<FloatList>();
}

array[1].add(new FloatList());

array[1].get(0).append(0.25);
array[1].get(0).append(0.5);
array[1].get(0).append(0.75);

float f = array[1].get(0).get(2);

println(f);

由于 JVM 提供泛型的方式,它不起作用。 Java 中的泛型是一种前端编译器功能,可在执行时变为原始类型用法和强制转换。

当我使用泛型时编译器在做什么?

这是一个非常人为设计的例子。假设我想创建一个 List<String> 来存储命令行参数,稍后我将使用它来启动新进程,如下所示:

List<String> cmd = new ArrayList<>();
cmd.add("java");
cmd.add("-jar");
cmd.add("path/to/my.jar");
...
String args = cmd.get(0)+" "+cmd.get(1)+" "+cmd.get(2);

在编译时,编译器将检查以确保每次我通过 cmd 使用通用 List 方法时我使用的是 String 类型,如果我尝试使用不兼容类型的实例。然而,在编译期间,在执行之前,有一个叫做 erasure 的小东西。实际上,在幕后,编译器将上面的代码转换成如下内容:

List cmd = new ArrayList();
cmd.add("java");
cmd.add("-jar");
cmd.add("path/to/my.jar");
...
String args = (String)cmd.get(0)+" "+(String)cmd.get(1)+" "+(String)cmd.get(2);

为什么我的通用数组代码不能编译?

在您的示例中,您想创建一个泛型数组,如下所示:

ArrayList<FloatList>[][] array = new ArrayList<FloatList>[n][m]; //Doesn't compile? What gives?

问题是,由于类型擦除,ArrayList<FloatList> class 类型并不真正存在,现在您已经要求 JVM 创建一个非类型的二维数组-存在类型。

好的,那还有什么选择呢?

好吧……这不是很漂亮,但你可以这样做:

class ArrayListOfFloatList extends ArrayList<FloatList>{
    ...
}

//Somewhere else in your code:
ArrayListOfFloatList[][] myArray = new ArrayListOfFloatList[n][m];
//This will compile because ArrayListOfFloatList is a real class.

解决此问题的唯一其他方法是不使用数组。也许丑陋,但不幸的是,这是对 Java 当前实施方式的限制。