<Previous    Back to Start  Contents   Next>


Flow Control, Assertions and Exception Handling


Write code using if, and switch statements and identify legal argument types for these statements.

Consult a text book for the basics of these, if unsure. If you do know the basics, here are a few things to watch out for:

Number 1
Be wary where if is used without braces, and with an else statement. This is referred to as the dangling else problem, and occurs in C and C++ aswell. The following example is from Boone (p.154):

if (result >=0)
	if (result > 0)		
		System.out.println("positive");	
else			
	System.out.println("negative");

The indentations are misleading. It might appear that the above code will print "positive" if result is greater than 0, "negative" if is less than zero, and print nothing if result is equal to 0. In fact, it will print "positive" if result is greater than 0, it will print nothing if is less than zero, and print "negative" if result is equal to 0. This is because the else statement belongs to the second if statement, and only executes if result >=0 but not if result>0, in other words if result equals 0. Using braces (curly brackets) would fix this and is the best practice if you want readable code that is not potentially misleading. The following indentation shows the real relationship, of course the compiler doesn't care about indentation:

if (result >=0)
	if (result > 0)
		System.out.println("positive");
	else
		System.out.println("negative");

A good practice is to use blocks with all your if and else statements to avoid this ambiguity.

Number 2
After switch/case construct has executed the correct case, it will continue to execute all those after it (including default: if it is there, after the selected case) on to the end of the switch/case block, unless you put in a break, return or throw statement. This is referred to as "falling through". For example:

switch (a) 
{
	case 1:
		System.out.println("one");
	case 2:
		System.out.println("two");
	case 3:
		System.out.println("three");
	default:
		System.out.println("some other number");
}

If a is 1, this will print "one", "two", "three" and then "some other number" in succession. If a is 3, this will print "three" and then "some other number".

In some cases, this kind of behaviour might desirable, but here it isn't. This block of code fixes it:

switch (a) {
	case 1:
		System.out.println("one");
		break;
	case 2:
		System.out.println("two");
		break;
	case 3:
		System.out.println("three");
		break;
	default:
		System.out.println("some other number");
}

Note that in switch blocks, it is legal to put default: anywhere in the block, it doesn't have to be the last one.

Number 3
The argument for an if() statement must be a boolean or an expression which evaluates to a boolean. A common beginners mistake is to use a single = rather than == to compare values. The following gives a compiler error:

public static void main(String[] args) {
	int a=1;
	if(a=2) System.out.println("a is two");
}

a=2 assigns the value 2 to a.

The argument for a switch statement must be a byte, a char, a short or an int, or an expression which evaluates to one of those.


Write code using all forms of loops including labeled and unlabeled, use of break and continue, and state the values taken by loop counter variables during and after loop execution.

An loop example:

for(int i=0;i<3;i++){ 
	System.out.println("i is "+i); 
	for(int j=0;j<3;j++) { 
		System.out.println("j is"+j); 
	}
}

Will print:

i is 0
j is 0
j is 1
j is 2
i is 1
j is 0

etc.

Note: Don't get thrown if the for loop uses pre-increment instead of post-increment i.e. for(int i=0;i<3;++j) instead of for(int i=0;i<3;j++). This does not make any difference to the behavior of a for loop.

break will cause the current loop to be abandoned. continue causes execution to skip the rest of the code in the current iteration of the loop, and start at the top of the loop with the next iteration.

These (unlabeled) versions will only affect the execution of loop that they are in. If you have nested loops, and want to break out of, or skip to the next iteration of, an outer loop, from an inner loop, you used the labeled versions. These jump to the wherever the label is, allowing you to break out of, or skip several nested loops, by placing the label in front of the outer loop.

Labels are a name followed by a colon, i.e. ":", placed before the loop.


Write code that makes proper use of exceptions and exception handling clauses (try, catch(), finally) and declares methods and overriding methods that throw exceptions.

