Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this Java Program not showing me the result I expect?

Here is the code I have:

/* User: [email protected] Date: 21/02/15 Time: 19:53 */

public class DriverClass {

    public static void main(String[] args) throws InterruptedException {

        int upper = 15;
        Integer sumValue = null;
        Thread thread = new Thread(new Summation(upper, sumValue));
        thread.start();
        thread.join();
        System.out.println(sumValue);

    }

}

and the Summation class:

class Summation implements Runnable {

    private int upper;
    private Integer sumValue;

    public Summation(int upper, Integer sumValue) {
        this.upper = upper;
        this.sumValue = sumValue;
    }

    public void run() {
        System.out.println("Thread started...");
        int sum = 0;
        for (int i = 0; i <= upper; i++) {
            sum += i;
        }
        System.out.println("Sum is:" + sum);
        sumValue = sum;
    }

}

I will see in the console:

Thread started...
Sum is:120
null

Why the last line is 'null' ? I am expecting to see 120 again?

like image 369
Koray Tugay Avatar asked Feb 10 '26 03:02

Koray Tugay


2 Answers

OK. Let me explain with a picture. First you create a reference in the main method and assign null to it:

main
----
sumValue -----> null

Then you pass this reference to the Summation constructor. This creates a copy of the reference:

main
----
sumValue -----> null
                ^
Summation       |
----            |
sumValue --------

Then the Summation.run() emthod assigns a new integer value to the Summation.sumValue reference:

main
----
sumValue -----> null

Summation       
----            
sumValue -----> 120

As you see, the reference in the main method still points to null. That's why null is printed.

What you can do, instead, is pass a reference to a mutable object, whose state can change (like an AtomicInteger for example):

main
----
sumValue -----> AtomicInteger(0)

Then pass it to Summation:

main
----
sumValue -----> AtomicInteger(0)
                ^
Summation       |
----            |
sumValue --------

Then in Summation, modify the state of the AtomicInteger: sumValue.set(120):

main
----
sumValue -----> AtomicInteger(120)
                ^
Summation       |
----            |
sumValue --------

And then, when printing the AtomicInteger in the main method, you'll have 120, because then the main method and the Summation object have two references pointing to the same object.

Or better, you could store the result as an Integer in the Summation object, and ask for the result in the main method once the computation is done:

System.out.println(summation.getSumValue());
like image 118
JB Nizet Avatar answered Feb 15 '26 13:02

JB Nizet


This happens because Integer is immutable.

You are passing your sumValue to Summation via the constructor, but in the constructor a new Integer is created to copy the value of the one you are passing to it.

To better understand what is happening here you may want to take a look at this article keeping in mind that you are working with an immutable object (your Integer object)

Edit:

Creating your own class extending Integer? take a look at this immutable class should be final?

You can instead create an accessor a getter for your sumValue:

public class DriverClass {

    public static void main(String[] args) throws InterruptedException {
        int upper = 15;
        Integer sumValue = null;
        Summation sum = new Summation(upper, sumValue);

        Thread thread = new Thread(sum);
        thread.start();
        thread.join();

        sumValue = sum.getSumValue();

        System.out.println(sumValue);
    }

}

class Summation implements Runnable {

    private final int upper;
    private Integer sumValue;

    public Summation(int upper, Integer sumValue) {
        this.upper = upper;
        this.sumValue = sumValue;
    }

    @Override
    public void run() {
        System.out.println("Thread started...");
        int sum = 0;
        for (int i = 0; i <= upper; i++) {
            sum += i;
        }
        System.out.println("Sum is:" + sum);
        sumValue = sum;
    }

    public Integer getSumValue() {
        return sumValue;
    }
}
like image 43
antonio Avatar answered Feb 15 '26 14:02

antonio