将参数化ArrayList传递给java中的函数

时间:2010-03-20 06:29:04

标签: java arraylist

我有以下功能。

func(ArrayList `<String>`[] name) { ........ }  

该函数填充ArrayList []。 (我不想退回ArrayList[]

但是,在调用者函数中,获得的ArrayList[]将所有ArrayLists都设为null
例如。

name = new ArrayList[num];  
func(name);  
System.out.println(name[0]);

我在NullPointerException获得line 3。这是因为line 1,即我没有参数化?如果是的话,还有另外一种方法吗?因为java不允许创建参数化ArrayList的通用数组。

5 个答案:

答案 0 :(得分:1)

这显然不是你真正的代码,但你正在创建一个ArrayLists数组,这可能不是你想要的。你可以这样做:

ArrayList<String> name = new ArrayList(num);
func(name);
System.out.println(name.get(0));

请注意,在创建ArrayList时,您只需指定初始容量,而不是大小(初始项目数)。它的初始大小为0.您的func只需调用add即可添加项目。

答案 1 :(得分:1)

更好(没有输入错误):

ArrayList<String> name = new ArrayList<String>();

我建议不要打扰初始容量参数(num) - 只需将其留空即可完美运行。但是在构造函数中使用泛型类型的String,或者编译器会抱怨。

如果你想知道如何使用ArrayList(例如,为什么要使用get()函数),你应该看看the documentation

答案 2 :(得分:1)

对于Java中的数组,当你创建它时,所有元素都是0,false或null,具体取决于它们的类型。

所以:

final List<String>[] foo;

foo = new ArrayList<String>[10];
foo[0].add("hello"); // crash

崩溃,因为foo = new ArrayList<String>[10];分配了足够的空间来容纳10 ArrayList<String>,但它将所有值设置为null。所以你还需要一个额外的步骤:

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

我没有编译代码,但很确定它是正确的。您可以在程序的第1步和第2步之间执行此操作。

我猜有点因为你的代码不太准确(它不会像我所知的那样生成一个空指针)。

修改

您可以在方法中执行新操作,并且可以在方法内部完成具有分配的for循环。我更喜欢在同一个地方分配和初始化(不那么令人困惑),但如果需要,你可以将其拆分。

答案 3 :(得分:0)

您遇到的问题是由于在Java中,方法的参数是按值传递的。这意味着,每个参数都被有效地“复制”到方法中,这意味着您对参数所做的任何分配只能在方法中可见,并且调用者无法看到。

按照您的示例,您将传入对List<String>数组的空引用。然后将此引用“复制”到func()方法中,当func然后为此变量赋值时,它只是正在更新的局部变量,而不是您的调用代码所持有的引用。

以下是一些可编译的代码(基于您的示例),用于演示此问题:

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));
    }

}

填充中的println打印正确的值,因为array变量已分配给fill方法中的某些内容,但main方法中的println会抛出NPE,因为只有数组变量的“副本”由func更改,而不是“真实”变量。

有两种方法可以解决这个问题:在调用代码中实例化数组,或者更改fill()方法以返回对已创建数组的引用。

以下是第一种方法:

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));
    }

}

您可能想知道为什么这样可行,因为您仍然将ArrayList分配给数组的元素,但是这些对象在调用方法之外是可见的。这样做的原因是虽然fill方法获得了对数组的引用的“复制”,但引用本身仍然引用相同的数组 object 。这意味着您可以修改数组对象的内部状态,调用者将看到您所做的任何更改,因为它引用了同一个对象。

以下是第二种方法:

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;
    }

}

(顺便说一句,你通常应该尽量避免创建泛型集合数组,更好的办法是使用列表来存储列表本身。例如:

List<List<String>> list = new ArrayList<List<String>>();
list.add(new ArrayList<String>());
list.get(0).add("test");

答案 4 :(得分:0)

new ArrayList<?>[10]给我不兼容的类型。但是,new ArrayList[10]对我有用。