12

I have the following code:

public class Book {
    private static int sample1(int i) {
        return i++;
    }
    private static int sample2(int j) {
        return ++j;
    }

    public static void main(String[] arguments){ 
        int i = 0;
        int j = 0;
        System.out.println(sample1(i++)); //0
        System.out.println(sample1(++i)); //1
        System.out.println(sample2(j++));//1
        System.out.println(sample2(++j));//2
        System.out.println(i);//2
        System.out.println(j);//2
    }
}

My expected output is in comments. The actual output is below:

0
2
1
3
2
2

I'm getting confused with the function calls and incemental operator. Can someone kindly explain the actual result?

rav_kr
  • 434
  • 8
  • 16
misguided
  • 3,699
  • 21
  • 54
  • 96
  • 2
    Your incrementing the same variable over and over. You need to reset it to zero every time you want to increment. – ctzdev Jun 26 '14 at 04:19
  • 2
    You are aware that Java is pass-by-value, so sample1 is really just ```return i;``` sand sample2 is ```return j + 1```, right? Doh! Typo fixed. Thanks @ElliottFrisch – David Ehrmann Jun 26 '14 at 04:20
  • 1
    @DavidEhrmann You mean [pass-by-value](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value)? – awksp Jun 26 '14 at 04:20
  • 1
    One is pre and one is post. Does that help? – Elliott Frisch Jun 26 '14 at 04:20
  • 1
    @ChrisTarazi I know I am incrementing same variable over and over again. I just want to explanation of how the values are getting increased step by step. – misguided Jun 26 '14 at 04:20
  • 1
    http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value?lq=1 , http://stackoverflow.com/questions/795160/java-is-never-pass-by-reference-right-right?lq=1 (discuss "assignment lost" issue) – user2864740 Jun 26 '14 at 04:27
  • My goodness--->+3 on this question!!! – Am_I_Helpful Jun 26 '14 at 04:35

7 Answers7

16

Since sample1 and sample2 are just modifying their own local variables i and j (not those of the calling method), it's clearer if we rewrite them without those modifications:

private static int sample1(int i) {
    return i;   // was 'i++', which evaluates to the old i
}
private static int sample2(int j) {
    return j + 1;   // was '++j', which evaluates to j after incrementing
}

At which point it's straightforward to just substitute them in place — sample1(...) becomes ..., and sample2(...) becomes ... + 1:

int i = 0;
int j = 0;
System.out.println(i++);
System.out.println(++i);
System.out.println((j++) + 1);
System.out.println((++j) + 1);
System.out.println(i);
System.out.println(j);

We can make this a bit clearer by separating the incrementations into their own commands. i++ evaluates to the original value of i, so it's like incrementing i after running the surrounding command; ++i, by contrast, is like incrementing i before running the surrounding command. So we get:

int i = 0;
int j = 0;
System.out.println(i);
i++;
++i;
System.out.println(i);
System.out.println(j + 1);
j++;
++j;
System.out.println(j + 1);
System.out.println(i);
System.out.println(j);

. . . at which point it should be straightforward to trace through and see what it will output.

Does that all make sense?

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • 1
    Does that mean in method `sample1` `return i` and `return i++` are the same thing ? – misguided Jun 26 '14 at 04:27
  • 1
    Yes, because Java passes method parameters by value, not by reference. The local ``i`` in ``sample1`` goes out of scope before it can be incremented – Jason Baker Jun 26 '14 at 04:30
  • OP just changed: System.out.println(j); System.out.println(j); to System.out.println(i); System.out.println(j); would you please update your answer as well? He was printing same variable twice (doesn't affect your answer, but anyway...) – Nenad Bulatović Jun 26 '14 at 05:21
13

First of all you need to know the difference between x++ and ++X;

In case of x++ :

First the current value will be used and it will be incremented next. That means you will get the present value of x for the operation and if you use x next time will get the incremented value;

In case of ++x :

First the current value will be incremented and it will be used (the incremented value) next, that means you will get the incremented value at this operation and for other after this operation.

Now lets split the code and discuss them separately

method: sample1() :

private static int sample1(int i) {
    return i++;
}

This method will take a int and return it first and then try to increment but as after returning the variable i will go out of scope so it will never be incremented at all. exp in: 10-> out 10

method: sample2() :

private static int sample2(int j) {
    return ++j;
}

This method will take a int and increment it first and then return it. exp in: 10-> out 11

In both case only the variables will change locally, that means if you call from main method the variables of main method will remain unaffected by the change (as the sample1() and sample2() are making copy of the variables)

Now for the code of the main method

System.out.println(sample1(i++)); // it's giving sample1() `i=0` then making `i=1` 
                                  //  so  sample1() will return 0 too;

System.out.println(sample1(++i)); // it's making `i=2` and then giving sample1() `i=2`
                                  // so sample1() will return 2;

System.out.println(sample2(j++)); // it's giving sample2() `j=0` then making `j=1` 
                                  // so sample2() will return 1;

System.out.println(sample2(++j)); // it's making `j=2` giving sample2() `j=2` then  
                                  // so sample2() will return 3;
rav_kr
  • 434
  • 8
  • 16
Saif
  • 6,804
  • 8
  • 40
  • 61
8

You're experiencing the fun of prefix and postfix operators.

The prefix operator, ++i increments the variable i by one before using it in the expression, where the postfix operator (i++) uses i in the expression before incrementing it.

This means that your method sample1 doesn't do anything; it evaluates the expression containing i, but because that expression is a return statement, the local variable i goes out of scope, and we can't modify it anymore.

sample2, by contrast, increments the local copy of j before returning it, which is why you print higher values of j than you expect.

Jason Baker
  • 2,471
  • 3
  • 23
  • 28
2

Easy:
1) First call:
a) Provide i (==0) to sample1(), which returns 0 (then increments the argument i, and that gets discarded).
b) increments i because of i++. i is now 1.
c) Prints the function result: 0.

