繁体   English   中英

传递给Java中方法的对象在原始副本上有效

[英]Object passed to method in java works on original copy

我有一个字段的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;
    }
}

调用:

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;
    }
}

输出:

3
8 8
5 7

您没有使用BigInteger做同样的事情-您正在调用add方法,该方法返回对 BigInteger的引用,并将该值分配回big

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

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

如果更改它以返回对新对象的引用,则其行为类似于BigInteger

public Sample add(int number){
    Sample sample = new Sample();
    sample.setNumber(sample.number + number);
    return sample;
}

但是,与BigInteger不同,此刻您的Sample类目前基本上是可变的。 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);
    }
}

重要的是要了解,您永远不会在Java中传递对象 -只是用于导航到对象的引用 因此,例如:

StringBuilder a = new StringBuilder();
StringBuilder b = a;
b.append("hello");
System.out.println(a); // Prints hello

这里有一个单一 StringBuilder对象,但两个变量( ab )具有指向同一个对象的值。 通过一个变量进行的任何更改仍然可以通过另一个变量看到。 (有关更多信息,请参见此堆栈溢出答案 。)

BigInteger是不可变的,每次都返回一个新对象。

您的Sample类是可变的,当您对其进行更改时,它仅保留一个副本/值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM