
- •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 12 ■ Localization
You create resource bundles by extending the ListResourceBundle class, whereas with PropertyResourceBundle, you create the resource bundle as property files. Furthermore, when extending ListResourceBundle, you can have any type of objects as values, whereas values in a properties file can only be Strings.
Loading a Resource Bundle
You’ve already loaded resource bundles in the programs you’ve written using ResourceBundle or its two derived classes. You need to understand this loading process thoroughly, and we’ll cover it in more detail in this section.
The process of finding a matching resource bundle is same for classes extended from ListResourceBundles as for property files defined for PropertyResourceBundles.
For the resource bundles implemented as classes extended from ListResourceBundles, Java uses the reflection mechanism to find and load the class. You need to make sure that the class is public so that the reflection mechanism will find the class.
Naming Convention for Resource Bundles
Java enforces a predefined naming convention to be followed for creating resource bundles. Only through the names of the property bundles does the Java library load the relevant locales. Hence, it is important to understand and follow this naming convention when creating the property bundles for localizing Java applications.
You already saw how a locale name is encoded. Understanding this locale name encoding is important for naming the resource bundles because it makes use of the same encoding scheme. A fully qualified resource bundle has the following form:
packagequalifier.bundlename + "_" + language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
Here is the description of the elements in this fully qualified name:
•packagequalifier: The name of the package (or the subpackages) in which the resource bundle is provided.
•bundlename: The name of the resource bundle that you’ll use in the program to refer and load it.
•language: A two-letter abbreviation typically given in lowercase for the locale’s language (in rare cases, it could be three letters as well).
•country: A two letter abbreviation typically given in uppercase for the locale’s country (in rare cases, it could be three letters as well).
•variant: An arbitrary list of variants (in lowercase or uppercase) to differentiate locales when you need more than one locale for a language and country combination.
We’ve omitted describing script and extension since they are rarely used.
372

Chapter 12 ■ Localization
For example, consider this fully qualified name:
localization.examples.AppBundle_en_US_Oracle_exam
In this case, localization.examples is the package, AppBundle is the name of the resource bundle, en is language (which stands for English), US is the country, and Oracle_exam is the variant.
The two (or sometimes three) letter abbreviations for the locale’s language and country are predefined since they are based on international standards. We don’t provide the detailed list and there is also no need to know or remember all of them. You can look at the documentation of the Locale class to understand that.
On the OCPJP 7 exam, you’re not expected to memorize language codes or country codes that are used for naming resource bundles. However, you are expected to remember the naming convention and recognize the constituents of a fully qualified resource bundle name.
Given that there could be many resource bundles for a bundle name, what is the search sequence to determine the resource bundle to be loaded? To clarify, we present the sequence as a series of steps. The search starts from Step 1. If at any step the search finds a match, the resource bundle is loaded. Otherwise, the search proceeds to the next step.
•Step 1: The search starts by looking for an exact match for the resource bundle with the full name.
•Step 2: The last component (the part separated by _) is dropped and the search is repeated with the resulting shorter name. This process is repeated till the last locale modifier is left.
•Step 3: The search is restarted using the full name of the bundle for the default locale.
•Step 4: Search for the resource bundle with just the name of the bundle.
•Step 5: The search fails, throwing a MissingBundleException.
The search starts with the given locale details and if not found, proceeds with checking for default locale, as in:
BundleName + "_" + language + "_" + country + "_" + variant
BundleName + "_" + language + "_" + country
BundleName + "_" + language
BundleName + "_" + defaultLanguage + "_" + defaultCountry
BundleName + "_" + defaultLanguage
Consider an example to find out how the matching resource bundle is found, and it will become clear to you. Assume that you have the following five entries in the search path, and your default locale is US English.
|
|
ResourceBundle.properties |
-- Global bundle |
ResourceBundle_ar.properties |
-- Arabic language bundle |
ResourceBundle_en.properties |
-- English bundle (assuming en_US is the default locale) |
ResourceBundle_it.properties |
-- Italian language bundle |
ResourceBundle_it_IT_Rome.properties |
-- Italian (Italy, Rome, Vatican) bundle |
373

