Page 1 of 2

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sun Aug 12, 2012 11:58 am
by Javanaut
I am still not clear why a) a nullpointerexception is not thrown or b) why the post-increment has no effect on the value of index.

This is a real brainer. :?

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sun Aug 12, 2012 8:04 pm
by admin
1. first index = 2 will be executed, which assigns 2 to index. After that null[2] is executed, which throws a NullPointerException. But this exception is caught by the catch block, which prints nothing. So it seems like NullPointerException is not thrown but it actually is.

2. post increment is not applied to index. It is applied to the result of getArray()[2]. Of course, before ++ can be executed, a NullPointerException is thrown as explained above.

HTH,
Paul.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Mon Aug 13, 2012 1:02 pm
by Javanaut
Ah, Thank-you Paul for the explanation. 8-)

Although, I see now that this code does throw a NullPointerException especially upon calling the printStackTrace method on the exception object, but if I pass a an array instead of null the index variable is still not post-incremented. :shock:

Code: Select all

public class Test {

	public static int[] getArray() { return new int[8]; }
	
	
	public static void main(String[] args) {
		
		
		int index = 1;
		try { 
			getArray()[index=2]++;
		}
		catch (Exception e) { e.printStackTrace();} // empty catch
		System.out.println("index = " + index);

	}

}

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Mon Aug 13, 2012 8:23 pm
by admin
Javanaut wrote:Ah, Thank-you Paul for the explanation. 8-)

Although, I see now that this code does throw a NullPointerException especially upon calling the printStackTrace method on the exception object, but if I pass a an array instead of null the index variable is still not post-incremented. :shock:

Code: Select all

public class Test {

	public static int[] getArray() { return new int[8]; }
	
	
	public static void main(String[] args) {
		
		
		int index = 1;
		try { 
			getArray()[index=2]++;
		}
		catch (Exception e) { e.printStackTrace();} // empty catch
		System.out.println("index = " + index);

	}

}
As I said before, ++ is not applied on index. We are not doing index++, we are going getArray()[2]++, so whatever is the result of getArray[2], that is incremented. Not index.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Tue Aug 14, 2012 12:12 pm
by Javanaut
heavy :o

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Tue Aug 21, 2012 8:03 am
by DooBeeDoo
Hi Enthuware Admin,

Would you kindly enlighten me on the following:

Snippet 1:

Code: Select all

public class ArrayKoPo {

    public static int[] getArray() {
        return null;
    }

    public static void main(String args[]) {
        int i = 0;
        try {
            int j = getArray()[i++];
        } catch (Exception e) {
            System.out.println(i); //prints 1 <---- This one I understand.
        }
    }
}
Snippet 2:

Code: Select all

public class ArrayKoPo {

    public static int[][] getArray() {
        return null;
    }

    public static void main(String args[]) {
        int i = 0;
        try {
            int j = getArray()[i++][i++];
        } catch (Exception e) {
            System.out.println(i); //prints 1 <---- This one I don't understand. I thought 2 will be printed.
        }
    }
}
I read somewhere in the explanation that if the array reference produces null, then a NPE is thrown at runtime, but only after all parts of the array reference expression have been evaluated and only if these evaluations completed normally.

But how come the variable i is not incremented twice in the second block of code?

What am I missing?

Thanks.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sun Dec 30, 2012 12:49 pm
by kappert
This was very surprising for me, too. To analyze complicated expressions, it may be an idea to try to duplicate what the compiler does, namely to build an expression tree.

This should also provide the answer to DooBeeDoo's question, "why is i incremented only once when getArray() returns null?" in this expression:

Code: Select all

int j = getArray()[i++][i++];
From my notes on how to create and use an expression tree (see also http://introcs.cs.princeton.edu/java/11precedence/):
1) Break into subexpressions recursively. The breaks happen at the operators of lowest precedence.
2) Within the same precedence, associativity determines sequence.
3) Traverse expression tree, left to right, leaves before nodes.

Let's start with a simple example, accessing a one-dimensional int[] myArray.
Expression: myArray[1]
Expression tree (nodes are operators, the slashes and backslashes are an attempt at painting the branches):

Code: Select all

          []
         /  \
  myArray     1
Traversal of the expression tree:
1) myArray (leaf)
2) 1 (leaf)
3) apply access array operator [] on the two leaves

Accessing a two-dimensional array:
Expression: myArray[1][2]
Expression tree:

Code: Select all

              []
             /  \
          []      2
         /  \
  myArray     1
Traversal:
1) myArray (leaf)
2) 1 (leaf)
3) apply access array operator [] on "myArray" and index 1, the result is a new leaf "IntArray1"
4) 2 (leaf)
5) apply access array operator [] on "IntArray1" and index 2

And now the more complicated expression (I did not split up all unary operators into "operator" and "operand" but for simplicity simply wrote "i++"):
Expression: int j = getArray()[i++][i++]
Expression Tree:

