Java - 按值传递:为什么列表在移交给另一个class时会发生变化?
Java - Pass by value: Why does the list change when being handed over to another class?
我正在为我的学校做一个 Java 问题,它给了我这个实用程序 class:
import java.util.*;
public class PassByValue
{
private PassByValue() {}
public static void add(int a)
{
a = a + 1;
}
public static void add(Set<String> b)
{
b = new HashSet<String>();
b.add("ABC");
}
public static void add(List<Integer> c)
{
c.add(new Integer(1));
}
}
它也给了我这个 class 和 main 方法
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PassByValueClient
{
public static void main(String[] args)
{
PrintStream output = System.out;
int a = 1;
PassByValue.add(a);
output.println(a);
Set<String> b = new HashSet<String>();
PassByValue.add(b);
output.println(b.size());
List<Integer> c = new ArrayList<Integer>();
PassByValue.add(c);
output.println(c.size());
}
}
我们应该预测输出。当我预测输出结果时,我的猜测分别是 1
、0
和 0
。但是,当我 运行 代码时,我得到的输出分别是 1
、0
和 1
。根据我对将 parameters/arguments 传递给方法的理解,客户端的代码应该保持不变。有人能告诉我为什么输出是 1
而不是 0
吗?
这是因为移交给 PassByValue.add() 的列表指向您存储中的一个位置(地址),即列表的位置(例如地址 42)。而当列表在方法.add()中时,它仍然指向同一个地址(42)
如果您更改它,该地址 (42) 上的数据也会更改。但是两个列表仍然指向相同的地址(42),所以它们指向相同的数据。
我想用图片解释你的例子中发生了什么:
/////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// /////////
变量"a"
Integer a = 1
这会在您的存储中创建一个地址,变量 a
指向该地址:
然后将其传递给方法时 PassByValue.add(a)
会创建一个新变量。但是这个新变量指向相同的地址(值)。
当您用 a = a+1
更改它时,变量不再指向地址,而是指向一个新地址,具有新值。
/////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// /////////
变量"b"
当您声明它时,会创建一个指向特定地址的对象:
当你移交它时,会创建另一个指向相同地址的对象:
当你将PassByValue.add()
中的对象设置为= new HashSet<String>();
时,它指向另一个地址。
//////////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// ////
变量"c"
当您更改对象本身时,情况就不同了。
就像你对列表所做的那样。
通过创建列表 List<Integer> c = new ArrayList<>();
变量指向特定地址。
当你把它交给.add()
-方法时,一个新变量被创建,但它指向相同的地址。
然后当您通过说 c.add(new Integer(1));
来更改它时,您更改了对象本身。当您更改对象 ITSELF 时,存储在该地址上的数据会更改,但不会创建新的 address-space 并且两个变量仍指向同一地址。
我正在为我的学校做一个 Java 问题,它给了我这个实用程序 class:
import java.util.*;
public class PassByValue
{
private PassByValue() {}
public static void add(int a)
{
a = a + 1;
}
public static void add(Set<String> b)
{
b = new HashSet<String>();
b.add("ABC");
}
public static void add(List<Integer> c)
{
c.add(new Integer(1));
}
}
它也给了我这个 class 和 main 方法
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PassByValueClient
{
public static void main(String[] args)
{
PrintStream output = System.out;
int a = 1;
PassByValue.add(a);
output.println(a);
Set<String> b = new HashSet<String>();
PassByValue.add(b);
output.println(b.size());
List<Integer> c = new ArrayList<Integer>();
PassByValue.add(c);
output.println(c.size());
}
}
我们应该预测输出。当我预测输出结果时,我的猜测分别是 1
、0
和 0
。但是,当我 运行 代码时,我得到的输出分别是 1
、0
和 1
。根据我对将 parameters/arguments 传递给方法的理解,客户端的代码应该保持不变。有人能告诉我为什么输出是 1
而不是 0
吗?
这是因为移交给 PassByValue.add() 的列表指向您存储中的一个位置(地址),即列表的位置(例如地址 42)。而当列表在方法.add()中时,它仍然指向同一个地址(42)
如果您更改它,该地址 (42) 上的数据也会更改。但是两个列表仍然指向相同的地址(42),所以它们指向相同的数据。
我想用图片解释你的例子中发生了什么:
/////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// ///////// 变量"a"
Integer a = 1
这会在您的存储中创建一个地址,变量 a
指向该地址:
然后将其传递给方法时 PassByValue.add(a)
会创建一个新变量。但是这个新变量指向相同的地址(值)。
当您用 a = a+1
更改它时,变量不再指向地址,而是指向一个新地址,具有新值。
/////////////////////////////////////////// //////////////////////////////////////////////// //////////////////////////////////////////////// ///////// 变量"b"
当您声明它时,会创建一个指向特定地址的对象:
当你移交它时,会创建另一个指向相同地址的对象:
当你将PassByValue.add()
中的对象设置为= new HashSet<String>();
时,它指向另一个地址。
当您更改对象本身时,情况就不同了。
就像你对列表所做的那样。
通过创建列表 List<Integer> c = new ArrayList<>();
变量指向特定地址。
当你把它交给.add()
-方法时,一个新变量被创建,但它指向相同的地址。
然后当您通过说 c.add(new Integer(1));
来更改它时,您更改了对象本身。当您更改对象 ITSELF 时,存储在该地址上的数据会更改,但不会创建新的 address-space 并且两个变量仍指向同一地址。