Chapter 12 ■ Localization
The getBundle() method takes a ResourceBundle.Control object as an additional parameter.
By extending this ResourceBundle.Control class and passing the instance of that extended class to the getBundle() method, you can change the default resource bundle search process or read from non-standard resource bundle formats (such as XML files).
So, you’ll extend this ResourceBundle.Control class and override the getCandidateLocales() method.
This is to programmatically list the candidate locales and finally display the matching locale. The program is given in Listing 12-7.
Listing 12-7. CandidateLocales.java
import java.util.*;
//Extend ResourceBundle.Control and override getCandidateLocales method
//to get the list of candidate locales that Java searches for
class TalkativeResourceBundleControl extends ResourceBundle.Control {
//override the default getCandidateLocales method to print
//the candidate locales first
public List < Locale > getCandidateLocales(String baseName, Locale locale) { List < Locale > candidateLocales = super.getCandidateLocales(baseName, locale); System.out.printf("Candidate locales for base bundle name %s and locale %s %n", baseName, locale.getDisplayName());
for(Locale candidateLocale : candidateLocales) { System.out.println(candidateLocale);
}
return candidateLocales;
}
}
// Use a helper method loadResourceBundle to load a bundle given the bundle name and locale class CandidateLocales {
public static void loadResourceBundle(String resourceBundleName, Locale locale) {
//Pass an instance of TalkativeResourceBundleControl
//to print candidate locales
ResourceBundle resourceBundle = ResourceBundle.getBundle(resourceBundleName, locale, new TalkativeResourceBundleControl());
String rbLocaleName = resourceBundle.getLocale().toString();
//if the resource bundle locale name is empty,
//it means default property file if(rbLocaleName.equals("")) {
System.out.println("Loaded the default property file with name: " + resourceBundleName);
} else {
System.out.println("Loaded the resource bundle for the locale: " + resourceBundleName + "." + rbLocaleName);
}
}
374
Chapter 12 ■ Localization
public static void main(String[] args) {
// trace how ResourceBundle_it_IT_Rome.properties is resolved loadResourceBundle("ResourceBundle", new Locale("it", "IT", "Rome"));
}
}
It prints the following:
Candidate locales for base bundle name ResourceBundle and locale Italian (Italy, Rome) it_IT_Rome
it_IT it
Loaded the resource bundle for the locale: ResourceBundle.it_IT_Rome
Now, before trying with other locales, consider how the program works. To trace how Java resolves the resource bundle to be finally loaded, you need to get the list of candidate locales. With the ResourceBundle.getBundle() method, you can pass an additional argument that is an instance of the ResourceBundle.Control class. For this reason, you define the TalkativeResourceBundleControl class.
The TalkativeResourceBundleControl class extends the ResourceBundle.Control class and overrides the getCandidateLocales() method. This getCandidateLocales() method returns a List < Locale > instance that contains the list of candidate locales for the given locale. You invoke super.getCandidateLocales() and traverse the resulting List < Locale > object to print the candidate locales so that you can examine the output
later. From this overridden getCandidateLocales() method, you simply return this List < Locale > object. So, the behavior of TalkativeResourceBundleControl is identical to ResourceBundle.Control except that the overridden getCandidateLocales() in TalkativeResourceBundleControl prints the candidate locales.
The CandidateLocales class makes use of the TalkativeResourceBundleControl. It has a helper method called loadResourceBundle() that takes the resource bundle name and the name of the locale as arguments. This method simply passes these argument values to the ResourceBundle.getBundle() method; additionally it instantiates TalkativeResourceBundleControl and passes that object as the third argument to this method. The getBundle() method returns a ResourceBundle object. If the locale of the ResourceBundle.getLocale() name is empty, it means Java has loaded the global resource bundle. (Remember that the global resource bundle for that bundle name does not have any associated locale details.) If the name of the locale is not empty, it means Java has resolved to that particular locale.
Now, consider the code in the main() method. It calls loadResourceBundle() for the locale it_IT_Rome. There are three candidate locales and of that it correctly loaded the matching property file for the locale it_IT_Rome. So you know that it loaded the property file ResourceBundle_it_IT_Rome.properties correctly.
To continue this experiment, let’s change the code inside the main() method of Listing 12-7 to this code:
loadResourceBundle("ResourceBundle", new Locale("fr", "CA", ""));
Now the program prints the following:
Candidate locales for base bundle name ResourceBundle and locale French (Canada) fr_CA
fr
Candidate locales for base bundle name ResourceBundle and locale English (United States) en_US
en
Loaded the resource bundle for the locale: ResourceBundle.en
375