Code: Select all

                        =
                      /   \
                    j      []  
                         /    \
                       []       i++
                     /    \
             getArray()    i++
Traversal:
1) j (leaf)
2) getArray() (leaf), resulting in "TheArray2D"
3) i++ (leaf), resulting in "FirstIndex"
4) apply access array operator on "TheArray2D" with "FirstIndex", resulting in "IntArray1"
5) i++ (leaf), resulting in "SecondIndex"
6) apply access array operator on "IntArray1" (result of 4) using "SecondIndex", resulting in "TheIntegerResult"
7) apply assignment operator on "j" and "TheIntegerResult"

This should clear up why the second increment of i (step 5) never happens: A NullPointerException occurs at step 4 of the tree traversal. The first increment in step 3 is still done, but step 5 never happens.

You may want to play around with building expression trees for very simple expressions like 1 + 2 * 3 and so on to get a feel for it.
Please post a reply if you have a clearer explanation of how to build the expression tree.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Wed Jan 23, 2013 8:47 pm
by philfrei
I found the explanation confusing. In the top half, the statement is made that "first, index = 2 will be evaluated" but in the second half "the expression to the left of the brackets appears to be fully evaluated before any part of the expression within the brackets is evaluated". These two statements, on the surface, contradict.

Why do you say "appears to be"? That kind of muddies things too, doesn't it?

If I now understand correctly, the order of occurrences is as follows:
1) expression to left of brackets is evaluated; (null is returned in place of int[])
2) expression within brackets is evaluated;
3) attempt to obtain the value in the array is performed; (throwing null exception)
and
4) the ++ (stuff after the []) would be performed on the array value IF it had been successful.

As a reply to the 2D array question from DooBeeDoo, a simpler answer would be that a 2D array is actually implemented as array of arrays, and the null exception occurs during the first array lookup. In other words, the second [] is only evaluated after the first left-side expression and [] return a sub array. That is my guess as to what is going on there.

By the way thanks for creating this excellent learning product! I am getting a lot out of it.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Thu Feb 28, 2013 1:14 pm
by Sweetpin2
Javanaut wrote:Ah, Thank-you Paul for the explanation. 8-)

Although, I see now that this code does throw a NullPointerException especially upon calling the printStackTrace method on the exception object, but if I pass a an array instead of null the index variable is still not post-incremented. :shock:

Code: Select all

public class Test {

	public static int[] getArray() { return new int[8]; }
	
	
	public static void main(String[] args) {
		
		
		int index = 1;
		try { 
			getArray()[index=2]++;
		}
		catch (Exception e) { e.printStackTrace();} // empty catch
		System.out.println("index = " + index);

	}

}

When i change the code as below

int t = getArray()[index=2]++;
System.out.println(t);

Why i am getting value of t as 0 instead of 1 as int array is initialized with 0 & doing a post incerement should make it 1?

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Thu Feb 28, 2013 5:42 pm
by admin
because it is post increment i.e. you assign the value first and then increment.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Fri Aug 30, 2013 6:45 am
by Rafael
Sorry but I don't understand this expression

Code: Select all

   getArray()[index=2]++
What means? How does it work? I'm looking for information on google but I don't understand this format call : method()[];


Regards.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Fri Aug 30, 2013 5:44 pm
by admin
Think of it this way:

someArray = getArray()
someInt = someArray[index=2]
someInt++

So, first getArray() returns an array, on which you apply [index] to access a specific element, and then you increment the value that you get by applying index to the array.

HTH,
Paul.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Mon Sep 02, 2013 5:34 pm
by Rafael
Thanks Paul, I had never seen that expression and I was a little confused.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Wed Mar 18, 2015 1:23 am
by bbakla
Hi,
I modified the code as below:

Code: Select all

public static int[] getArray()
	{
		return new int[]{0, 1, 4, 6, 8, 10};
	}

public static void main(String[] args)
	{
		int index = 1;
		int g = 0;
		
		try
		{
			 g = getArray()[index=2]++;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
		System.out.println("index = " + index);
		System.out.println("index = " + g);
		
	}}

Since it is a post increment and it seems to increment index not result. The print out is

Code: Select all

index = 2
index = 4
But when I change the code in try expression as below

Code: Select all

g = getArray()[index=2]<<2;
g is printed out 16 so it shifts actually the result!..

Can you please help me to understand that?

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Wed Mar 18, 2015 2:42 am
by admin
Your print statement has a problem. It says "index =" but prints g.
index is not incremented due to ++. It is set to 2 because of the assignment operation index=2

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sat Mar 28, 2015 11:53 am
by bbakla
My intention is actually to print g.

if the ++ doesnt increment the variable index, shouldn't g be 5? I guess ++ operator increments g in this case

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sat Mar 28, 2015 9:31 pm
by admin
bbakla wrote:My intention is actually to print g.

