Abdul Rahman Abdul Rahman - 1 month ago 16
Java Question

why the output shown like that ? java

i'm little confused why the out put gave me the value of m = 1111???
here is the code :

class X
{
int m = 1111;

{
m = m++;

System.out.println(m);
}
}

class Y extends X
{
{
System.out.println(methodOfY());
}

int methodOfY()
{
return m-- + --m;
}
}

public class MainClass
{
public static void main(String[] args)
{
Y y = new Y();
}
}


could you please explain why the output be like that ?

Answer

The execution order is defined from super- to subclass and within the classes, first the static initialization of variables are executed, before initializer-blocks are executed. This gives the following order:

class X {
    int m = 1111; // 1st point visited

    // This is X's initializer block:
    {
        m = m++; // 2nd point visited: m's value is not changed, read below
        System.out.println(m);
    }
}

class Y extends X {
    // This is Y's initializer block:
    {
        System.out.println(methodOfY()); // 3rd and 5th point visited: 
                                         // 2220 is printed after
                                         // methodOfY() has been evaluated
    }

    int methodOfY() {
        return m-- + --m; // 4th point visited: m-- = 1111 (m = 1110),
                          // --m = 1109 (m = 1109), therefore 2220 is 
                          // returned
    }
}

public class MainClass {
    public static void main(String[] args) {
        Y y = new Y();
    }
}

Now to the pre- and postincrement operator. You can implement them "by hand"1 to understand their behaviour:

public class PrePostIncrement {
    int value;

    public PrePostIncrement(int value) {
        this.value = value;
    }

    public int preIncrement() {
        this.value = this.value + 1;
        return (this.value);
    }

    public int postIncrement() {
        int result = this.value;
        this.value = this.value + 1;
        return (result);
    }

    public static void main(String... args) {
        PrePostIncrement test = new PrePostIncrement(1111);
        int newValue = test.postIncrement();
        System.out.println(newValue);
    }
}

As you see, the value returned by postIncrement() is 1111. This will be the new value assigned to m in X's initializer block. Thus, m will have the value of 1112 just for a very brief.

Since I do not expect you to simply believe me, I wrote some code showing exactly this behaviour:

public class Main {
    public static volatile int x = 0;
    public static volatile boolean running = true;

    public static void main(String... args) {
        Thread observer = new Thread(() -> {
            while (true) {
                int x = Main.x;
                System.out.println("Observer observed: " + x);
                if (0 != x) {
                    break;
                }
            }
            Main.running = false;
        });
        observer.start();

        while (running) {
            Main.x = Main.x++;
        }
        System.out.println(Main.x);
    }
}

As you see, observer's only purpose is to print x's value, until it sees x's value as 1. The main thread keeps executing x = x++; until observer has seen one change in x's value. Afterwards, the final value of x will be printed. Please note that this program must be run on a true multicore-system, otherwise it may run in an endless loop.

On my system, I usually get one to six iterations of observer until the change is seen. The final value of x, however, will always be ´0´2.

P.S.: Welcome to the world of Java Concurrency. If one would write an application with multiple threads, that need concurrent access to x, one would most probably define x as AtomicInteger and use the methods int incrementAndGet() (instead of ++x) and int getAndIncrement() (instead of ++x). Those methods guarantee that the intermediate values of x are not seen by other threads.


1Please never do such a thing. ++i and i++ are language constructs and highly optimizable by the compiler. This is only to demonstrate their behaviour.

2It is possible that even on a multicore-system this program runs in an endless-loop, but the programm will terminate almost surely. Reasoning is that the probability of observer seeing x's value as 0 is < 1 and something < 1 to the power of n for n towards infinity is 0.