Java严格按值传递。例如,如果我将整数传递给更改其值的方法而没有返回该值,则main方法中的整数将不会更改。
但是,当我将ArrayList
传递给将项目添加到列表的方法时,事实证明该方法更改了main方法中的ArrayList。
public class test {
public static void main(String[] args) {
// create a array list
ArrayList<String> item = new ArrayList<String>();
addItems(item);
System.out.println("Items in the main method are: ");
for (int i = 0; i < item.size(); i++) {
System.out.println(item.get(i));
}
System.out.println("\n***************************\n");
int num = 0;
plusOne(num);
System.out.println("The value of num in the main method is: " + num);
}
//add two items to arrayList
public static void addItems(ArrayList<String> item) {
item.add("Item #1");
item.add("Item #2");
System.out.println("Items in the addItems method are: ");
for (int i = 0; i < item.size(); i++) {
System.out.println(item.get(i));
}
}
//add one to num
public static void plusOne(int num) {
num = num +1;
System.out.println("The value of num in the plusOne method is: " + num);
}
}
以下是输出:
Items in the addItems method are:
Item #1
Item #2
Items in the main method are:
Item #1
Item #2
***************************
The value of num in the plusOne method is: 1
The value of num in the main method is: 0
这令人困惑。
为什么addItems()
更改了item
而plusOne()
没有更改num
呢?
有人可以解释吗?谢谢!
答案 0 :(得分:1)
您需要区分按值传递和按引用传递。
当您将自己的自定义类的实例或List
实例之类的对象作为方法的参数传递时,它们将通过引用传递。基本上,您仍然有一个指向原始对象的指针,并且您正在直接编辑该对象。这就是为什么您在List
中看到新项目的原因。
但是,在Java中,原始数据类型和诸如String
之类的不可变类是按值传递的。换句话说,您在num
方法内收到的plusOne
与方法外的num
不同。这就是为什么您看不到方法范围之外的更改的原因。
只要看一下String的文档,您就会看到大量的方法吸收String
并返回一个新的String
。他们不会直接修改输入字符串。
答案 1 :(得分:0)
这只是引用(如果您熟悉C / C ++,则为指针)。
在Java中,列表/数组...或任何对象都有引用,这表示Java将它们存储在同一存储单元中。
因此,当您将对象String传递给函数 addItems ()时,该对象仍保留引用。而且该函数内部对象的任何更改都将受到该变量的影响,因为该变量存储在同一存储单元中。
另一方面, plusOne()以原始类型(int / long / double)接收参数,并且没有引用。因此,函数内部的任何更改都不会受到影响。
如果您更改 plusOne(Integer num)而不是(int num),然后将参数íInteger发送给您,
答案 2 :(得分:0)
按值传递-在这种情况下,要传递的值是指向保存数组实例的内存块的地址(Java称这些引用)。
这在您的本地参数item
中分配。当您执行item.add(...)
时,它将尝试取消引用-查找-本地item
中的地址指向的对象-并对其执行操作(add
)
为说明这仍然是按值传递,请考虑以下因素(语法可能并不完全有效):
ArrayList<String> x = null;
addItems(x);
void addItems(ArrayList<String> arr) {
// arr will now have the null address
// arr.add("xxx"); -> throws NullPointerException -> nothing to dereference
// Consider another scenario, if here I do:
arr = new ArrayList<>();
// x outside won't see the change, because it had copied over its address, null
// but not the "real" x symbol reference itself.
}
对于诸如int
之类的图元,其值是内容本身,诸如3的值是复制到本地参数的一系列位。
但是对于非基本体,任何从Object
派生的内容-您基本上都将地址作为值-直到应用.
运算符为止,该运算符将查找变量引用的对象。
希望更有意义。
答案 3 :(得分:0)
这是非常基本的概念,无论Java是通过引用传递还是通过Value传递?回答Java是按值传递的,在您的情况下,当您传递原始类型时,它是通过该值的副本传递的(所有原始类型都不是引用类型),因此num在main方法中不更改,并且在ArrayList会作为对指向同一内存位置的 addItems()方法的引用的副本传递。
为进一步了解您可以从此链接Is java pass by reference or pass by value引用帖子