if the ++ doesnt increment the variable index, shouldn't g be 5?
No, because it is postfix.
I guess ++ operator increments g in this case
No, it doesn't. Not sure why you think so.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sun Mar 29, 2015 1:58 pm
by bbakla
Now I got it. postfix increments the element in the array..

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sat May 16, 2015 2:40 am
by ElizabethCM
Hello,

Could you please explain me the observation written at this exercise with a small example?

"In an array access, the expression to the left of the brackets appears to be fully evaluated before any part of the expression within the brackets is evaluated.
Note that if evaluation of the expression to the left of the brackets completes abruptly, no part of the expression within the brackets will appear to have been evaluated."

If we have this:
 int[] a = { 1, 2, 3, 4 };       
int[] b = { 2, 3, 1, 0 };       
System.out.println( a [ (a = b)[3] ] );

First it evaluates the whole expression: a[expression]. Keeps this on its stack trace.
Then evaluates (a=b)[3]. Here a points to the same array as b. So a[3] is equivalent to b[3] which is 0.
When it gets back on the stack to evaluate a[expression], which one is evaluated here? the initially declared array a or the one that is pointing to the same array as b?

Thank you for explaining ;)

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sat May 16, 2015 4:02 am
by admin
1. As it clearly says, "the expression to the left of the brackets appears to be fully evaluated ",
in a [ (a = b)[3] ], the expression to the left of the brackets is "a", which is evaluated first. Which means, the reference to the object pointed to be a is put on the stack first.

2. Now, (a = b)[3] is evaluated. Again, the expression to the left of brackets is (a = b), thus b is assigned to a. (This doesn't change the value that has already been put on the stack in previous step.)

3. Now, a[3] is evaluated, which is actually same as b[3] because a points to the same array as b i.e. 0.

4. Finally, [0] is applied to the original reference that was stored on the stack in step 1. It points to the array { 1, 2, 3, 4 }. Thus, the complete expression finally returns 1.

HTH,
Paul.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Thu Feb 02, 2017 10:07 am
by qmwuzapz
from the exam explanation:
In an array access, the expression to the left of the brackets appears to be fully evaluated before any part of the expression within the brackets is evaluated. Note that if evaluation of the expression to the left of the brackets completes abruptly, no part of the expression within the brackets will appear to have been evaluated.
Is this the case ?

Code: Select all

class X {
    public static int [] apply(){
       if (Y.i==Y.i)throw new NullPointerException();
        return new int[]{10,8,4,6};
    }
}
public class Y {
    public static int i = 0;
    public static void main(String[] args) {
        try {
            System.out.println(X.apply()[i = 3]);
        } finally {
            System.out.println(i);
        }
    }
}

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sun Feb 26, 2017 1:05 pm
by EricLeesburg

Code: Select all


     class Test  {

         public static int[ ] getArray() {  return null;  } 

         public static void main(String[] args)    {      
         
               int index = 1;     

               try{         
 
                     getArray()[index=2]++;     //1 
                   
                     } catch (Exception e){  }  //empty catch      
  
             System.out.println("index = " + index);   
             }
      }
For the statement 1, my understanding is that it equals the statements below:

Code: Select all

                 
                int temp= getArray()[index=2];
                
                 temp++;
and getArray()[index=2] actually is a element of the array. So by the explanation " In an array access, the expression to the left of the brackets appears to be fully evaluated before any part of the expression within the brackets is evaluated. Note that if evaluation of the expression to the left of the brackets completes abruptly, no part of the expression within the brackets will appear to have been evaluated.", the getArray () should be evaluated first, then the index=2 statement. In this case, getArray() throws a NullPointerException which leaves the index=2 statement unevaluated. So, what's wrong here?

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sun Feb 26, 2017 10:18 pm
by admin
qmwuzapz wrote:from the exam explanation:
In an array access, the expression to the left of the brackets appears to be fully evaluated before any part of the expression within the brackets is evaluated. Note that if evaluation of the expression to the left of the brackets completes abruptly, no part of the expression within the brackets will appear to have been evaluated.
Is this the case ?

Code: Select all

class X {
    public static int [] apply(){
       if (Y.i==Y.i)throw new NullPointerException();
        return new int[]{10,8,4,6};
    }
}
public class Y {
    public static int i = 0;
    public static void main(String[] args) {
        try {
            System.out.println(X.apply()[i = 3]);
        } finally {
            System.out.println(i);
        }
    }
}
Yes, i will remain 0. i = 3 will not be executed.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sun Feb 26, 2017 10:24 pm
by admin
Your getArray method doesn't throw a NullPointerException. It returns null. So the statement, "if evaluation of the expression to the left of the brackets completes abruptly," doesn't apply here.

Re: About Question enthuware.ocajp.i.v7.2.1029 :

Posted: Sat Mar 23, 2019 1:36 am
by MariaRoxana
Hello,

Can someone please give an example when it applies this rule "if evaluation of the expression to the left of the brackets completes abruptly"? Meaning in which cases the evaluation completes abruptly?