Java传递值:为什么列表在移交给另一个类时会发生变化?

Java传递值:为什么列表在移交给另一个类时会发生变化?,java,pass-by-reference,pass-by-value,Java,Pass By Reference,Pass By Value,我正在为我的学校研究一个Java问题,它给了我这个实用程序类: 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 Has

我正在为我的学校研究一个Java问题,它给了我这个实用程序类:

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));
    }
}
import java.util.*;
公共类PassByValue
{
私有PassByValue(){}
公共静态无效添加(int a)
{
a=a+1;
}
公共静态无效添加(集合b)
{
b=新的HashSet();
b、 添加(“ABC”);
}
公共静态无效添加(列表c)
{
c、 加(新整数(1));
}
}
它还为我提供了这个类的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());
    }
}
导入java.io.PrintStream;
导入java.util.ArrayList;
导入java.util.HashSet;
导入java.util.List;
导入java.util.Set;
公共类PassByValueClient
{
公共静态void main(字符串[]args)
{
PrintStream输出=System.out;
INTA=1;
PassByValue.add(a);
输出println(a);
Set b=新的HashSet();
PassByValue.add(b);
output.println(b.size());
列表c=新的ArrayList();
PassByValue.add(c);
println(c.size());
}
}

我们应该预测产量。当我预测输出时,我的猜测分别是
1
0
、和
0
。然而,当我运行代码时,我得到的输出分别是
1
0
、和
1
。根据我对将参数/参数传递到方法的理解,客户机的代码应该保持不变。有人能告诉我为什么输出是
1
而不是
0

这是因为传递给PassByValue.add()的列表指向存储中的某个位置(地址),即列表中的某个位置(比如地址42)。当列表位于.add()方法中时,它仍然指向相同的地址(42)

如果你改变它,地址(42)上的数据也会改变。但两个列表仍然指向相同的地址(42),因此它们指向相同的数据

我想用图片解释一下你的例子中发生了什么:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 变量“a”

这将在存储器中创建一个地址,变量
a
指向该地址:

然后将其传递给方法
PassByValue.add(a)
时,将创建一个新变量。但是这个新变量指向相同的地址(值)

然后使用
a=a+1
对其进行更改时,该变量不再指向地址,而是指向一个新地址,并带有一个新值。

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 变量“b”

声明时,将创建指向特定地址的对象:

当您将其移交时,会创建另一个对象,该对象指向同一地址:

PassByValue.add()中将对象设置为
=newhashset()时,它指向另一个地址

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 变量“c”

更改对象本身时,情况会有所不同。

就像你用清单做的一样。 通过创建List
List c=new ArrayList()变量指向特定地址

当您将它交给
.add()
-方法时,将创建一个新变量,但它指向相同的地址

当你改变它的时候,说
c.add(新的整数(1))更改对象本身。当您更改对象本身时,存储在该地址上的数据会发生更改,但不会创建新的地址空间,而且两个变量仍然指向同一地址。

非常感谢您!这对变量b真的很有帮助,它是否因为实例化了一个新的HashSet对象而指向内存中的另一个地址?没错-我更新了变量b的答案@EdShirinian如果答案解决了您的问题,请接受答案(否则问题会一直悬而未决)。当使用
int a=1
时,您的解释不正确,当使用
整数a=1
时,您的解释是正确的。像
int
这样的原语不会像您在解释中使用的那样作为引用。Java总是按值传递,但是像
List
这样的引用类型的值是引用,因此称为“引用类型”
Integer a = 1