
- •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
•Static initialization blocks cannot throw any checked exceptions. Why? Remember that static initialization blocks are invoked when the class is loaded, so there is no way to handle the thrown exceptions in the caller. Further, there is no way to declare the checked exceptions in a throws clause.
•Non-static initialization blocks can throw checked exceptions; however, all the constructors should declare those exceptions in their throws clause. Why? The compiler merges the code for non-static initialization blocks and constructors during its code generation phase, hence the throws clause of the constructor can be used for declaring the checked exceptions that a non-static initialization block can throw.
•An overriding method cannot declare more exceptions in the throws clause than the list of exceptions declared in the throws clause of the base method. Why? The callers of the base method see only the list of the exceptions given in the throws clause of that method and will declare or handle these checked exceptions in their code (and not more than that).
•An overriding method can declare more specific exceptions than the exception(s) listed in the throws clause of the base method; in other words, you can declare derived exceptions in the throws clause of the overriding method.
•If a method is declared in two or more interfaces, and if that method declares to throw different exceptions in the throws clause, the implementation should list all of these exceptions.
Custom Exceptions
In most situations, it will be sufficient to throw exceptions that are already provided in the Java library. For example, if you’re checking for the validity of the arguments passed to a public function, and you find them to be null or out of expected range, you can throw an IllegalArgumentException. However, for most non-trivial applications, it will be necessary for you to develop your own exception classes (custom exceptions) to indicate exceptional conditions.
How do you define a custom exception? There are two options: you can extend either the Exception or RuntimeException class depending on your need. If you want to force the users of your custom exception to handle the exception, then you can extend your exception class from the Exception class, which will make your custom exception a checked exception. If you want to give flexibility to the users of your custom exception, and leave it to the users of your exception to decide if they want to handle the exception or not, you can derive your exception from the RuntimeException class. So it is a design choice that you make to choose the base class of your custom exception. How about extending the Throwable or Error class for custom exceptions? The Throwable class is too generic to make it the base class of your exception, so it is not recommended. The Error class is reserved for fatal exceptions that the JVM can throw (such as StackOverflowError), so it is not advisable to make this the base class of your exception.
Custom exceptions should extend either the Exception or RuntimeException class. It is a bad practice to create custom exceptions by extending the Throwable or Error classes.
For extending from a base class, you need to see what methods the base class provides. In this case, you want to create a custom exception by extending the Exception or RuntimeException classes. Since the Exception class is the base class of the RuntimeException class, it is sufficient to know the members of the Exception class. Table 11-4 lists the important methods (including constructors) of the Exception class.
347
Chapter 11 ■ Exceptions and Assertions
Table 11-4. Important Methods and Constructors of the Exception Class
|
|
Member |
Short description |
Exception() |
Default constructor of the Exception class with no additional (or detailed) |
|
information on the exception. |
Exception(String) |
Constructor that takes a detailed information string about the constructor as |
|
an argument. |
Exception(String, Throwable) |
In addition to a detailed information string as an argument, this exception |
|
constructor takes the cause of the exception (which is another exception) as |
|
an argument. |
Exception(Throwable) |
Constructor that takes the cause of the exception as an argument. |
String getMessage() |
Returns the detailed message (passed as a string when the exception |
|
was created). |
Throwable getCause() |
Returns the cause of the exception (if any, or else returns null). |
Throwable[] getSuppressed() |
Returns the list of suppressed exceptions (typically caused when using a |
|
try-with-resources statement) as an array. |
void printStackTrace() |
Prints the stack trace (i.e., the list of method calls with relevant line |
|
numbers) to the console (standard error stream). If the cause of an |
|
exception (which is another exception object) is available in the exception, |
|
then that information will also be printed. Further, if there are any |
|
suppressed exceptions, they are also printed. |
|
|
For illustrating how to create your own exception classes, assume that you want to create a custom exception named InvalidInputException. When you try to read input (read an integer, in this case), and if it fails, you want to throw this InvalidInputException. Listing 11-23 defines this exception class by extending the RuntimeException class.
Listing 11-23. InvalidInputException.java
//a custom "unchecked exception" that is meant to be thrown
//when the input provided by the user is invalid
class InvalidInputException extends RuntimeException {
// default constructor
public InvalidInputException() {
super();
}
// constructor that takes the String detailed information we pass while // raising an exception
public InvalidInputException(String str) {
super(str);
}
// constructor that remembers the cause of the exception and // throws the new exception
public InvalidInputException(Throwable originalException) {
super(originalException);
}
348
Chapter 11 ■ exCeptions and assertions
//first argument takes detailed information string created while
//raising an exception
//and the second argument is to remember the cause of the exception public InvalidInputException(String str, Throwable originalException) {
super(str, originalException);
}
}
In this InvalidInputException class, you did not introduce any new fields but you can add any fields if necessary. This is also a simple custom exception where the constructors simply call the base class versions of the same constructor type. The class CustomExceptionTest (see Listing 11-24) shows how to make use of this custom exception.
Listing 11-24. InvalidInputException.java
import java.util.*;
// class for testing the custom exception InvalidInputException class CustomExceptionTest {
public static int readIntFromConsole() {
Scanner consoleScanner = new Scanner(System.in); int typedInt = 0;
try {
typedInt = consoleScanner.nextInt(); } catch(NoSuchElementException nsee) {
System.out.println("Wrapping up the exception and throwing it...");
throw new InvalidInputException("Invalid integer input typed in console", nsee);
}catch(Exception e) {
//call all other exceptions here ...
System.out.println("Error: Encountered an exception and could not read an integer from the console... ");
}
return typedInt;
}
public static void main(String [] args) { System.out.println("Type an integer in the console: "); try {
System.out.println("You typed the integer value: " + readIntFromConsole()); } catch(InvalidInputException iie) {
System.out.println("Error: Invalid input in console... "); System.out.println("The current caught exception is of type: " + iie); System.out.println("The originally caught exception is of type: " + iie.getCause());
}
}
}
349