
- •Contents at a Glance
- •Contents
- •About the Authors
- •About the Technical Reviewer
- •Acknowledgments
- •Introduction
- •Oracle Java Certifications: Overview
- •FAQ 1. What are the different levels of Oracle Java certification exams?
- •FAQ 4. Is OCPJP 7 prerequisite for other Oracle certification exams?
- •FAQ 5. Should I take the OCPJP 7 or OCPJP 6 exam?
- •The OCPJP 7 Exam
- •FAQ 7. How many questions are there in the OCPJP 7 exam?
- •FAQ 8. What is the duration of the OCPJP 7 exam?
- •FAQ 9. What is the cost of the OCPJP 7 exam?
- •FAQ 10. What are the passing scores for the OCPJP 7 exam?
- •FAQ 11. What kinds of questions are asked in the OCPJP 7 exam?
- •FAQ 12. What does the OCPJP 7 exam test for?
- •FAQ 13. I’ve been a Java programmer for last five years. Do I have to prepare for the OCPJP 7 exam?
- •FAQ 14. How do I prepare for the OCPJP 7 exam?
- •FAQ 15. How do I know when I’m ready to take the OCPJP 7 exam?
- •Taking the OCPJP 7 Exam
- •FAQ 16. What are my options to register for the exam?
- •FAQ 17. How do I register for the exam, schedule a day and time for taking the exam, and appear for the exam?
- •The OCPJP 7 Exam: Pretest
- •Answers with Explanations
- •Post-Pretest Evaluation
- •Essentials of OOP
- •FunPaint Application: An Example
- •Foundations of OOP
- •Abstraction
- •Encapsulation
- •Inheritance
- •Polymorphism
- •Class Fundamentals
- •Object Creation
- •Constructors
- •Access Modifiers
- •Public Access Modifier
- •Private Access Modifier
- •Protected and Default Access Modifier
- •Overloading
- •Method Overloading
- •Constructor Overloading
- •Overload resolution
- •Points to Remember
- •Inheritance
- •Runtime Polymorphism
- •An Example
- •Overriding Issues
- •Overriding: Deeper Dive
- •Invoking Superclass Methods
- •Type Conversions
- •Upcasts and Downcasts
- •Casting Between Inconvertible Types
- •Using “instanceof” for Safe Downcasts
- •Java Packages
- •Working with Packages
- •Static Import
- •Summary
- •Abstract Classes
- •Points to Remember
- •Using the “final” Keyword
- •Final Classes
- •Final Methods and Variables
- •Points to Remember
- •Using the “static” Keyword
- •Static Block
- •Points to Remember
- •Flavors of Nested Classes
- •Static Nested Classes (or Interfaces)
- •Points to Remember
- •Inner Classes
- •Points to Remember
- •Local Inner Classes
- •Points to Remember
- •Anonymous Inner Classes
- •Points to Remember
- •Enum Data Types
- •Points to Remember
- •Summary
- •Interfaces
- •Declaring and Using Interfaces
- •Points to Remember
- •Abstract Classes vs. Interfaces
- •Choosing Between an Abstract Class and an Interface
- •Object Composition
- •Composition vs. Inheritance
- •Points to Remember
- •Design Patterns
- •The Singleton Design Pattern
- •Ensuring That Your Singleton Is Indeed a Singleton
- •The Factory Design Pattern
- •Differences Between Factory and Abstract Factory Design Patterns
- •The Data Access Object (DAO) Design Pattern
- •Points to Remember
- •Summary
- •Generics
- •Using Object Type and Type Safety
- •Using the Object Class vs. Generics
- •Container Implementation Using the Object Class
- •Container Implementation Using Generics
- •Creating Generic Classes
- •Diamond Syntax
- •Interoperability of Raw Types and Generic Types
- •Generic Methods
- •Generics and Subtyping
- •Wildcard Parameters
- •Limitations of Wildcards
- •Bounded Wildcards
- •Wildcards in the Collections Class
- •Points to Remember
- •The Collections Framework
- •Why Reusable Classes?
- •Basic Components of the Collections Framework
- •Abstract Classes and Interfaces
- •Concrete Classes
- •List Classes
- •ArrayList Class
- •The ListIterator Interface
- •The LinkedList Class
- •The Set Interface
- •The HashSet Class
- •The TreeSet Class
- •The Map Interface
- •The HashMap Class
- •Overriding the hashCode() Method
- •The NavigableMap Interface
- •The Queue Interface
- •The Deque Interface
- •Comparable and Comparator Interfaces
- •Algorithms (Collections Class)
- •The Arrays Class
- •Methods in the Arrays Class
- •Array as a List
- •Points to Remember
- •Summary
- •Generics
- •Collections Framework
- •Processing Strings
- •String Searching
- •The IndexOf() Method
- •The regionMatches() Method
- •String Parsing
- •String Conversions
- •The Split() Method
- •Regular Expressions
- •Understanding regex Symbols
- •Regex Support in Java
- •Searching and Parsing with regex
- •Replacing Strings with regex
- •String Formatting
- •Format Specifiers
- •Points to Remember
- •Summary
- •Reading and Writing from Console
- •Understanding the Console Class
- •Formatted I/O with the Console Class
- •Special Character Handling in the Console Class
- •Using Streams to Read and Write Files
- •Character Streams and Byte Streams
- •Character Streams
- •Reading Text Files
- •Reading and Writing Text Files
- •“Tokenizing” Text
- •Byte Streams
- •Reading a Byte Stream
- •Data Streams
- •Writing to and Reading from Object Streams: Serialization
- •Serialization: Some More Details
- •Points to Remember
- •Summary
- •A Quick History of I/O APIs
- •Using the Path Interface
- •Getting Path Information
- •Comparing Two Paths
- •Using the Files Class
- •Checking File Properties and Metadata
- •Copying a File
- •Moving a File
- •Deleting a File
- •Walking a File Tree
- •Revisiting File Copy
- •Finding a File
- •Watching a Directory for Changes
- •Points to Remember
- •Summary
- •Introduction to JDBC
- •The Architecture of JDBC
- •Two-Tier and Three-Tier JDBC Architecture
- •Types of JDBC Drivers
- •Setting Up the Database
- •Connecting to a Database Using a JDBC Driver
- •The Connection Interface
- •Connecting to the Database
- •Statement
- •ResultSet
- •Querying the Database
- •Updating the Database
- •Getting the Database Metadata
- •Points to Remember
- •Querying and Updating the Database
- •Performing Transactions
- •Rolling Back Database Operations
- •The RowSet Interface
- •Points to Remember
- •Summary
- •Define the Layout of the JDBC API
- •Connect to a Database by Using a JDBC driver
- •Update and Query a Database
- •Customize the Transaction Behavior of JDBC and Commit Transactions
- •Use the JDBC 4.1 RowSetProvider, RowSetFactory, and RowSet Interfaces
- •Introduction to Exception Handling
- •Throwing Exceptions
- •Unhandled Exceptions
- •Try and Catch Statements
- •Programmatically Accessing the Stack Trace
- •Multiple Catch Blocks
- •Multi-Catch Blocks
- •General Catch Handlers
- •Finally Blocks
- •Points to Remember
- •Try-with-Resources
- •Closing Multiple Resources
- •Points to Remember
- •Exception Types
- •The Exception Class
- •The RuntimeException Class
- •The Error Class
- •The Throws Clause
- •Method Overriding and the Throws Clause
- •Points to Remember
- •Custom Exceptions
- •Assertions
- •Assert Statement
- •How Not to Use Asserts
- •Summary
- •Introduction
- •Locales
- •The Locale Class
- •Getting Locale Details
- •Resource Bundles
- •Using PropertyResourceBundle
- •Using ListResourceBundle
- •Loading a Resource Bundle
- •Naming Convention for Resource Bundles
- •Formatting for Local Culture
- •The NumberFormat Class
- •The Currency Class
- •The DateFormat Class
- •The SimpleDateFormat Class
- •Points to Remember
- •Summary
- •Introduction to Concurrent Programming
- •Important Threading-Related Methods
- •Creating Threads
- •Extending the Thread Class
- •Implementing the Runnable Interface
- •The Start( ) and Run( ) Methods
- •Thread Name, Priority, and Group
- •Using the Thread.sleep() Method
- •Using Thread’s Join Method
- •Asynchronous Execution
- •The States of a Thread
- •Two States in “Runnable” State
- •Concurrent Access Problems
- •Data Races
- •Thread Synchronization
- •Synchronized Blocks
- •Synchronized Methods
- •Synchronized Blocks vs. Synchronized Methods
- •Deadlocks
- •Other Threading Problems
- •Livelocks
- •Lock Starvation
- •The Wait/Notify Mechanism
- •Let’s Solve a Problem
- •More Thread States
- •timed_waiting and blocked States
- •waiting State
- •Using Thread.State enum
- •Understanding IllegalThreadStateException
- •Summary
- •Using java.util.concurrent Collections
- •Semaphore
- •CountDownLatch
- •Exchanger
- •CyclicBarrier
- •Phaser
- •Concurrent Collections
- •Apply Atomic Variables and Locks
- •Atomic Variables
- •Locks
- •Conditions
- •Multiple Conditions on a Lock
- •Use Executors and ThreadPools
- •Executor
- •Callable, Executors, ExecutorService, ThreadPool, and Future
- •ThreadFactory
- •The ThreadLocalRandom Class
- •TimeUnit Enumeration
- •Use the Parallel Fork/Join Framework
- •Useful Classes of the Fork/Join Framework
- •Using the Fork/Join Framework
- •Points to Remember
- •Summary
- •Using java.util.concurrent Collections
- •Applying Atomic Variables and Locks
- •Using Executors and ThreadPools
- •Using the Parallel Fork/Join Framework
- •Chapter 3: Java Class Design
- •Chapter 4: Advanced Class Design
- •Chapter 5: Object-Oriented Design Principles
- •Chapter 6: Generics and Collections
- •Chapter 7: String Processing
- •Chapter 8: Java I/O Fundamentals
- •Chapter 9: Java File I/O (NIO.2)
- •Chapter 10: Building Database Applications with JDBC
- •Chapter 11: Exceptions and Assertions
- •Chapter 12: Localization
- •Chapter 13: Threads
- •Chapter 14: Concurrency
- •OCPJP7 Exam (1Z0-804 a.k.a. Java SE 7 Programmer II) Topics
- •OCPJP 7 Exam (1Z0-805, a.k.a. Upgrade to Java SE 7 Programmer) Topics
- •Answers and Explanations
- •Answer Sheet
- •Answers and Explanations
- •Index
Chapter 11 ■ Exceptions and Assertions
First compile and run this program before reading the discussion of the code.
D:\> java CustomExceptionTest Type an integer in the console: one
Wrapping up the exception and throwing it...
Error: Invalid input in console...
The current caught exception is of type: InvalidInputException: Invalid integer input typed in console
The originally caught exception is of type: java.util.InputMismatchException
In this code, you use InvalidInputException just like any other exception already defined in the Java library. You are catching the InvalidInputException thrown from the readIntFromConsole() method in the main() method. The following statement invokes the toString() method of the InvalidInputException:
System.out.println("The current caught exception is of type: " + iie);
You did not override the toString() method, so the InvalidInputException class inherits the default implementation of the toString() method from the RuntimeException base class. This default toString() method prints the name of the exception thrown (InvalidInputException) and it also includes the detailed information string (“Invalid integer input typed in console”) that you passed while creating the exception object. The last statement in the main() method is to get the cause of the exception.
System.out.println("The originally caught exception is of type: " + iie.getCause());
Since the cause of InvalidInputException is InputMismatchException, this exception name is printed in the console as a fully qualified name, java.util.InputMismatchException. You can think of InputMismatchException causing InvalidInputException; these two exceptions are known as chained exceptions.
Assertions
When creating application programs, you assume many things. However, often it happens that the assumptions don’t hold, resulting in an erroneous condition. The assert statement is used to check or test your assumptions about the program.
The keyword assert provides support for assertions in Java. Each assertion statement contains a Boolean expression. If the result of the Boolean expression is true, it means the assumption is true, nothing happens. However, if the Boolean result is false, then the assumption you had about the program holds no more, and an AssertionError is thrown. Remember that the Error class and its derived classes indicate serious runtime errors and are not meant to be handled. In the same way, if an AssertionError is thrown, the best course of action is not to catch the exception and to allow the program to terminate. After that, you need to examine why the assumption did not hold true and then fix the program.
There are many reasons why you should add assertions to the program. One reason is that it helps find the problems early; when you check your assumptions in the program, and when any of them fail, you immediately know where to look out for the problem and what to fix. Also, when other programmers read your code with assertions, they will be in a better position to understand the code because you are making your assumptions explicit using assertions.
Assert Statement
Assert statements in Java are of two forms:
assert booleanExpression;
assert booleanExpression : "Detailed error message string";
350
Chapter 11 ■ Exceptions and Assertions
It is a compiler error if a non-Boolean expression is used within the assert statement. Listing 11-25 contains the first example for assertions.
Listing 11-25. AssertionExample1.java
class AssertionExample1 {
public static void main(String []args) {
int i = -10;
if(i < 0) {
// if negative value, convert into positive value
i = -i;
}
System.out.println("the value of i is: " + i);
// at this point the assumption is that i cannot be negative;
// assert this condition since its an assumption that will always hold
assert (i >= 0) : "impossible: i is negative!";
}
}
In this program, you are checking if the value of i is < 0; you are using the expression –i to convert it to a positive value. Once the condition check if (i < 0) is completed, the value of i cannot be negative, or that is your assumption. Such assumptions can be asserted with an assert statement. Here is the assert statement:
assert (i >= 0) : "impossible: i is negative!";
The program will run fine if the Boolean expression (i >= 0) evaluates to true. However, if it evaluates to false, the program will crash by throwing an AssertionError. Let’s check this behavior (you need to use the –ea flag to enable assertions at runtime; we will discuss more about this flag in a moment).
D:\>java -ea AssertionExample1 the value of i is: 10
Yes, this program executed successfully without throwing any exceptions.
Is there any value of i for which the condition will fail? Yes, there is! If the value of i is a minimum possible value of integer, then it cannot be converted into a positive value. Why? Remember that the range of integers is -231 to 231 – 1, so the integer values the value of i as –2147483648 to 2147483647. In other words, the positive value 2147483648 is not in the range of integers. So, if the value of i is –2147483648, then the expression -i will overflow and again result in the value –2147483648. Thus, your assumption is not true.
In Listing 11-25, change the value of i to the minimum value of an integer, as in the following:
int i = Integer.MIN_VALUE;
Now, try running this program.
D:\> java -ea AssertionExample1 the value of i is: -2147483648
Exception in thread "main" java.lang.AssertionError: impossible: i is negative! at AssertionExample1.main(AssertionExample1.java:12)
In this output, note how the assertion failed. The application crashes because the program threw the AssertionError, and there is no handler, so the program terminates.
351
Chapter 11 ■ Exceptions and Assertions
You saw that assertions are disabled at runtime; to enable assertions at runtime, use an -ea switch (or its longer form of -enableasserts). To disable assertions at runtime, use a -da switch. If assertions are disabled by default at runtime, then what is the use of -da switch? There are many uses. For example, if you want to enable assertions for all classes within a given package and want to disable asserts in a specific class in that package, then a -da switch is useful. Table 11-5 lists the important command-line arguments and their meaning. Note that you need not recompile your programs to enable or disable assertions; just use the command-line arguments when invoking the JVM to enable or disable them.
Table 11-5. Important Command-Line Arguments for Enabling/Disabling Assertions
|
|
Command-Line Argument |
Short Description |
-ea |
Enables assertions by default (except system classes). |
-ea:<class name> |
Enables assertions for the given class name. |
-ea:<package name>... |
Enables assertions in all the members of the given package <package name>. |
-ea:... |
Enable assertions in the given unnamed package. |
-esa |
Short for -enablesystemsassertions; enables assertions in system classes. This |
|
option is rarely used. |
-da |
Disable assertions by default (except system classes). |
-da:<class name> |
Disable assertions for the given class name. |
-ea:<package name>... |
Disables assertions in all the members of the given package <package name>. |
-da:... |
Disable assertions in the given unnamed package. |
-dsa |
Short for -disablesystemsassertions; disables assertions in system classes. |
|
This option is rarely used. |
|
|
How Not to Use Asserts
The key to understanding assertions is that they are useful for debugging and testing applications, and assertions are meant to be disabled when the application is deployed to end users.
•Don’t use assertions for validating input values or for validating arguments to public methods. For signaling such runtime failures, use exceptions instead.
•Don’t use assertions to check conditions that are required for the correct functioning of the application. Since assertions are disabled by default at runtime, the application will not function correctly when the asserted conditions are not present in the code.
•The Boolean expressions given inside assert statements should not have side effects— modifying variable values, printing values to console, etc. In other words, the functioning of the application should remain the same no matter if assertions are enabled or disabled.
352

