Question

I have Sample class with one field and I am doing following things:

  1. Calling method with object of this class as a parameter.
  2. Make some operations on this object.
  3. Original object got changed after all.

I am doing same thing with BigInteger class object and it works different. Why is that so?

My class:

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

Invocation:

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

Output:

3
8 8
5 7
Was it helpful?

Solution

You're not doing the same thing with BigInteger - you're calling the add method which returns a reference to a new BigInteger, and you're assigning that value back to big.

Your Sample.add method changes the existing object instead:

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

If you changed it to return a reference to a new object, it would behave like BigInteger:

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

However, your Sample class is fundamentally mutable at the moment, unlike BigInteger. No operations on BigInteger change the state of an existing object; instead, they all create new objects. If you want to replicate that behaviour in Sample, you'd write it something like this:

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

It's important to understand that you're never passing objects around in Java - only references which are used to navigate to objects. So for example:

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

Here there's a single StringBuilder object, but both variables (a and b) have values which refer to the same object. Any changes made via one variable are still visible through the other variable. (See this Stack Overflow answer for more about this.)

OTHER TIPS

BigInteger is immutable and return a new object each time.

Your Sample class is mutable and when you alter it there is only one copy/value it holds.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top