2) Second call:
a) Increments i because of ++i. i is now 2.
b) Provide i (==2) to sample1(), which returns 2 (then increments the argument i, and that gets discarded)
c) Prints the function result: 2.

3) Third call:
a) Provide j (==0) to sample2(), which increments the argument, and therefore returns 1.
b) increments j because of j++. j is now 1.
c) Prints the function result: 1.

4) Fourth call:
a) Increments j because of ++j. j is now 2.
b) Provide j (==2) to sample2(), which increments the argument, and therefore returns 3.
c) Prints the function result: 3.

5 & 6) Fifth and Sixth call:
a) Prints the value of j: 2.

The key to remember here is that i++ increments the variable after passing it as an argument, whereas ++i increments the variable before passing it as an argument.

Hope this helps

NotSoOldNick
  • 555
  • 4
  • 11
  • Why does it get discarded? – misguided Jun 26 '14 at 04:36
  • 2
    Hi @misguided, it gets discarded because the method parameters' scope is local to the method only: this means that when the method returns its result, what you get is a copy of the variable, and in sample1() for instance, the increment i++ operation happens after you get hold of the method result. Java always passes method arguments by value, never by reference (contrary for instance to C++ or VB where you have the option)... – NotSoOldNick Jun 26 '14 at 04:45
  • ... So you can never provide a primitive type variable to a function, modify it in that function, and hope to see the modification outside of that function: the only way you'll see the modification is by providing a copy to the method first via a local parameter, then by returning a copy of the modified parameter back to the calling part of the code. – NotSoOldNick Jun 26 '14 at 04:45
  • This is basically what @Jason explained in his comment to ruakh's answer – NotSoOldNick Jun 26 '14 at 04:49
2

1st print

before call: i = 0

increment after call

sample1 is called with a value of 0

sample 1 returns 0, the increment is discarded

after call: i = 1

2nd print

before call: i = 1

increment before call

sample1 is called with a value of 2

sample1 returns 2, the increment is discarded

after call: i = 2

3rd print

before call: j = 0

increment after call

sample2 is called with a value of 0

sample2 the increments 0 to 1, returns it

1 is printed

increment j to 1

after call: j = 1

4th print

before call: j = 1

increment before call

increment j to 2

sample2 is called with a value of 2

sample2 the increments 2 to 3, returns it

3 is printed

after call: j = 2

5th print

prints i

2 is printed

6th print

prints j

2 is printed

Titi Wangsa bin Damhore
  • 7,101
  • 4
  • 31
  • 36
2

Both of them increase the variable i by one like i = i + 1;

The difference is that :

++i increments the value first and then return it

i++ return the value first and then increments it

This behavior difference doesn’t matter in a for loop.

If you want to know the difference try this :

int x = 0;
int y = x++;

int x = 0;
int y = ++x;

Here x++ returns the value then increments it but ++x first increments the value then returns that value

SparkOn
  • 8,806
  • 4
  • 29
  • 34
2

Form your example,

  private static int sample1(int i) {
    return i++;
  }
  private static int sample2(int j) {
  return ++j;
  }

  public static void main(String[] arguments)
  { 
  int i = 0;
  int j = 0;
  System.out.println(sample1(i++)); //0
  System.out.println(sample1(++i)); //1
  System.out.println(sample2(j++));//1
  System.out.println(sample2(++j));//2
  System.out.println(j);//2
  System.out.println(j);//2
  }
  1. i = 0; sample1(i++) -> it pass '0'->in sample1 return i++ so, 0(++) Here it returns 0 but incremented to 1 , so println is = 0 but finally i takes 1
  2. i = 1; sample1(++i) -> it pass '2'-> in sample1 return i++ so, 2(++) Here it returns 2, so println is = 2
  3. j = 0; sample2(j++) -> it pass '0'-> in sample2 return ++j so, (++)0 Here it returns 1, so println is = 1.
  4. j = 1; sample2(++j) -> it pass ++1 => 2, in sample2 return ++j so, (++)2 Here it returns 3, so println is = 3. But increment is ended with in sample2, not in main so j still holds 2.
  5. j = 2
  6. j = 2