Chapter 11 ■ Exceptions and Assertions
Question Time!
1.Consider the following class hierarchy from the package java.nio.file and answer the question.
Exception
IOException
FileSystemException
AccessDeniedException |
DirectoryNotSupportedException |
AtomicMoveNotSupportedException FileAlreadyExistsException
In the following class definitions, the base class Base has the method foo() that throws a FileSystemException; the derived class Deri extending the class Base overrides the foo() definition.
class Base {
public void foo() throws FileSystemException {
throw new FileSystemException("");
}
}
class Deri extends Base {
/* provide foo definition here */
}
Which of the following overriding definitions of the foo() method in the Deri class are compatible with the base class foo() method definition? Choose all the foo() method definitions that could compile without errors when put in the place of the comment: /* provide foo definition here */
A.
public void foo() throws IOException { super.foo();
}
B.
public void foo() throws AccessDeniedException {
throw new AccessDeniedException("");
}
353
Chapter 11 ■ Exceptions and Assertions
C.
public void foo() throws FileSystemException, RuntimeException {
throw new NullPointerException();
}
D.
public void foo() throws Exception {
throw new NullPointerException();
}
Answer: B and C.
(In option A and D, the throws clause declares to throw exceptions IOException and Exception respectively, which are more general than the FileSystemException, so they are not compatible with the base method definition. In option B, the foo() method declares to throw AccessDeniedException, which is more specific than FileSystemException, so it is compatible with the base definition of the foo() method. In option C, the throws clause declares to throw FileSystemException, which is the same as in the base definition of the foo() method. Additionally it declares to throw RuntimeException, which is not a checked exception, so the definition of the foo() method is compatible with the base definition of the foo() method).
2.Consider the following program:
class ChainedException {
public static void foo() {
try {
throw new ArrayIndexOutOfBoundsException();
} catch(ArrayIndexOutOfBoundsException oob) {
RuntimeException re = new RuntimeException(oob);
re.initCause(oob);
throw re;
}
}
public static void main(String []args) {
try {
foo();
} catch(Exception re) {
System.out.println(re.getClass());
}
}
}
When executed, this program prints which of the following?
A.class java.lang.RuntimeException
B.class java.lang.IllegalStateException
354
Chapter 11 ■ Exceptions and Assertions
C.class java.lang.Exception
D.class java.lang.ArrayIndexOutOfBoundsException Answer: B. class java.lang.IllegalStateException
(In the expression new RuntimeException(oob);, the exception object oob is already chained to the RuntimeException object. The method initCause() cannot be called on an exception object that already has an exception object chained during the constructor call. Hence, the call
re.initCause(oob); results in initCause() throwing an IllegalStateException.)
3.Consider the following program:
class ExceptionTest {
public static void foo() {
try {
throw new ArrayIndexOutOfBoundsException();
} catch(ArrayIndexOutOfBoundsException oob) {
throw new Exception(oob);
}
}
public static void main(String []args) {
try {
foo();
} catch(Exception re) {
System.out.println(re.getCause());
}
}
}
Which one of the following options correctly describes the behavior of this program?
A.java.lang.Exception
B.java.lang.ArrayIndexOutOfBoundsException
C.class java.lang.IllegalStateException
D.This program fails with compiler error(s)
Answer: D. This program fails with compiler error(s)
(The foo() method catches ArrayIndexOutOfBoundsException and chains it to an Exception object. However, since Exception is a checked exception, it must be declared in the throws clause of foo(). Hence this program results in this compiler error:
ExceptionTest.java:6: error: unreported exception Exception; must be caught or declared to be thrown
throw new Exception(oob);
^
1 error)
355

