永远记住Java is pass by value。
如果您在方法中重新实例化变量,则传递的变量将保持不变。您的示例正是这样做的。
String myValue = "All your variables belong to us";
setValue(myValue);
System.out.println(myValue); //All your variables belong to us
void setValue(String v){
v = "Hello World!";
}
你应该首先初始化你的变量:
import java.util.ArrayList;
public class One {
private ArrayList<Integer> list = new ArrayList<Integer>();
public One() {
addString(list);
sysoutList(list);
}
public void sysoutList(ArrayList<Integer> list2) {
for (int i = 0; i < list2.size(); i++) {
System.out.println(list2.get(i));
}
}
private void addString(ArrayList<Integer> list2) {
list2.removeAll();
list2.add(1);
list2.add(2);
list2.add(3);
list2.add(4);
}
}
列表是一种特殊情况。您可以认为 使用 add() 方法我实际上是在修改变量,因此不应该发生修改。这不是真的,为什么?
那是因为您正在为列表传递引用的值。如果您使用 new 关键字为该引用分配一个新值,您将“松开”附加到它的对象(您不再拥有它的引用)。
但是,如果您修改该对象的属性(例如使用 add() 方法),该对象的引用仍然有效,因此您修改了原始对象。
我们可以做一个类比。
想象一下,你有一个风筝系在一根绳子上。现在您将一个新字符串附加到它并将新创建的字符串传递给朋友。
如果他切断绳子(也就是创建一个new 一个),他会丢失对你的风筝的引用并且他无法触及它。他可以附加一个新的风筝并进行他想要的所有修改(又名add()),但它永远不会是你的风筝。
如果他使用你给他的绳子来接触风筝并修改它,你会收到一个修改过的风筝。
为了在您的情况下保持相似性,您正在使用private ArrayList<Integer> list; 创建一个没有风筝的字符串 (list),然后将其传递给您的朋友创建一个新字符串 (list2)。现在你和你的朋友都有一个没有附加任何东西的字符串。
他创建了一个新风筝并将其连接到他的绳子上 (list2 = new ArrayList<>()),但您的绳子仍然没有连接任何东西。当您尝试放风筝时,您会发现风筝根本不存在(null 参考)。
首先,您必须创建自己的风筝并附上绳子 (private ArrayList<Integer> list = new ArrayList<Integer>();)。当您将它传递给您的朋友时,会附加另一个字符串 (list2)。现在你的朋友可以使用list2来修改你的风筝了。
编辑
关于您的其他问题,如果可以在从构造函数调用的方法中实例化变量,答案是是,但必须将此类变量声明为static 如果你想在你的方法之外使用它。
在风筝中,就像您将风筝连接到一根绳子上,您和您的朋友使用同一根绳子对其进行操作(是的,手牵手)。
为你变成:
import java.util.ArrayList;
public class One {
private static ArrayList<Integer> list;
public One() {
addString();
sysoutList();
}
public void sysoutList() {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
private void addString() {
list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
}
}
您不需要传递ArrayList,因为您在程序中的任何地方都使用相同的“风筝字符串”。
注意:如果您调用sysoutList() 之前addString(),您仍然会得到NullPointerException,因为列表尚未初始化。
这是一种不好的做法。我强烈建议你改变你的逻辑。