将参数化的 ArrayList 传递给 java 中的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2482193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing parametrized ArrayList to a function in java
提问by athena
I have the following function.
我有以下功能。
func(ArrayList `<String>`[] name) { ........ }
The function fills the ArrayList[]. (I don't want to return the ArrayList[])
该函数填充 ArrayList[]。(我不想退货ArrayList[])
However, in the caller function the ArrayList[]obtained has all ArrayLists as null.
For eg.
但是,在调用者函数中,ArrayList[]获得的所有 ArrayList 都为null。
例如。
name = new ArrayList[num];
func(name);
System.out.println(name[0]);
I get NullPointerExceptionat line 3. Is this because of line 1, i.e. I am not parametrizing? If yes, is there another way this can be done? Because java does not allow creating a generic array of parametrized ArrayList.
我到NullPointerException了line 3。这是因为line 1,即我没有参数化?如果是,有没有其他方法可以做到这一点?因为java不允许创建参数化的通用数组ArrayList。
回答by Matthew Flaschen
That is obviously not your real code, but you're creating an array of ArrayLists, which probably isn't what you want. You can probably just do:
这显然不是您真正的代码,但您正在创建一个 ArrayLists 数组,这可能不是您想要的。你大概可以这样做:
ArrayList<String> name = new ArrayList(num);
func(name);
System.out.println(name.get(0));
Note that when you create the ArrayList, you're only specifying the initial capacity, not the size (number of initial items). It will have an initial size of 0. Your func can just call add to add items.
请注意,当您创建 ArrayList 时,您只指定了初始容量,而不是大小(初始项目的数量)。它的初始大小为 0。您的 func 可以调用 add 来添加项目。
回答by John
Even better (no typing errors):
更好(没有打字错误):
ArrayList<String> name = new ArrayList<String>();
I recommend not bothering with the initial capacity argument (num) - just leave it blank and it will work perfectly. But dobother with the generic type of String in the constructor, or the compiler will complain.
我建议不要打扰初始容量参数 (num) - 只需将其留空,它就会完美运行。但是不要在构造函数中处理 String 的泛型类型,否则编译器会抱怨。
If you want to know how to use the ArrayList (for example, why to use the get() function), you should look at the documentation.
如果您想知道如何使用 ArrayList(例如,为什么要使用 get() 函数),您应该查看文档。
回答by TofuBeer
For arrays in Java when you create it all of the elements are either 0, false, or null depending in their type.
对于 Java 中的数组,当您创建它时,所有元素都是 0、false 或 null,具体取决于它们的类型。
So:
所以:
final List<String>[] foo;
foo = new ArrayList<String>[10];
foo[0].add("hello"); // crash
that crashes because foo = new ArrayList<String>[10];allocates enough room to hold 10 ArrayList<String>but it sets all of the values to null. So you need one additional step:
崩溃是因为foo = new ArrayList<String>[10];分配了足够的空间来容纳 10,ArrayList<String>但它将所有值设置为 null。所以你需要一个额外的步骤:
for(int i = 0; i < foo.length; i++)
{
foo[i] = new ArrayList<String>();
}
I haven't compiled the code, but pretty sure it is all correct. You would do that between step 1 and 2 of your program.
我还没有编译代码,但很确定它是正确的。您可以在程序的第 1 步和第 2 步之间执行此操作。
I am guessing a bit because your code isn't quite accurate (it would not generate a null pointer as written as near as I can tell).
我有点猜测,因为你的代码不是很准确(它不会生成一个空指针,就像我能说的那样写)。
EDIT:
编辑:
You would do the new in the method and the for loop with the assignments could be done inside of the method. I prefer to allocate and initialize in the same place (less confusing) but you can split it up if you needed to.
您将在方法中执行 new 并且可以在方法内部完成带有赋值的 for 循环。我更喜欢在同一个地方分配和初始化(不太容易混淆),但如果需要,您可以将其拆分。
回答by Jared Russell
The problem you are encountering is due to the fact that in Java, parameters to methods are passed by value. What this means, is that every parameter is effectively "copied" into the method, meaning that any assignments you make to the parameters are only visible within the method, and cannot be seen by the caller.
您遇到的问题是由于在 Java 中,方法的参数是按值传递的。这意味着每个参数都被有效地“复制”到方法中,这意味着您对参数所做的任何分配仅在方法内可见,调用者无法看到。
Going by your example, you're passing in a null reference to an array of List<String>'s. This reference is then "copied" into the func()method, and when func then assigns something to this variable, it is only the local variable that is being updated, and not the reference held by your calling code.
按照您的示例,您正在传递对List<String>'s数组的空引用。然后这个引用被“复制”到func()方法中,当 func 然后给这个变量赋值时,它只是被更新的局部变量,而不是你的调用代码持有的引用。
Here's some compilable code (based on your example) that demonstrates the problem:
这是一些演示问题的可编译代码(基于您的示例):
public class Main {
public static void main(String[] args) {
List<String>[] array = null;
fill(array);
System.out.println("In main(): " + array[0].get(0));
}
public static void fill(List<String>[] array) {
array = (List<String>[])new List[10];
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
}
}
The printlnin fill prints the correct value, because the arrayvariable has been assigned to something within the fill method, however the printlnin the main method throws an NPE because only the "copy" of the array variable was changed by func, and not the "real" variable.
将println在填充打印正确的值,因为array变量已被分配到的东西填充方法中,但是println在主要方法抛出NPE因为只有数组变量的“复制”被改变func,而不是“真实”多变的。
There are two ways to get around this: either instantiate the array within your calling code, or change the fill()method to return a reference to the array is has created.
有两种方法可以解决这个问题:要么在调用代码中实例化数组,要么更改fill()方法以返回对已创建数组的引用。
Below is the first approach:
下面是第一种方法:
public class Main {
public static void main(String[] args) {
List<String>[] array = (List<String>[])new List[10];
fill(array);
System.out.println("In main(): " + array[0].get(0));
}
public static void fill(List<String>[] array) {
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
}
}
You may be wondering why this works, because you're still assigning ArrayList's to the elements of the array, however these objects are visible outside of the calling method. The reason for this is that although the fill method is getting a "copy" of the reference to the array, the reference itself is still referencing the same array object. This means that you can modify the internal state of the array object, and any changes you make will be seen by the caller because it referencing that same object.
您可能想知道为什么会这样,因为您仍在将ArrayList's分配给数组的元素,但是这些对象在调用方法之外是可见的。这样做的原因是,尽管 fill 方法正在获取对数组引用的“副本”,但引用本身仍然引用相同的数组对象。这意味着您可以修改数组对象的内部状态,并且您所做的任何更改都会被调用者看到,因为它引用了相同的对象。
Below is the second approach:
下面是第二种方法:
public class Main {
public static void main(String[] args) {
List<String>[] array = fill();
System.out.println("In main(): " + array[0].get(0));
}
public static List<String>[] fill() {
List<String>[] array = (List<String>[])new List[10];
array[0] = new ArrayList<String>();
array[0].add("test");
System.out.println("In fill(): " + array[0].get(0));
return array;
}
}
(As an aside, you should generally try to avoid creating arrays of generic collections, a better idea would be to use a list to store the lists themselves. E.g:
(顺便说一句,您通常应该尽量避免创建泛型集合的数组,更好的主意是使用列表来存储列表本身。例如:
List<List<String>> list = new ArrayList<List<String>>();
list.add(new ArrayList<String>());
list.get(0).add("test");
回答by Lily Wei
new ArrayList<?>[10]give me incompatible type. However, new ArrayList[10]works for me.
new ArrayList<?>[10]给我不兼容的类型。但是,new ArrayList[10]对我有用。