Chapter 11 ■ Exceptions and Assertions
4.Consider the following program:
import java.io.*; import java.sql.*;
class MultiCatch {
public static void fooThrower() throws FileNotFoundException {
throw new FileNotFoundException();
}
public static void barThrower() throws SQLException {
throw new SQLException();
}
public static void main(String []args) {
try {
fooThrower();
barThrower();
} catch(FileNotFoundException || SQLException multie) {
System.out.println(multie);
}
}
}
Which one of the following options correctly describes the behavior of this program?
A.This program prints the following: java.io.FileNotFoundException.
B.This program prints the following: java.sql.SQLException.
C.This program prints the following: java.io.FileNotFoundException || java.sql.SQLException.
D.This program fails with compiler error(s).
Answer: D. This program fails with compiler error(s).
(For multi-catch blocks, the single pipe (|) symbol needs to be used and not double pipe (||), as provided in this program. Hence this program will fail with compiler error(s).)
5.Consider the following class hierarchy from the package javax.security.auth.login and answer the questions.
LoginException
AccountException
AccountExpiredException AccountLockedException AccountNotFoundException
356

Chapter 11 ■ Exceptions and Assertions
5.1.Which of the following handlers that makes use of multi-catch exception handler feature will compile without errors?
A.catch (AccountException | LoginException exception)
B.catch (AccountException | AccountExpiredException exception)
C.catch (AccountExpiredException | AccountNotFoundException exception)
D.catch (AccountExpiredException exception1 | AccountNotFoundException exception2)
Answer: C. catch (AccountExpiredException | AccountNotFoundException exception)
(For A and B, the base type handler is provided with the derived type handler, hence the multicatch is incorrect. For D, the exception name exception1 is redundant and will result in a syntax error. C is the correct option and this will compile fine without errors).
5.2.Consider the following code segment, which makes use of this exception hierarchy:
try {
LoginException le = new AccountNotFoundException();
throw (Exception) le;
}
catch (AccountNotFoundException anfe) {
System.out.println("In the handler of AccountNotFoundException");
}
catch (AccountException ae) {
System.out.println("In the handler of AccountException");
}
catch (LoginException le) {
System.out.println("In the handler of LoginException");
}
catch (Exception e) {
System.out.println("In the handler of Exception");
}
When executed, which of the following statements will this code segment print?
A.In the handler of AccountNotFoundException
B.In the handler of AccountException
C.In the handler of LoginException
D.In the handler of Exception
Answer: A. In the handler of AccountNotFoundException
(In this code, the created type of the exception is AccountNotFoundException. Though the exception object is stored in the variable of type LoginException and then typecasted to Exception, the dynamic type of the exception remains the same, which is
AccountNotFoundException. When looking for a catch handler, the Java runtime looks for the exact handler based on the dynamic type of the object. Since it is available immediately as the first handler, this exactly matching catch handler got executed.)
357