This document discusses exceptions and assertions in Java, including defining exceptions, using try/catch/finally statements, built-in exception categories, and developing programs to handle custom exceptions. It also covers appropriate uses of assertions such as validating internal invariants, control flow assumptions, and pre/postconditions. The document provides examples of throwing, catching, and propagating exceptions as well as enabling and using assertions in code.
6. Exception propagation Imagine a building, say, five stories high, and at each floor there is a deck or balcony. Now imagine that on each deck, one person is standing holding a baseball mitt. Exceptions are like balls dropped from person to person, starting from the roof. An exception is first thrown from the top of the stack (in other words, the person on the roof)
7. If it isn't caught by the same person who threw it (the person on the roof), it drops down the call stack to the previous method, which is the person standing on the deck one floor down. If not caught there, by the person one floor down, the exception/ball again drops down to the previous method (person on the next floor down), and so on until it is caught or until it reaches the very bottom of the call stack. This is called exception propagation. If an exception reaches the bottom of the call stack, it's like reaching the bottom of a very long drop; the ball explodes, and so does your program.
8. Throwing an Exception * When an error occurs within a method, the method creates an object and hands it off to the runtime system. * The object, called an exception object , contains information about the error, including its type and the state of the program when the error occurred. * Creating an exception object and handing it to the runtime system is called throwing an exception .
9. After a method throws an exception, the runtime system attempts to find something to handle it.This "somethings" to handle the exception is the ordered list of methods that had been called to get to the method where the error occurred. The list of methods is known as the call stack. call stack
27. Flow of simple exception conditions Exception try() catch() Behaviour No N/A N/A Normal Flow Yes No N/A Method Termination Yes Yes No Compile Time Error Yes Yes Yes *Terminate try{} block *Execute body of matching Catch block *Continue Normal flow after Catch block
28.
29.
30. The throws statement If a method is capable of causing an exception that it does not handle, it must specify this behavior so that callers of the method can guard themselves against that exception. You do this by including a throws clause in the method’s declaration.
31.
32. Because the program does not specify a throws clause to declare this fact, the program will not compile. To make this example compile, you need to make two changes. 1. First, you need to declare that throwOne( ) throws IllegalAccessException. 2. Second, main( ) must define a try/catch statement that catches this exception.
33.
34.
35.
36.
37.
38.
39.
40.
41. Assertions An assertion is a statement in the Java programming language that enables you to test your assumptions about your program. Suppose you assume that a number passed into a method will never be negative,to validate your assumption,you write private void methodA(int num) { if (num >= 0) { useNum(num + x); } else { // num must be < 0 // This code should never be reached! System.out.println("Yikes! num is a negative number! " + num);} }
42.
43. Forms of Assertion The assertion statement has two forms. The first, simpler form is: assert Expression1 ; where Expression1 is a boolean expression. When the system runs the assertion, it evaluates Expression1 and if it is false throws an AssertionError with no detail message. Example private void doStuff() { assert (y > x); // more code assuming y is greater than x }
44. The second form of the assertion statement is: assert Expression1 : Expression2 ; where: Expression1 is a boolean expression. Expression2 is an expression that has a value. The second form assert Expression1 : Expression2 ; Use this version of the assert statement to provide a detail message for the AssertionError. The system passes the value of Expression2 to the appropriate AssertionError constructor, which uses the string representation of the value as the error's detail message.
45.
46.
47.
48.
49.
50. It probably indicates an assumption that the suit variable will have one of only four values. To test this assumption, add the following default case: default: assert false : suit; If the suit variable takes on another value and assertions are enabled, the assert will fail and an AssertionError will be thrown. Alternative is: default: throw new AssertionError(suit); This alternative offers protection even if assertions are disabled
51. Control-Flow Invariants Place an assertion at any location you assume will not be reached. The assertions statement to use is: assert false; For example, suppose you have a method that looks like this: void foo() { for (...) { if (...) return; } // Execution should never reach this point!!! }
52. Replace the final comment so that the code now reads: void foo() { for (...) { if (...) return; } assert false; // Execution should never reach this point! }
53. Preconditions & Postconditions By convention, preconditions on public methods are enforced by explicit checks that throw particular, specified exceptions. For example: public void setRefreshRate(int rate) { // Enforce specified precondition in public method if (rate <= 0 || rate > MAX_REFRESH_RATE) throw new IllegalArgumentException("Illegal rate: " + rate); setRefreshInterval(1000/rate); } This convention is unaffected by the addition of the assert construct.
54.
55. However assertion can be used to test a non public method's precondition. If you write a private method, you almost certainly wrote (or control) any code that calls it. When you assume that the logic in code calling your private method is correct, you can test that assumption with an assertion as follows: private void doMore(int x) { assert (x > 0); // do things with x } Remember You're certainly free to compile assertion code with an inappropriate validation of public arguments,
56. Don't Use assertions to validate Command-Line arguments If your program requires command-line arguments, you'll probably use the exception mechanism to enforce them.
57.
58. If using a Java 1.4 compiler , and also using assert as a keyword (in other words, you're actually trying to assert something in your code), then you must explicitly enable assertion-awareness at compile time, as follows: javac -source 1.4 com/geeksanonymous/TestClass.java The Java 5 compiler will use the assert keyword by default, the compiler will generate an error message if it finds the word assert used as an identifier. However, you can tell the compiler that you're giving it an old piece of code to compile, javac -source 1.3 OldCode.java
59. What will happen in the following case Suppose the program is using the assert as an identifier and you compile using javac -source 1.4 NotQuiteSoOldCode.java Will the code compile?
60. In this case, the compiler will issue errors when it discovers the word assert used as an identifier. Using Java 5 Compiler
61. Enable Assertions Programmers of certain critical systems might wish to ensure that assertions are not disabled in the field. The following static initialization idiom prevents a class from being initialized if its assertions have been disabled: static { boolean assertsEnabled = false; assert assertsEnabled = true; // Intentional side effect!!! if (!assertsEnabled) throw new RuntimeException("Asserts must be enabled!!!"); }
62.
63. Selective Enabling and Disabling no arguments Enables or disables assertions in all classes except system classes. packageName ... Enables or disables assertions in the named package and any subpackages. className Enables or disables assertions in the named class
64. For example, java -ea:com.wombat.fruitbat BatTutor The following command runs a program, BatTutor, with assertions enabled in only package com.wombat.fruitbat and its subpackages: -enablesystemassertions, or -esa. To enable assertions in all system classes. java -ea -da:com.geeksanonymous.Foo this tells the JVM to enable assertions in general, but disable them in the class com.geeksanonymous.Foo. java -ea -da:com.geeksanonymous... tells the JVM to enable assertions in general, but disable them in the package com.geeksanonymous, and all of its subpackages!