Place code which is likely to throw an exception inside a try { } block. Create one or more catch() { } blocks with code to deal with the types of exceptions that might be thrown in the try block. The type of exception goes inside the round brackets of the catch() statement, as you would when declaring a method.

Exceptions are objects, which belong to a class hierarchy. If the exception thrown is an instance of the class, or a subclass of the class, specified in catch(), that catch block is the one executed. Your catch() block therefore can handle a range of exceptions if they are subclasses of the class specified. If you want to handle one specific subclass one way, and all the other subclasses differently, put a catch statement for the specific subclass first, and a more general catch block for the superclass second. Then when an exception is thrown, if the exception is a member of the subclass, that catch block only executes, but if it is a different subclass of the parent class, the general catch block executes. If you put the superclass first, you will get a compiler error.

Declaring exceptions in a method

For example:

void mymethod(int i) throws Exception { }

Methods can throw more than one class of exception, you list all the exceptions after the throws keyword, separated by commas.

Overriding and exceptions

Essentially, a method can throw the same or fewer, but not more, exceptions than the superclass method it is overriding. This has to do with object orientation, if you could broaden the number of exceptions in the subclass method, anything which can deal with the superclass might not be able to deal with the subclass, because the are new exceptions there that it was not designed to handle. You want all members of subclasses to be able to be handled as if there were members of the parent class ("upcasting" or polymorphism).

The hierarchy of exceptions is important here, you can replace a exception class in the overridden method with one or more of its subclasses, but you can't replace it with its superclass. To do this would be to broaden the range of exceptions the method could throw.

To create and throw a specified exception

For example:

throw new SomeKindOfException();

Recognize the effect of an exception arising at a specified point in a code fragment. Note: The exception may be a runtime exception, a checked exception, or an error (the code may include try, catch, or finally clauses in any legitimate combination).

If an exception is thrown, then the rest of the code in the try block is not executed. If any catch block matches the exceptions class or a super class of the exception, that block executes. If the exception is not caught correctly, then after the finally block executes, the rest of the code in the method is not executed.

finally blocks execute no matter what, in other words, whether the code executes without an exception, or an exception is thrown and successfully caught, or an exception is thrown and not caught. This is useful because, except for code in a finally block, if an exception is thrown and not caught, the execution of the rest method is abandoned.

It is legal to have a try block, followed by a finally block, without any catch blocks.

One thing (probably not important for the exam) which could stop a finally clause from executing, is a call to System.exit(0).

RuntimeExceptions differ from normal exceptions in that they are not required to be declared or handled within a try block. An Error indicates serious problems that a reasonable application should not try to catch. Examples are the VM running out of memory.


Write code that makes proper use of assertions, and distinguish appropriate from inappropriate uses of assertions.

For more information see: http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html.
The simplest form of assertion consists of the assert keyword followed by an expression which evaluates to a boolean. Example:

	assert someObject != null;
If the expression evaluates to false then an AssertionError is thrown. The other form adds a colon followed by a second expression which evaluates to a value of some kind. If the assertion fails, the value is included in the AssertionError for information. Example:
	assert someObject != null : "someObject should not be null at this point!";

Assertions may be enabled or disabled. Your code should work correctly in either cases. Do not do anything in an assertion which will have side affects on the behaviour of other parts of your code (with the possible exception of other assertions). Sun do not recommend the use of assertions to verify the correct use of the public API of you classes. Instead a more specific exception such as IllegalArgumentException should be used. However you can perform checks using assertions on the arguments provided to non-public methods, so long as those assertions should remain true regardless of how other classes invoke your API. In other words use assertions to confirm your is doing internally what you intended, rather than to check that it is being used correctly by others.


Identify correct statements about the assertion mechanism.

See the previous objective, or look in a textbook or on the web.


<Previous    Back to Start  Contents   Next>

©1999, 2000, 2002 Dylan Walsh.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being the disclaimer, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".