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 当前实施方式的限制。
如果我可以声明一个 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 当前实施方式的限制。