传递给java中方法的对象适用于原始副本

ner*_*sol 0 java reference object biginteger

我有Sample一个领域的课,我正在做以下事情:

  1. 使用此类的对象作为参数调用方法.
  2. 对此对象进行一些操作.
  3. 原始对象毕竟发生了变化.

我对BigInteger类对象做同样的事情,它的工作方式不同.为什么会这样?

我的课:

public class Sample {
    private int number;

    public int getNumber(){
        return number;
    }

    public void setNumber(int number){
        this.number = number;
    }

    public Sample add(int number){
        this.number += number;
        return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

调用:

public class Main {

    public static void main(String[] args) {
        Main m = new Main();
        BigInteger b1 = new BigInteger("5");
        Sample s1 = new Sample();
        s1.setNumber(3);
        System.out.println(s1.getNumber());
        Sample s2 = m.checkSample(s1);
        BigInteger b2 = m.checkBig(b1);
        System.out.println(s1.getNumber()+" "+s2.getNumber());
        System.out.println(b1.toString()+" "+b2.toString());


    }
    public Sample checkSample(Sample k){
        k = k.add(5);
        return k;
    }
    public BigInteger checkBig(BigInteger big){
        big = big.add(new BigInteger("2"));
        return big;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

3
8 8
5 7
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

你没有做同样的事情BigInteger- 你正在调用add返回对new 的引用的方法BigInteger,并且你正在将该值赋值给big.

您的Sample.add方法改为改变现有对象:

public Sample add(int number){
    this.number += number;
    return this;
}
Run Code Online (Sandbox Code Playgroud)

如果您更改它以返回对新对象的引用,它将表现如下BigInteger:

public Sample add(int number){
    Sample sample = new Sample();
    sample.setNumber(sample.number + number);
    return sample;
}
Run Code Online (Sandbox Code Playgroud)

但是,与此不同,你的Sample班级目前基本上是可变BigInteger.没有操作可以BigInteger改变现有对象的状态; 相反,它们创建了新对象.如果你想复制那个行为Sample,你会写这样的东西:

public final class Sample {
    private final int number;

    public Sample(int number) {
        this.number = number;
    }

    public int getNumber(){
        return number;
    }

    public Sample add(int number){
        return new Sample(this.number + number);
    }
}
Run Code Online (Sandbox Code Playgroud)

重要的是要理解你永远不会在Java中传递对象 - 只有用于导航到对象的引用.例如:

StringBuilder a = new StringBuilder();
StringBuilder b = a;
b.append("hello");
System.out.println(a); // Prints hello
Run Code Online (Sandbox Code Playgroud)

这里有一个单一的 StringBuilder对象,但是这两个变量(ab)具有指向同一个对象的值.通过一个变量进行的任何更改仍然可以通过另一个变量看到.(有关此内容的更多信息,请参阅此Stack Overflow答案.)