Here’re some review notes before my Oracle Certified Professional Java SE 8 exam. They’re highly inspired by the following books:
They are excellent resources for learning Java, which I highly recommend. In particular, the OCP Java SE 7 Programmer II Certification Guide is really the best resource that you can have for learning Java and pass the certification!
Java Class Design
Java access modifiers:
- Access modifiers defined by Java are
public
,protected
, andprivate
. In the absence of an explicit access modifier, a member is defined with the default access level. - The members of a class defined using the
protected
access modifier are accessible to classes and interfaces defined in the same package and to all derived classes, even if they’re defined in separate packages. - A top-level class, interface, or enum can only be defined using the
public
or default access. They cannot be defined usingprotected
orprivate
access. - There are two kinds of class declarations: normal class declarations and enum declarations.
-
A class declaration may include class modifiers.
ClassModifiers: ClassModifier ClassModifiers ClassModifier ClassModifier: one of Annotation public protected private abstract static final strictfp
The access modifiers
protected
andprivate
(§6.6) pertain only to member classes within a directly enclosing class or enum declaration (§8.5). The modifierstatic
pertains only to member classes (§8.5.1), not to top level or local or anonymous classes. - If two or more (distinct) class modifiers appear in a class declaration, then it is customary, though not required, that they appear in the order consistent with that shown above in the production for ClassModifier.
Overloaded methods and constructors:
- Overloaded methods are methods with the same name but different method parameter lists.
- Overloaded methods are bound at compile time. Unlike overridden methods they’re not bound at runtime.
- A call to correctly overloaded methods can also fail compilation if the compiler is unable to resolve the call to an overloaded method.
- Overloaded methods might define a different return type or access or non-access modifier, but they cannot be defined with only a change in their return types or access or non-access modifiers.[1.1]
- Overloaded constructors must be defined using different argument lists.
- Overloaded constructors cannot be defined by just a change in the access modifiers.
- A constructor can call another overloaded constructor by using the keyword
this
. - A constructor cannot invoke another constructor by using its class’s name.
- If present, the call to another constructor must be the first statement in a constructor.
Method overriding and virtual method invocation:
- Whenever you intend to override methods in a derived class, use the
annotation
@Override
. It will warn you if a method cannot be overridden or if you’re actually overloading a method rather than overriding it. - Overridden methods can define the same or covariant return types. [1.2]
- A derived class cannot override a base class method to make it less accessible.
- Static methods cannot be overridden. They’re not polymorphic and they are bound at compile time.
- The
instanceof
operator must be followed by the name of an interface, class, or enum. - In a derived class, a static method with the same signature as that of a static method in its base class hides the base class method.
- Constructor cannot be overridden because a base class constructor is not inherited by a derived class.
- A method that can be overridden by a derived class is call a virtual method.
[1.1] Example:
Compile failure:
$ javac A.java
A.java:7: error: age() in A cannot implement age() in B
class C extends A implements B {
^
overriding method is static
1 error
[1.2] Example: Dog extends animal, and the return type of method
getChild()
is covariant.
Compilation is successful:
Java packages:
- The package and subpackages names are separated using a period.
- You cannot import classes from a subpackage by using the wildcard character,
an asterisk (
*
), in theimport
statement. - A class from the default package cannot be used in any named package, regardless of whether it’s defined within the same directory or not.
- An
import
statement cannot be placed before a package statement in a class. Any attempt to do so will cause the compilation of the class to fail.
Sample questions correction:
Question 1-4: Given that classes Class1
and Class2
exist in separate
packages and source code files, examine the code and select the correct options.
Class 2 won’t compile because it cannot access the name
variable on line 3.
The base class Class1
and derived class Class2
are in separate packages, so
you cannot access protected members of the base class by using reference
variables.
Question ME-75: What is the result of the following code? (Choose the best option.)
The compilation will fail, becuase instance initializer of a class must complete
normally to enable the class to compile. The code in Metal
’s instance
initializer throws a RuntimeException
, which is not handled. So compilation of
class Metal
fails with the follwing message:
Metal.java:2: error: initializer must be able to complete normally
{
^
1 error
Advanced Class Design
Abstract classes:
- An abstract class must not necessarily define abstract methods. But if it defines even one abstract method, it must be marked as an abstract class.
- An abstract class cannot be instantiated.
- An abstract class forces all its non-abstract derived classes to implement the incomplete functionality in their own unique manner.
- If an abstract class is extended by another abstract class, the derived abstract class might not implement the abstract methods of its base class.
- If an abstract class is extended by a concrete class, the derived class must implement all the abstract methods of its base class, or it won’t compile.
- A derived class must call its super class’s constructor (implictly or explicitly), irrespective of whether the super class or derived class is an abstract class or concrete class.
- An abstract class cannot define abstract static methods. Because static methods belong to a class and not to an object, they aren’t inherited. A method that cannot be inherited cannot be implemented. Hence this combination is invalid.
- A static variable defined in a base class is accessible to its derived class. Even though derived class does not define the static variable, it can access the static variable defined in its base class.
Non-access modifier—static:
- Static members are also known as class fields or class methods because they are said to belong to their class, and not to any instance of that class.
- A static variable and method cannot access non-static variables and methods of a class. But the reverse works: non-static variables and methods can access static variables and methods.
- When you instantiate a derived class, the derived class instantiates its base class. The static initializers execute when a class is loaded in memory, so the order of execution of static and instance initializer blocks is as follow: base class static init-block, derived class static init-block, base class instance init-block, derived class instance init-block.
Non-access modifier—final:
- An instance final variable can be initialized either with its declaration in the initilizer block or in the class’s constructor.
- A static final variable can be initialized either with its declaration or in the class’s static initializer block.
- If you don’t initialize a final local variable in a method, the compiler won’t complain, as long as you don’t use it.
- The Java compiler considers initialization of a final variable complete only
if the initialization code will execute in all conditions. If the Java
compiler cannot be sure of execution of code that assigns a value to your
final variabl, it will complain (code won’t compile) that you haven’t
initialized a final variable. If an
if
construct uses constant values, the Java compiler can predetermine whether thethen
orelse
blocks will execute. In this case, it can predetermine whether these blocks of code will execute to initialize a final variable. - The initialization of a final veriable defined in an abstract base class must complete in the class itself. It connot be deferred to its derived class.
Enumerated types:
- All enums extend the abstract class
java.lang.Enum
, defined in Java API. - Because a class can extend from only base class, an attempt to make your enum extend any other class will fail its compilation.
- The enum constants are implicit static members.
- The creation of enum constants happens in a static initializer block, before
the execution of the rest of the code defined in the
static
block. - You can define multiple constructors in your enums.
- Enum constants can define new methods, but these methods cannot be called on the enum constant.
- All the constants of an enum type can be obtained by calling the implicit
public static T[] values()
method of that type. This array contains the enumerated types in natural order. (Probably defined by the private memberordinal
ofjava.lang.Enum
) - You can define an enum as a top-level enum or within another class or interface.[2.1]
- You cannot define an enum local to a method.[2.2]
[2.1],[2.2] Example:
Static nested class:
- This class is not associated with any object of its outer class. Nested within its outer class, it’s accessed like any other static member of a class—by using the class name of the outer class.
- The accessibility of the nested static class depends on its access modifier. For example, a private static nested class cannot be accessed outside its class.
Inner class:
- An object of an inner class shares a special bound with its outer class and cannot exist without its instance.
- An inner class cannot define static methods and non-final static variables.
- You can create an object of an inner class within an outer class[4] or outside an outer class[5].
[4] Inside the outer class, an inner class is instantiated like:
[5] Outside the outer class, an inner class is instantiated like:
Here’s a complete example:
Compile and execute:
$ javac Outer.java App.java
$ java App
Outside: Inner
Outer: Inner
Anonymous inner classes:
- An anonymous inner class is created when you combine object instance creation with inheriting a class or implementing an interface.
-
The following line creates an anonymous inner class that extends
Object
and assigns it to a reference variable of typeObject
:Object o = new Object(){};
- When an anonymous inner class is defined within a method, it can access only the final variables of the method in which it’s defined. This is to prevent reassignment of the variable values by the inner class.
- Since Java 8, certain variables that are not declared
final
are instead considered effectively final. See JLS 4.12.4. final Variables for more detail.
Method local inner classes:
- Method local inner classes are defined within a static or instance method of a class.
- A method local inner class can define its own constructors, variables, and
methods by using any of the four access levels—
public
,protected
, default, andprivate
. - A method local inner class can access all variables and methods of its outer class, including its private members and the ones that it inherits from its base classes. It can only access the final local variables of the method in which it’s defined.
Sample questions correction:
Question 2-13: What is the output of the following code?
Here’s part of the decompiled code. Note that the contents of the default constructor and instance initializer blocks are added to the new constructor, implicitly defined during the compilation process.
final class BasicColor extends Enum
{
private BasicColor(String s, int i)
{
super(s, i);
System.out.println("Init block");
System.out.println("Constructor");
}
...
static
{
RED = new BasicColor("RED", 0);
$VALUES = (new BasicColor[] {
RED
});
System.out.println("Static init");
}
}
Thus the answer is:
Init block
Constructor
Static init
Object-Oriented Design Principles
Interfaces
- The methods of an interface are implicitly abstract and public.
- The vairables of an interface are implicitly public, static, and final.
- Because the methods in an interface are implicitly public, if you try to assign a weaker access to the implemented method in a class, it won’t compile.
Generics and Collections
Creating generic entities:
- Java’s naming conventions limit the use of single uppercase letters for type parameters. Though not recommended, using any valid identifier name for type parameters is acceptable code.
- When a non-generic class extends a generic class, the derived class doesn’t define any type parameters but passes arguments to all type parameters of its generic base class.
- A method’s type parameter list is placed just after its access and non-access modifiers and before its return type. Because a type parameter could be used to define the return type, it should be known before the return type is used.
- For a bounded type parameter, the bound can be a class, an interface, or an enum.
- For a bounded type parameter, the bound cannot be primitive types or array.
- All cases use the keyword
extends
to specify the bound, even if the bound is an interface. - Use method
Class#newInstance()
can create a new instance of the class represented by thisClass
object.[4.1]
[4.1] Example:
Compile and execution:
$ javac App.java
$ java App
Hi, Tom
String Processing
Regular expressions:
- Regular expressions, or regex, are used to define patterns of datat to be found in a stream.
- Character classes aren’t classes defined in the Java API. The term refers to
a set of characters that you can enclose within square brackets
[]
. - You can create a custom character class by enclosing a set of characters
within square brackets
[]
.[fdn]
can be used to find an exact match of f, d, or n.[^fdn]
can be used to find a character that does not match either f, d, or n.[a-cA-C]
can be used to find a exact match of either a, b, c, A, B, or C.
- Use predefined character classes:
- A dot
.
matches any character \d
matches any digit:[0-9]
\D
matches any non-digit:[^0-9]
\s
matches a whitespace character: spaces,\t
tab,\n
new line,\x0B
end of line,\f
form feed,\r
carriage.\S
matches a non-whitespace character:[^\s]
\w
matches a word character:[a-zA-Z_0-9]
\W
matches a non-word character:[^\w]
- A dot
- Boundary metchers:
\b
indicates a word boundary\B
indicates a non-word boundary^
indicates the beginning of a line$
indicates the end of a line
- Specify the number of occurrences of a pattern to match in a target value by
using quantifiers:
X?
matches X, once or not at allX*
matches X, zero or more timesX+
matches X, one or more timesX{min,max}
matches X, which the specified range
- Regex in Java supports Unicode, as it matches against the
CharSequence
objects. - Class
Pattern
is a compiled representation of a regular expression. Instantiate aPattern
by using its factory methodcompile()
. [5.1] - Class
Matcher
is referred to as an engine that scans a targetCharSequence
for a metching regex pattern. You can create aMatcher
object by calling the instance methodPattern#matcher(CharSequence)
.[5.2]
[5.1],[5.2] Example:
Then compile and execute:
$ javac Regex.java
$ java Regex
2018-01-06: true
Search, parse, and build strings:
You can search strings for exact matches of characters or string, at the
beginning of a string, or starting at a specified position, using String
class’s overloaded methods indexOf
.
indexOf
increases position numberslastIndexOf
decreases position numbersindexOf
andlastIndexOf
don’t throw a compilation error or runtime exception if the search position is negative or greater than the length of this string. If no match is found, they return -1.contains
searches for an exact match in this string. Becuasecontains
accepts a method parameter of interfaceCharSequence
, you can pass to it bothString
andStringBuilder
object.substring
defines 2 overloaded versions, which accept one or two parameters for the start and end positions.[5.3] WhilesubSequence()
defines only one variant, the one that accepts two int method parameters for the start and end positions.[5.4]subSequence
is defined in interfaceCharSequence
, it returns an object of typeCharSequence
.subSequence
andsubstring
do not include the character at the end position in the resultString
.- The combination of the
replace
,replaceAll
, andreplaceFirst
overloaded methods can be confusing on the exam. Be aware ofStringBuilder
, which implementsCharSequence
:replace(char oldChar, char newChar)
replace(CharSequence oldVal, CharSequence newVal)
replaceAll(String regex, String replacement)
replaceFirst(String regex, String replacement)
Scanner
can be used to parse and tokenize strings.- If no delimiter specified, a pattern that matches whitespace is used by default.
- Use customized pattern by calling
userDelimiter
with a regex. next()
returns a string.nextXXX()
returns a primitive typeXXX
.
[5.3],[5.4] Example:
Compile and execute:
$ javac Process.java
$ java Process xPath
s: xPath
s[1:]: Path
s[1:2]: P
s[1:2]: P
Formatting strings:
-
The format specifier takes the following form:
%[argument_index$][flags][width][.precision]conversion
Width specifier indicates the minimum number of characters to be written to the output.
- A format specification must start with a
%
sign and end with a conversion character:b
for booleanc
for chard
for int, byte, short, and longf
for float, and doubles
for string
- If the number of arguments exceeds the required count, the extra variables are quietly ignored by the compiler and JVM.
- If the number of arguments falls short, the JVM throws a runtime exception.
- The
-
indicates to left-justify this arguments; you must specify width as well. Number flags[5.5] (only applicable for numbers, conversion charsd
andf
) are as follows:- The
+
indicates to include a sign (+
,-
) with this argument. 0
indicates to pad this arguments with zeros. Must pecify width as well.,
indicates to use local-specific grouping separators, e.g. the comma in 123,456.(
is used to enclose negative numbers in parentheses.
- The
- The floags
+
,0
,(
, and,
can be specified only with the numeric specifiers%d
and%f
. Using it with other specifier will raise a runtime exception. - Format specifier
%b
null
-> false- Boolean, boolean -> itself
- Else -> true
- Format specifier
%c
- Accepted inputs: char, byte, short, int, and their related non-primitive types. The result is a unicode character.
- Refused inputs: boolean, long, float, and their related non-primitive
types. An
IllegalFormatConversionException
will be thrown.
- Format specifier
%f
- Accepted inputs: float, double, and their related non-primitive types.
- By default,
%f
prints six digits after the decimal.
- Format specifier
%d
- Accepted inputs: byte, short, int, long and their related non-primitive types.
- Refused inputs: float, double and their related non-primitive types.
- Format specifier
%s
%s
outputs the value for a primitvie variable. It callestoString
behind the screen, and outputs “null” for null values.- It accepts all types.
[5.5] Example:
Compile and execute:
$ javac NumberFlags.java
$ java NumberFlags
+1000
01000
1,000
(1000)
Exceptions and Assertions
Using the throw statement and the throws clause:
- When you use a method that throws a checked exception, you must either
enclose the code within a
try
block or declare it to be rethrown in the calling method’s declaration. This is also known as the handle-or-declare rule. - A method can throw a runtime exception or error irrespective of whether its
name is included in the
throws
clause. - A method can throw a subclass of the exception mentioned in its
throws
clause but not a superclass. - A method can declare to throw any type of exception, checked or unchecked, even if it doesn’t.
- But a
try
block cannot define acatch
block for a checked exception (other thanException
) if thetry
block doesn’t throw that checked exception or use a method that declares to throw that checked exception.
Custom exceptions:
- Custom exceptions help you restrict the escalation of implementation-specific
exceptions to higher layers. For example,
SQLException
thrown by data access code can be wrapped within a custom exception and rethrown.
Overriding methods that throw exceptions:
- If a method in the base class doesn’t declare to throw any checked exception, the overriding method in the derived class cannot throw any checked exception.
- If a method in the base class declares to throw a checked exception, the overriding method in the derived class can choose not to declare to throw any checked exception.
- Subclass cannot override a method in the base class, if it declares to throw a more generic checked exception.
- Moethod overriding rules apply only to checked exceptions. They don’t apply to runtime exceptions or errors.
try statement with multi-catch and finally clauses:
- The exceptions that you catch in a multi-
catch
block cannot share an inheritance relationship. If you try to do so, your code won’t compile. - Declare more specific exceptions at the top, more general ones at the bottom.
Auto-close resources with try-with-resources statement:
- A try-with-resources block might not be followed by a
catch
or afinally
block. This is unlike a regulartry
block, which must be followed by either acatch
or afinally
block. - The variables used to refer to resources are implicitly final variables. You must declare and initialize resources in the try-with-resources statement.
- Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources. Such an exception is suppressed if an exception was thrown previously by an initializer, the try block, or the closing of a resource.
Assertions:
An assertion is an assert statement containing a boolean expression. An
assertion is either enabled or disabled. If the assertion is enabled,
execution of the assertion causes evaluation of the boolean expression and an
error is reported if the expression evaluates to false
. If the assertion is
disabled, execution of the assertion has no effect whatsoever.
AssertStatement:
assert Expression1 ;
assert Expression1 : Expression2 ;
It is a compile-time error if Expression1 does not have type boolean
or
Boolean
. In the second form of the assert
statement, it is a compile-time
error if Expression2 is void
.
- The second form, when the boolean expression evaluates to
false
, the JRE creates an object ofAssertError
by passing the value of the second expression toAssertionError
’s constructor. -
From the Javadoc of
AssertionError
: the seven one-argument public constructors provided by this class ensure that the assertion error returned by the invoation:new AssertionError(expression)
has as its detail message the string conversion of expression, regardless of the type of expression. (JLS §15.18.1.1)
- Assertions can be enabled or disabled at the launche of a program.[6.1]
- Use the command-line option
-ea
or-enableassertions
to enable assertions - Use the command-line option
-da
or-disableassertions
to disable assertions - A generalized
-da
switch (no assertions enabled) corresponds to the default JRE behavior.
[6.1] Example:
Compile and execute:
$ javac App.java
$ java App
Finished.
$ java -da App
Finished.
$ java -ea App
Exception in thread "main" java.lang.AssertionError: You should be happy :)
at App.main(App.java:5)
Java File IO
RandomAccessFile#readLine()
successively reads bytes from the file, starting at the current file pointer, until it reaches a line terminator or the end of the file.FileInputStream
acceptsFile
as constructor input parameter.FileInputStream
acceptsString
as constructor input parameter.BufferedInputStream
acceptsInputStream
as constructor input parameter.- Concatenating int and
StringBuilder
fails to compile. E.g.String s = 1 + sb;
. Although using the additive operator for concatenation is implemented by invoking the append method on theStringBuilder
orStringBuffer
class, this operator is not supported for theStringBuilder
orStringBuffer
operands. InputStream#read()
returns the next byte of data, or-1
if the end of the stream is reached.InputStream#skip()
skips over and discards n bytes of data from this input stream.
Building Database Applications with JDBC
JDBC 4.0 and its later version support automatic loading and registration of all
JDBC drivers accessible via an application’s classpath. For all earlier versions
of JDBC, you must manually load the JDBC drivers using Class.forName()
, before
you can access the driver.
JDBC transactions:
- When connection’s auto-commit mode is changed during a transaction, the transaction is committed. So when auto-commit is enabled, all the “pending” changes in the current transaction are commited.
Threads
Create and use threads:
- Implementation of Java threads is JVM-specific.
- To create your own thread objects using class
Thread
, you must extend it and override its methodrun()
. - When you call
start()
on aThread
instance, it creates a new thread of execution. When a new thread of execution starts, it will execute the code defined in the thread instance’s methodrun()
. Methodstart()
will trigger the creation of a new thread of execution, allocating resources to it. - When you create a thread class by extending class
Thread
, you lose the fexibility of inheriting any other class. - When you implement the
Runnable
interface, you must implement its methodrun()
. - The
Thread
constructor accepts aRunnable
object. AThread
instance stores a reference to aRunnable
object and uses it when you start its execution (by callingstart()
). - You cannot guarantee that a thread with a higher priority will always execute before a thread with a lower priority.
Thread lifecycle:
- Thread states: new, runnable, wait, timed, timed-waiting, blocked, or terminated.
- Calling
start()
on a new thread instance implicitly calls its methodrun()
, which transitions its state from “new” to “ready”. - A running thread might enter the blocked state when it’s waiting for other system resources like network connections or to acquire an object lock to execute a synchronized method or code block. Depending on whether the thread is able to acquire the monitor lock or resources, it returns back to the ready state.
Methods of class Thread:
- Calling
run()
on aThread
instance doesn’t start a new thread of execution. Therun()
continues to execute in the same thread. - Method
yield()
makes the currently executing thread pause its execution and give up its current use of the processor. But it only acts as a hint to the scheduler. The scheduler might also ignore it. - A thread that’s suspended due to a call to
sleep()
doesn’t lose ownership of any monitors.
Protect shared data:
- A simple statement like incrementing a variable value might involve multiple steps like loading of the variable value from memory to registers (working space), incrementing the value, and reloading the new value in memory.
- When multiple threads execute this seemingly atomic statement, they might interleave, resulting in incorrect variable values.
- Thread safety is about safe-guarding your shared data that might be accessible to multiple threads.
- To execute synchronized statements, a thread must acquire a lock on an object monitor. For instance methods an implicit lock is acquired on the object on which it’s called. For synchronized statements, you can specify an object to acquire a lock on.
- For instance synchronized methods, a thread locks the instance’s monitor
- For static synchronized methods, a thread locks the
Class
object’s monitor.[10.1] - A thread releases the lock on the object monitor once it exits the synchronized statement block due to successful completion or an exception.
- Immutable objects are thread-safe, because they cannot be modified.
- Using
valatile
ensures objects are accessed from the main memory, as opposed to storing its copy in the thread’s cache memory. It prevents data consistency problem caused by local copy.
[10.1] Example:
Identify and fix code in a multi-threaded environment:
- Local variables, method params, and exception handler params are always safe.
- Class and instance variables might not always be safe.
- Use
wait()
,notify()
, andnotifyAll()
for inter-thread notification. -
To call
wait()
ornotify()
a thread must own the object’s monitor lock. So calls to these methods should be placed within synchronized methods or blocks or else anIllegalMonitorStateException
will be thrown by the JVM. - A thread can starve to be scheduled when it’s waiting to acquire a lock on an object monitor that has been acquired by another thread that usually takes long to execute and is invoked frequently.
- Java language uses “happens-before” relationship, which is when one task is guaranteed to happen before another.
- The execution of
start()
happens-before any action in a thread is started. - When code is defined in a sequence, step 1 happens-before step 2.
- Unlocking of an object monitor heppens-before any other thread acquires a lock on it.
- A write to a volatile field happens-before every subsequent read of that field.
- All actions in a thread happens-before any other thread returns from a join on that thread.
Miscellaneous:
- Livelock occurs when two or more threads are so busy responding to each other that they are unable to complete their tasks. Technically, these threads are running and not waiting, but the locking mechanism consumes their execution.
- Starvation occurs when one or more threads access a shared resource so frequently that other threads are unable to gain needed access. Those threads with access to the shared resource are not waiting.
- 3 methods affect the frequency and/or duration of a running thread. They’re
setDaemon
,setPriority
, andyield
. - The
setPriority
method indicates the relative likelihood and frequency that a thread will be given a time slice to execute. Possible values: max, norm, or min. - The
yield
method will cause the current thread to give up its time slice, so that another thread can execute. - If true is specified for
setDaemon
, then the JVM may exit before the thread terminates. The JVM exits only when all non-daemon threads terminate. java.util.ConcurrentModificationException
can be thrown by threads when modifyingArrayList
which is not thread-safe. Use the thread-safe variant ofArrayList
:CopyOnWriteArrayList
is a good alternative.ThreadLocalRandom
can be used to create random numbers in a multi-threaded application with the least amount of contention and best performance
Concurrency
Locks:
Lock
andReadWriteLock
are interface.ReentrantLock
andReentrantReadWriteLock
are concrete classes.Lock
objects offer multiple advantages over the implicit locking of an object’s monitor. Unlike an implicit lock, a thread can use explicit lock objects to wait to acquire a lock until a time duration elapses.- Method
lock()
acquires a lock on aLock
object. If the lock is not available, it waits until the lock can be acquired. - Call
unlock
on aLock
object to release its lock when you no longer need it. - The
ReadWriteLock
interface doesn’t extendLock
or any other interface.
Parallel fork/join framework:
- Method
compute()
determines whether the task is small enough to be executed or if it needs to be divided into multiple tasks. - If the task needs to be split, a new
RecursiveAction
orRecursiveTask
object is created, callingfork
on it. - Calling
join
on these tasks returns their result.
Localization
Internationalization and localization:
- Class
Locale
does not itself provide any moethod to format the numbers, dates or currencies. You useLocale
objects to pass locale-specific information to other classes likeNumberFormat
orDateFormat
to format data. - You can create and access objects of class
Locale
by using constructors, methods, constants, and builder. -
Overloaded constructors of
Locale
Locale(String language) Locale(String language, String country) Locale(String language, String country, String variant)
- Variant is a vendor- or browser-specific code, such as WIN for Windows and MAC for Macintosh.
- Language is the most important parameter that you pass to a
Locale
object. - You can access the current value of a JVM’s default locale by using method
Locale#getDefault
.
Resource bundles:
-
An abstract class
ResourceBundle
represents locale-specific resources.ResourceBundle r = ResourceBundle.getBundle("i18n.foo", Locale.FRANCE);
- You can call methods
getString()
,getObject()
,keySet()
,getKeys()
, andgetStringArray()
from classResourceBundle
to access its keys and values. -
The order in which Java searches for a matching:
bundle_localeLang_localeCountry_localeVariant bundle_localeLang_localeCountry bundle_localeLang bundle_defaultLang_defaultCountry_defaultVariant bundle_defaultLang_defaultCountry bundle_defaultLang bundle
- If there’s no matching resource bundle for the target language, neither a
default resource bundle, then the application throws a
MissingResourceException
at runtime.
Formatting dates, numbers, and currencies for locales:
-
Format currency
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(Locale.FRANCE); assertThat(numberFormat.format(10000L)).isEqualTo("10 000,00 €");
-
Format date using
DateFormat
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US); assertThat(dateFormat.format(date)).isEqualTo("Nov 26, 2017");
-
Format date using
SimpleDateFormat
SimpleDateFormat iso = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ"); assertThat(iso.format(date)).isEqualTo("2017-11-26T10:15:49.000+0000");
-
Create a
Calendar
:private static Calendar newCalendar() { Calendar calendar = Calendar.getInstance(Locale.US); calendar.set(2017, Calendar.NOVEMBER, 26, 10, 15, 49); calendar.set(Calendar.MILLISECOND, 0); calendar.setTimeZone(TimeZone.getTimeZone("UTC")); return calendar; }
Frequently Asked Java API
Method | Return Type | Checked Exception |
---|---|---|
Thread#sleep() |
void | InterruptedException |
Runnable#run() |
void | - |
Callable#call() |
V | Exception |
RecursiveAction#compute() |
void | - |
RecursiveTask#compute() |
V | - |
Predicate#test(T) |
boolean | - |
Consumer#accept(T) |
void | - |
Supplier#get() |
T | - |
Function#apply(T) |
R | - |
Tricky points
Some tricky points that can happen in OCP exam.
- The method name can be mis-spelled. For example,
hashcode()
is not the correct method for providing a hash-code in Java. The correct one is camel-case:hashCode()
. - The default locale defined in JVM might not be
Locale.US
. - Be careful whether the method output is assigned to a variable, e.g.
String#replaceAll(String, String)
returns another string.