Short-Circuit Boolean Expressions

Sometimes you know that something is true without taking the time to figure out all of the details. For instance, if someone says to you, "I will go out for a run if the sun is shining or ...", it doesn't really matter what comes after the OR — as long as you know the sun is shining. A Java program does the same thing. It can often figure out if an expression will be true or false without evaluating the entire expression. It takes a short-cut, called "short-circuit evaluation," to arrive at the same answer.

Opportunities for short-circuit evalution are apparent from the truth tables examined in the previous lab exercise. When two expressions are joined by OR (||), if the first one is true, the answer will always be true. When two expressions are joined by AND (&&), if the first one is false, the answer will aways be false. It doesn't matter what the second expression is and hence, it doesn't need to be evaluated.

|| true false
true true true
false true false
&& true false
true true false
false false false

Open project.jpr, found in the Booleans folder that you downloaded earlier. The main method contains

	public static void main(String[] args)
	{  ShortCircuitTest sct = new ShortCircuitTest();

	   if (sct.isTrue("left") && sct.isTrue("right"))
	   {  System.out.println("Expression is true.");
	   } else
	   {  System.out.println("Expression is false.");
	   }
	   System.out.println("All done.");
	}

isTrue is a predicate that always returns true. This is pretty useless except that it also prints out it's argument, "left" or "right", when it is called. We can use this to understand short-circuit evaluation more thoroughly. The definition of isTrue is

	public boolean isTrue(String msg)
	{  System.out.println("in isTrue   (arg = '" + msg + "')");
	   return true;
	}

When this program is run (do it!), it prints out

	in isTrue (arg = 'left')
	in isTrue (arg = 'right')
	Expression is true.
	All done.

This shows that to evaluate the if statement, both the expression on the left of the && and the expression on the right were evaluated.

Now change the left-most isTrue to isFalse in the if statement. It should now read

	if(sct.isFalse("left") && sct.isTrue("right")) 
Run the program. What is the output?

Explain the number of lines of output.

Which of the following conditions will result in only a single line of output? (Note: The code always prints out a line that starts with “Expression is...” and another that says “All done.” Ignore them when counting lines of output.)

isTrue("left") || isTrue("right")

isFalse("left") || isTrue("right")

isTrue("left") || isFalse("right")

isFalse("left") || isFalse("right")

Using Short-Circuit Evaluation

Add the following code to the end of the main method, along with import java.util.ArrayList; at the beginning of the file:

	ArrayList aList = new ArrayList();
	aList.add("Cobol");
	aList.add("Pascal");
	aList.add("Java");
	aList.add("Cobol");
	aList.add("Basic");
	aList.add("Java");

	// find first position containing "Java"
	int pos = 0;
	while (!aList.get(pos).equals("Java"))  // while we haven't found "Java"
	{  pos++;
	}
	System.out.println("'Java' is at position " + pos);

Run the program. It should print out “'Java' is at position 2.” Now, remove both lines adding “Java” to the ArrayList. Re-run the program. You'll get a nasty exception because the while loop tried to access an invalid position in the ArrayList. The while loop should only continue if we haven't yet found the string we're looking for AND we haven't reached the end of the ArrayList.

Do the following:

  1. Replace the last line with
    	if (pos < aList.size())
    	{  System.out.println("'Java' is at position " + pos);
    	} else
    	{  System.out.println("'Java' is not in the ArrayList.");
    	}
    
  2. Change the test for the while loop so that if pos is beyond the end of the ArrayList, the test for equality with “Java” is not performed because of short-circuit evaluation. (Hint: Your new test should also use the size method.)
  3. Test your changes.
  4. What is the new test for your while loop?