Showing posts with label effective java. Show all posts
Showing posts with label effective java. Show all posts

Monday, October 14, 2013

Notes of “Effective Java” (Chapter 7-11)

Item 37: Use marker interfaces to define types
Marker interface contains no method declarations, which indicates some property or features. The typical marker interface is Serialize interface.
Item 38: Check parameters for validity
Check and restrict the parameters of functions.
  • Throw Exception
  • Assert
Item 39: Make defensive copies when needed
In general, if a class has mutable components that it gets from or returns to its clients, the class must defensively copy these components.
Defensive copy usually implemented by:
  • clone() method
  • copy constructor
  • static factory
This is not mandatory. If the class trusts the clients, then defensive copy could be replaced by documentation explanation to save the cost.

Item 40: Design method signatures carefully
Avoid long parameter lists.  Divide them to several methods or use helper method and helper class.
Favor interfaces over classes.
Prefer two-element enum types to boolean parameters for clearness and extendability.
Item 41: Use overloading judiciously
Selection among overloaded methods is static (at the compile time), while selection among overridden methods is dynamic.
Refrain using of overloading methods with same number of parameters.
If you can not avoid that, try avoiding parameters that can be passed to different overloadings by casts.
Item 42: Use varargs judiciously
Do not use varargs unless you really need it and benefit from it.
Varargs is expensive in resources.
Arrays.asList() is tricky. It returns List<Integer> when the argument is Integer[] and returns List<int[]> when the argument is int[].
Item 43: Return empty arrays or collections, not nulls
Returning null requires extra judgement in the client side.
Use new Object1[0] for arrays and emptyList(), emptySet() and emptyMap() for containers.
Item 44: Write doc comments for all exposed API elements
@param tag for the parameters. @return for return values. @throws for exception may throw.
Care the HTML metacharacters in doc comments.
Write succinct and nice comment as the summary description in the beginning.
For methods and constructors: verb phrase .
  • Returns the number of elements in this collection.
For classes, interfaces, and fields: noun phrase.
  • A task that can be scheduled for one-time or repeated execution by a Timer.
Document generic types and constants.
Item 45: Minimize the scope of local variables
Minimize the scope of a local variable by declaring it where it is first used.
Prefer  for loops to  while loops.
Item 46: Prefer for-each loops to traditional for loops
Use the for each loops to iterate the arrays.
Exception:
  1. you need to remove the elements.
  2. you need to change the value of elements.
  3. special control for the pace of iteration.
Item 47: Know and use the libraries
Be familiar with the contents of java.lang, java.util, and, to a lesser extent, java.io.
Item 48: Avoid  float and double  if exact answers are required
Use the BigDecimal or int or long instead.
int for number with less than 9 digits and long for 19 digits.
Item 49: Prefer primitive types to boxed primitives
“==” operation to mixture of primitive and boxed primitive compares the reference identity but not value.
Use autoboxing carefully.
Item 50: Avoid strings where other types are more appropriate
Do not use string type in everywhere.
Item 51: Beware the performance of string concatenation
Use append() of StringBuilder instead.
Item 52: Refer to objects by their interfaces
Using interface as parameter type make the program more flexible.
List<Subscriber> subscribers = new Vector<Subscriber>();
List<Subscriber> subscribers = new ArrayList<Subscriber>();
Item 53: Prefer interfaces to reflection
Reflection loses all information of complile-time check.
Reflection is only used at design time.
When using the class unknown at compile time, try to only instantiate them by reflection. Access fields and call methods using interfaces or superclasses.
Item 54: Use native methods judiciously 
Avoid using native code unless you really need it.
Item 55: Optimize judiciously
Weshould  forget about small efficiencies, say about 97% of the time: prema-ture optimization is the root of all evil.  –Donald E. Knuth.
Write good programs but not fast programs.
Item 56: Adhere to generally accepted naming conventions
Generally, follow The Java Language Specification as conventions.
Package      com.google.inject, org.joda.time.format
Class or Interface     Timer, FutureTask, LinkedHashMap, HttpServlet
Method or Field    remove, ensureCapacity, getCrc
Constant Field      MIN_VALUE, NEGATIVE_INFINITY
Local Variable      i, xref, houseNumber
Type Parameter    T, E, K, V, X, T1, T2
Item 57: Use exceptions only for exceptional conditions
Do not use the exception for control flow, exception is designed for exceptional condition.
Item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
Checked exception is used in recoverable case. For that, it need to provide information or methods to help the caller to recover.
Item 59: Avoid unnecessary use of checked exceptions
Avoid using the checked exception unless:
  • the exception can not avoided by proper use of API.
  • Handling exception brings benefits.
Item 60: Favor the use of standard exceptions
Some commonly used exceptions:
IllegalArgumentException: Non-null parameter value is inappropriate
IllegalStateException: Object state is inappropriate for method invocation
NullPointerException: Parameter value is null where prohibited
IndexOutOfBoundsException: Index parameter value is out of range
ConcurrentModificationException: Concurrent modification of an object has been detected where it is prohibited
UnsupportedOperationException: Object does not support method
Item 61: Throw exceptions appropriate to the abstraction
If it is impossible to prevent the occurring of exception in lower level, propagate it to higher level by catching and rethrowing.
Try to log the exception information if detailed information is needed.
Item 62: Document all exceptions thrown by each method
Document the exceptions by Javadoc @throws tag. Do not “throws” unchecked exceptions.
Item 63: Include failure-capture information in detail messages
Include failure-capture information in checked exceptions. Those information is useful in recovering from failure.
Item 64: Strive for failure atomicity
Any generated exception should leave the object in the same state it was in prior to the method invocation.
Example:
1
2
3
4
5
6
7
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
Do not try to maintain the failure atomicity when throwing errors.
Item 65: Don’t ignore exceptions
Do not use empty catch block to ignore the exception. Throw it outward at least if you do not know how to handle it.
Item 66: Synchronize access to shared mutable data
Synchronization includes two parts: mutual exclusion and visibility. Without synchronization, one thread’s changes might not be visible to other threads.
Do not use  Thread.stop as it is depreciated.
Synchronization has no effect unless both read and write operations are synchronized.
Volatile and Atomic types should be carefully used.
Item 67: Avoid excessive synchronization
Do not call alien methods in synchronized block. Doing this is uncontrollable and may cause exceptions and deadlock.
Use concurrent containers like CopyOnWriteArrayList to separate the data writing and reading. This is particularly useful to the situation in which writing data is happened occasionally.
In a multicore world, the real cost of excessive synchronization is not the CPU time spent obtaining locks; it is the lost opportunities for parallelism and the delays imposed by the need to ensure that every core has a consistent view of memory.
Do not synchronize the class internally unless you have good reason.
Item 68: Prefer executors and tasks to threads
Executor framework separate the task and mechanism of executing. So use executors prior to  Thread.
Using Executors.newFixedThreadPool under heavy loading situations.
Using ScheduledThreadPoolExecutor prior to Timer when multiple timing tasked are required.
Item 68: Prefer executors and tasks to threads
The higher-level utilities in java.util.concurrent fall into three categories:the Executor Framework, concurrent collections; and synchronizers.
Utilities in the concurrent library should be considered first before wait() and notify().
Use  ConcurrentHashMap in preference to  Collections.synchronizedMap  or  Hashtable.
Common synchronizers include CyclicBarrier, CountdownLatch and Semaphore.
Item 70: Document thread safety
The presence of the synchronized modifierin a method declaration is an implementation detail, not a part of its exported API.
To enable safe concurrent use, a class must clearly document what level of thread safety it supports.
levels of thread safety:
  • immutable
  • unconditionally thread-safe
  • conditionally thread-safe
  • not thread-safe
Item 71: Use lazy initialization judiciously
Lazy initialization decreases the cost of initializing a class or creating an instance, at the expense of increasing the cost of accessing the lazily initialized field. It may be worthwhile when only part of instances will be initialized in practice.
Use a synchronized accessor to the getfield method to ensure the concurrency.
Use the lazy initialization holder class idiom for static field.
1
2
3
4
5
// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
static FieldType getField() { return FieldHolder.field; }
Use the double-check idiom for instance field.
1
2
3
4
5
6
7
8
9
10
11
12
13
// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
Item 72: Don’t depend on the thread scheduler
Do not rely on scheduler for correctness of program.
Do not let the thread busy-wait.
Use Thread.sleep(1) instead of Thread.yield() for increasing concurrency.
Item 73: Avoid thread groups
Thread groups are obsolete.
Item 74: Implement  Serializable judiciously
Long term cost of implementing Serializable include:
Decreases the flexi-bility to change a class’s implementation once it has been released.
Increase the likelihood of bug and security holes.
Increase the burden of testing.
Classes designed for inheritance  should rarely implement Serializable, and interfaces should rarely extend it.
Exceptions: Throwable, Component, and HttpServlet, etc.
Item 75: Consider using a custom serialized form
Use the default serialized form only when an object’s phys-ical representation is identical to its logical content.
Disadvantages of inappropriate default serialized form:
  • permanently ties the exported API to the  current internal representation.
  • consume excessive space.
  • consume excessive time (graph traversal).
  • stack overflow.
Provide writeObject and readOb-ject methods implementing this serialized form.  The transient modifier indicates that an instance field is to be omitted from a class’s default serialized form.
Before deciding to make a field nontransient, convince yourself that its value is part of the logical state of the object.
Declare an explicit serial version UID in every serializable class you write, to tackle the version problem.
Item 76: Write  readObject methods defensively
Make defensive copy of fields in readObject() method is necessary like in the constructor.
For classes with object reference fields that must remain private, defensively copy each object in such a field.
Check any invariants and throw an  InvalidObjectException if a check fails.
Do not invoke any overridable methods in the constructor or readObject() method.
Item 77: For instance control, prefer enum types to readResolve
The instance control (e.g, Singleton) is violated without readResolve() method after serialization.
All instance fields with object reference types must be declared transient if using the readResolve() to do the instance control.
Instance control through Enum is preferred to the readResolve().
Item 78: Consider serialization proxies instead of serialized instances
Serialization proxy pattern is implemented based on an inner static class with a single constructor.
Use writeReplace() of enclosing class to write a proxy instance instead of the instance of enclosing class.
Use readResolve() method to return a instance of enclosing class at the time of deserialization, since the method in the inner class is able to call the constructor of enclosing class.
Two limitations of the serialization proxy pattern:
It is not compatible with classes that are extendable by their clients (in that time, the enclosing class has not been initialized).
It is not compatible with some classes whose object graphs contain circularities.
Serialization proxy pattern is more secure, but with higher expense.

Source

Notes of “Effective Java” (Chapter 1-6)

Item 1: Consider static factory methods instead of constructors
advantage:
  1. Customized meaningful names better than constructors.
  2. Associated with class instead of creating new objects.
  3. Able to return subtypes.
For the 2nd advantage, static factory methods form the basis of Service provider Framework including service interface, provider interface, provider registration API and service access API.
Item 2: Consider a builder when faced with many constructor parameters
Compare with telescoping constructors and JavaBean Style.
Builder is set as a static inner class. Builder makes the object initialized immutable.

Item 3: Enforce the singleton property with a private constructor or an enum type
Three ways to implement Singleton patter:
  • Public field
  • Static factory method
  • Enum Singleton
Without Enum, readResovle() function needs to be added to avoid creating spurious instances when doing serialization.
Item 4: Enforce noninstantiability with a private constructor
Some utility classes like java.lang.Math or java.util.Arrays are not designed to be instantiated. For preventing them from instantiation and subclassing, make the constructor to be private.
Item 5: Avoid creating unnecessary objects
Creating new object especially heavy objects is expensive. Therefore, reusing object always increases efficiency.
Example: String appending, Boxed primitives.
Item 6: Eliminate obsolete object references
Although Java has garbage collector, memory leak can still happen. GC reclaims the memory by inspecting the references of objects.
Therefore, we need to null out the obsolete object references to release the unused object memory.
Common memory leak scenarios: Objects constructed inside classes, Cache, Callbacks.
Notice the Weak references and weakHashmap.
Item 7: Avoid finalizers
In summary, don’t use finalizers except as a safety net or to terminate noncritical native resources. In those rare instances where you do use a finalizer, remember to invoke super.finalize.
Explicit termination inside a “try finally” is preferable and reliable.
Item 8: Obey the general contract when overriding equals
Conditions do not need overriding equals():
  1. Instances are distinguished by reference.
  2. Equals() defined in superclass works.
  3. You do not care the equals() function.
Contract when overriding equals():
Reflexive, Symmetric, Transitive, Consistent.
There is no perfect way to override equals() between the subclasses with additional value components and superclasses.
Notice the @Override annotation.
Item 9: Always override hashCode when you override equals
Principle: equal objects according the equals() function must produce the same hashcode.
General recipe for hashCode():
result = 31 * result + c;
  • boolean: (f?1:0).
  •  byte, char, short, or int: (int) f
  • long: (int) (f ^ (f >>> 32))
  • float: Float.floatToIntBits(f)
  • double: Double.doubleToLongBits(f)
  •  null: 0
Note we could lazily initialize the hashCode value.
Item 10: Always override toString
Faciliate the class client user by giving useful information in string.
Item 11: Override clone judiciously
Once one class implements the Cloneable interface and overrides the clone() method, invoking super.clone() will return a field-to-field copy of this class object in which the method is called. If a class contains only primitive fields or references to immutable objects, then it is usually the case that no fields in the object returned by super.clone need to be modified. Otherwise, deep copy is needed.
Be careful to use clone except for arrays. Usually it is better to use copy constructor and copy factory method.
  • public Yum(Yum yum);
  • public static Yum newInstance(Yum yum);
Item 12: Consider implementing Comparable
1
2
3
public interface Comparable<T> {
int compareTo(T t);
}
Classes that depend on comparison include the sorted collections TreeSet and TreeMap, and the utility classes Collections and Arrays, which contain searching and sorting algorithms. General interfaces like Set, Map, and Collection depend on equals() method.
Principle:
If the most significant fields are equal, go on to compare the next-most-significant fields, and so on. If all fields are equal, the objects are equal; return zero.
Item 13: Minimize the accessibility of classes and members
The rule of thumb is simple: make each class or member as inaccessible as possible.
Exported API: public, protected.
If a method overrides a superclass method, it is not permitted to have a lower access level in the subclass than it does in the superclass. This is necessary to ensure that an instance of the subclass is usable anywhere that an instance of the superclass is usable.  A special case of this rule is that if a class implements an interface, all of the class methods that are also present in the interface must be declared public. This is so because all members of an interface are implicitly public.
  • Instance fields should never be public
  • Classes with public mutable fields are not thread-safe
  • Public static final fields should be only used for constants
Item 14: In public classes, use accessor methods, not public fields
Class is package-private or is a private nested class, there is nothing inherently wrong with exposing its data fields.
Item 15: Minimize mutability
  1. Make the immutable class to be final.
  2. Immutable objects are inherently thread-safe; they require no synchroni-zation.
  3. Use companion class such as StringBuilder replacing String for performance.
  4. Static factory is a good way for immutable class.
  5. Classes should be immutable unless there’s a very good reason to make them mutable.
  6. Make every field final unless there is a compelling reason to make it nonfinal.
  7. Don’t provide a public initialization method separate from the constructor or static factory unless there is a compelling reason to do so.
Item 16: Favor composition over inheritance
For most cases, composition is better than inheritance.
The keyword “super” is for calling overrided methods or constructors in superclass. The invocation in super.method() still calls the override methods but not overriden methods.
Item 17: Design and document for inheritance or else prohibit it
  • The class must document or simply prohibit its  self-use of overridable methods.
  • Constructors must not invoke overridable methods.
  • Neither clone() nor readObject() may invoke an overridable method, directly or indirectly, as they behave like constructors.
  • Prohibit subclassing in classes that are not designed and documented to be safely subclassed by “final” or making the constructor “private”.
Item 18: Prefer interfaces to abstract classes
Interface is generally the better way to define a type that permits multiple implementations.
Abstract class and Interface can be combined to generate skeletal implementation, such as AbstractCollection, AbstractSet, AbstractList.
Item 19: Use interfaces only to define types
Interfaces should only used to define type, representing some classes in hierarchy.
Enum and Utility class are more appropriate for defining constants.
Item 20: Prefer class hierarchies to tagged classes
Tagged classes are cluttered with tag fields, and switch statements, messing the encapsulation and  being prone to run-time errors.
Tagged class should be abandoned and replaced by abstract classes.
Item 21: Use function objects to represent strategies
Features like function pointers, delegates, lambda expressions call functions in functions.
Strategy pattern is built on these features typically on function pointers.
Function pointers is not supported in java. However, it can be emulated by a concrete class with only one method, as a “concrete strategy class”.
  • Strategy ==> Interface
  • Concrete strategy ==> Concrete class implementing the interface
Usually the concrete class is used as anonymous class. For class used repeatedly, singleton pattern is applied to the concrete class with one static and final instance.
Item 22: Favor static member classes over nonstatic
Four kinds of nested classes: static member classes, nonstatic member classes, anonymous classes, and local classes.
It is impossible to create an instance of a nonstatic member class without an enclosing instance.
Declare a member class that does not require access to an enclosing instance, always make it to be static.
Three common uses of anonymous classes:
  1. function objects
  2. process objects, such asRunnable, Thread
  3. static factory methods
Item 23: Don’t use raw types in new code
  • Do not use raw type to define variable, as the compiler will not check the type of parameters and it loses the type safety and may generate run-time error.
  • Generics like List<Object> can contain any arbitrary types but still with type safety.
  • Unbounded wildcard types like List<?> is capable to hold one of any type of element with type safety.
  • Generic type information is erased at runtime
Item 24: Eliminate unchecked warnings
Try to eliminate the unchecked warning, including:
  • unchecked cast warnings
  • unchecked method invocation warnings
  • unchecked generic array creation warnings
  • unchecked conversion warnings
Suppress the warning with an @SuppressWarnings(“unchecked”) annotation in narrowest scope if you are sure about the type safety.
Item 25: Prefer lists to arrays
Arrays are covariant and reifiable. Generics are invariant and erased in run-time.
Arrays provide runtime type safety but not compile-time type safety and vice versa for generics.
1
2
3
// Fails at runtime!
Object[] objectArray = new Long[1];
objectArray[0] = "I don't fit in"; // Throws ArrayStoreException
1
2
3
// Won't compile!
List<Object> ol = new ArrayList<Long>(); // Incompatible types
ol.add("I don't fit in");
Generics enforce their type constraints only at compile time and discard (or erase) their element type information at runtime.
it is illegal to create an array of a generic type such as “new List<String>[]” and “new List<E>[]“.
Non-reifiable type is one whose runtime representation contains less information than its compile-time representa-tion.
Casts to arrays of non-reifiable types should be used only under special circumstances. A better solution is to use list.
Item 26: Favor generic types
Generics are safer. Suppress the warning when casting.
1
2
3
4
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
Item 27: Favor generic methods
Generic singleton factory:
1
2
3
4
5
6
7
8
9
10
11
12
// Generic singleton factory pattern
private static UnaryFunction<Object> IDENTITY_FUNCTION =
new UnaryFunction<Object>()
{
public Object apply(Object arg) { return arg; }
};
// IDENTITY_FUNCTION is stateless and its type parameter is
// unbounded so it's safe to share one instance across all types.
@SuppressWarnings("unchecked")
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) IDENTITY_FUNCTION;
}
Recursive type bound is usually used for Comparable<T>.
1
2
3
4
5
public interface Comparable<T>; {
int compareTo(T o);
}
// Using a recursive type bound to express mutual comparability
public static <T extends Comparable<T>> T max(List<T> list) {...}
Item 28: Use bounded wildcards to increase API flexibility
Producer-extends, consumer-super(PECS)
1
2
3
4
5
6
7
8
9
10
// Wildcard type for parameter that serves as an E producer
public void pushAll(Iterable<? extends E> src) {
for (E e : src)
push(e);
}
// Wildcard type for parameter that serves as an E consumer
public void popAll(Collection<? super E> dst) {
while (!isEmpty())
dst.add(pop());
}
Do not use wildcard types as return types. Rather than providing additional flexibility for your users, it would force them to use wildcard types in client code.
Always use Comparable<? super T> in preference to Comparable<T>, since the type may implements the Comparable interface as an subinterface.
If a type parameter appears only once in a method declaration, replace it with a wildcard.
Can’t put any value except null into a List<?>, which means List of some particular type.
Item 29: Consider typesafe heterogeneous containers
Place the type parameter on the key rather than the container to enable the container to include different types.
1
2
3
4
5
6
7
8
9
10
11
12
13
// Typesafe heterogeneous container pattern - implementation
public class Favorites {
private Map<Class<?>, Object> favorites =
new HashMap<Class<?>, Object>();
public <T> void putFavorite(Class<T> type, T instance) {
if (type == null)
throw new NullPointerException("Type is null");
favorites.put(type, instance);
}
public <T> T getFavorite(Class<T> type) {
return type.cast(favorites.get(type));
}
}
Item 30: Use enums instead of int constants
Java’s enum types are full-fledged classes.
Enums provide high-quality implementations of all the Object methods, Comparable and Serializable.
Enums can also add methods or fields.
1
2
3
4
5
6
7
8
// Enum type with constant-specific method implementations
public enum Operation {
PLUS { double apply(double x, double y){return x + y;} },
MINUS { double apply(double x, double y){return x - y;} },
TIMES { double apply(double x, double y){return x * y;} },
DIVIDE { double apply(double x, double y){return x / y;} };
abstract double apply(double x, double y);
}
ValueOf(String) method can translate a constant’s name into the constant itself.
Consider the strategy enum pattern if multiple enum constants share common behaviors.
Item 31: Use instance fields instead of ordinals
Avoid using ordinal() method of enum.
1
2
3
4
5
6
// Abuse of ordinal to derive an associated value - DON'T DO THIS
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SEPTET, OCTET, NONET, DECTET;
public int numberOfMusicians() { return ordinal() + 1; }
}
Item 32: Use EnumSet instead of bit fields
Use general Set interface for input type.
1
2
3
4
5
6
// EnumSet - a modern replacement for bit fields
public class Text {
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
// Any Set could be passed in, but EnumSet is clearly best
public void applyStyles(Set<Style> styles) { ... }
}
Item 33: Use EnumMap instead of ordinal indexing
It is better to use EnumMap to catalog relationship related with Enum type.
1
2
3
4
5
6
7
8
// Using an EnumMap to associate data with an enum
Map<Herb.Type, Set<Herb>> herbsByType =
new EnumMap<Herb.Type, Set<Herb>>(Herb.Type.class);
for (Herb.Type t : Herb.Type.values())
herbsByType.put(t, new HashSet<Herb>());
for (Herb h : garden)
herbsByType.get(h.type).add(h);
System.out.println(herbsByType);
Item 34: Emulate extensible enums with interfaces
In general, extending enums is a bad idea. If you really want to do that, define an interface for expected behaviors.
Item 35: Prefer annotations to naming patterns
Annotations do not directly affect program semantics, but they do affect the way programs are treated by tools and libraries, which can in turn affect the semantics of the running program. Annotations can be read from source files, class files, or reflectively at run time.
Annotations complement javadoc tags. In general, if the markup is intended to affect or produce documentation, it should probably be a javadoc tag; otherwise, it should be an annotation.
Item 36: Consistently use the Override annotation
Use @Override annotation except for the abstract methods or methods of interfaces.

Source

Friday, July 15, 2011

Effective Java : How to Avoid NPE / Null Pointer Exception in java?

It doesn't take much Java development experience to learn firsthand what the NullPointerException is about. In fact, one person has highlighted dealing with this as the number one mistake Java developers make. I blogged previously on use of String.value(Object) to reduce unwanted NullPointerExceptions. There are several other simple techniques one can use to reduce or eliminate the occurrences of this common type of RuntimeException that has been with us since JDK 1.0. This blog post collects and summarizes some of the most popular of these techniques.

Check Each Object For Null Before Using

The most sure way to avoid a NullPointerException is to check all object references to ensure that they are not null before accessing one of the object's fields or methods. As the following example indicates, this is a very simple technique.

final String causeStr = "adding String to Deque that is set to null.";
final String elementStr = "Fudd";
Deque<String> deque = null;

try
{
deque.push(elementStr);
log("Successful at " + causeStr, System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
if (deque == null)
{
deque = new LinkedList<String>();
}
deque.push(elementStr);
log( "Successful at " + causeStr
+ " (by checking first for null and instantiating Deque implementation)",
System.out);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

In the code above, the Deque used is intentionally initialized to null to facilitate the example. The code in the first try block does not check for null before trying to access a Deque method. The code in the second try block does check for null and instantiates an implementation of the Deque (LinkedList) if it is null. The output from both examples looks like this:

ERROR: NullPointerException encountered while trying to adding 
String to Deque that is set to null.
java.lang.NullPointerException
INFO: Successful at adding String to Deque that is set to null.
(by checking first for null and instantiating Deque implementation)

The message following ERROR in the output above indicates that a NullPointerException is thrown when a method call is attempted on the null Deque. The message following INFO in the output above indicates that by checking Deque for null first and then instantiating a new implementation for it when it is null, the exception was avoided altogether.

This approach is often used and, as shown above, can be very useful in avoiding unwanted (unexpected) NullPointerException instances. However, it is not without its costs. Checking for null before using every object can bloat the code, can be tedious to write, and opens more room for problems with development and maintenance of the additional code. For this reason, there has been talk of introducing Java language support for built-in null detection, automatic adding of these checks for null after the initial coding, null-safe types, use of Aspect-Oriented Programming (AOP) to add null checking to byte code, and other null-detection tools.

Groovy already provides a convenient mechanism for dealing with object references that are potentially null. Groovy's safe navigation operator (?.) returns null rather than throwing a NullPointerException when a null object reference is accessed.

Because checking null for every object reference can be tedious and does bloat the code, many developers choose to judiciously select which objects to check for null. This typically leads to checking of null on all objects of potentially unknown origins. The idea here is that objects can be checked at exposed interfaces and then be assumed to be safe after the initial check.

This is a situation where the ternary operator can be particularly useful. Instead of
// retrieved a BigDecimal called someObject
String returnString;
if (someObject != null)
{
returnString = someObject.toEngineeringString();
}
else
{
returnString = "";
}

the ternary operator supports this more concise syntax

// retrieved a BigDecimal called someObject
final String returnString = (someObject != null)
? someObject.toEngineeringString()
: "";
}

Check Method Arguments for Null

The technique just discussed can be used on all objects. As stated in that technique's description, many developers choose to only check objects for null when they come from "untrusted" sources. This often means testing for null first thing in methods exposed to external callers. For example, in a particular class, the developer might choose to check for null on all objects passed to public methods, but not check for null in private methods.

The following code demonstrates this checking for null on method entry. It includes a single method as the demonstrative method that turns around and calls two methods, passing each method a single null argument. One of the methods receiving a null argument checks that argument for null first, but the other just assumes the passed-in parameter is not null.

/**
    * Append predefined text String to the provided StringBuilder.
    *
    * @param builder The StringBuilder that will have text appended to it; should
    * be non-null.
    * @throws IllegalArgumentException Thrown if the provided StringBuilder is
    * null.
    */
private void appendPredefinedTextToProvidedBuilderCheckForNull(
final StringBuilder builder)
{
if (builder == null)
{
throw new IllegalArgumentException(
"The provided StringBuilder was null; non-null value must be provided.");
}
builder.append("Thanks for supplying a StringBuilder.");
}

/**
    * Append predefined text String to the provided StringBuilder.
    *
    * @param builder The StringBuilder that will have text appended to it; should
    * be non-null.
    */
private void appendPredefinedTextToProvidedBuilderNoCheckForNull(
final StringBuilder builder)
{
builder.append("Thanks for supplying a StringBuilder.");
}

/**
    * Demonstrate effect of checking parameters for null before trying to use
    * passed-in parameters that are potentially null.
    */
public void demonstrateCheckingArgumentsForNull()
{
final String causeStr = "provide null to method as argument.";
logHeader("DEMONSTRATING CHECKING METHOD PARAMETERS FOR NULL", System.out);

try
{
appendPredefinedTextToProvidedBuilderNoCheckForNull(null);
}
catch (NullPointerException nullPointer)
{
log(causeStr, nullPointer, System.out);
}

try
{
appendPredefinedTextToProvidedBuilderCheckForNull(null);
}
catch (IllegalArgumentException illegalArgument)
{
log(causeStr, illegalArgument, System.out);
}
}

When the above code is executed, the output appears as shown next.
ERROR: NullPointerException encountered while trying to provide null to 
method as argument.
java.lang.NullPointerException
ERROR: IllegalArgumentException encountered while trying to provide null
to method as argument.
java.lang.IllegalArgumentException: The provided StringBuilder was null;
non-null value must be provided.


In both cases, an error message was logged. However, the case in which a null was checked for threw an advertised IllegalArgumentException that included additional context information about when the null was encountered. Alternatively, this null parameter could have been handled in a variety of ways. For the case in which a null parameter was not handled, there were no options for how to handle it. Many people prefer to throw a NullPolinterException with the additional context information when a null is explicitly discovered (see Item #60 in the Second Edition of Effective Java or Item #42 in First Edition), but I have a slight preference for IllegalArgumentException when it is explicitly a method argument that is null because I think the very exception adds context details and it is easy to include "null" in the subject.

The technique of checking method arguments for null is really a subset of the more general technique of checking all objects for null. However, as outlined above, arguments to publicly exposed methods are often the least trusted in an application and so checking them may be more important than checking the average object for null.

Checking method parameters for null is also a subset of the more general practice of checking method parameters for general validity as discussed in Item #38 of the Second Edition of Effective Java (Item 23 in First Edition).


Consider Primitives Rather than Objects

I don't think it is a good idea to select a primitive data type (such as int) over its corresponding object reference type (such as Integer) simply to avoid the possibility of a NullPointerException, but there is no denying that one of the advantages of primitive types is that they do not lead to NullPointerExceptions. However, primitives still must be checked for validity (a month cannot be a negative integer) and so this benefit may be small. On the other hand, primitives cannot be used in Java Collections and there are times one wants the ability to set a value to null.

The most important thing is to be very cautious about the combination of primitives, reference types, and autoboxing. There is a warning in Effective Java (Second Edition, Item #49) regarding the dangers, including throwing of NullPointerException, related to careless mixing of primitive and reference types.


Carefully Consider Chained Method Calls

A NullPointerException can be very easy to find because a line number will state where it occurred. For example, a stack trace might look like that shown next:

java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.
demonstrateNullPointerExceptionStackTrace(AvoidingNullPointerExamples.java:222)
at dustin.examples.
AvoidingNullPointerExamples.main(AvoidingNullPointerExamples.java:247)

The stack trace makes it obvious that the NullPointerException was thrown as a result of code executed on line 222 of AvoidingNullPointerExamples.java. Even with the line number provided, it can still be difficult to narrow down which object is null if there are multiple objects with methods or fields accessed on the same line.

For example, a statement like someObject.getObjectA().getObjectB().getObjectC().toString(); has four possible calls that might have thrown the NullPointerException attributed to the same line of code. Using a debugger can help with this, but there may be situations when it is preferable to simply break the above code up so that each call is performed on a separate line. This allows the line number contained in a stack trace to easily indicate which exact call was the problem. Furthermore, it facilitates explicit checking each object for null. However, on the downside, breaking up the code increases the line of code count (to some that's a positive!) and may not always be desirable, especially if one is certain none of the methods in question will ever be null.


Make NullPointerExceptions More Informative

In the above recommendation, the warning was to consider carefully use of method call chaining primarily because it made having the line number in the stack trace for a NullPointerException less helpful than it otherwise might be. However, the line number is only shown in a stack trace when the code was compiled with the debug flag turned on. If it was compiled without debug, the stack trace looks like that shown next:

java.lang.NullPointerException
at dustin.examples.AvoidingNullPointerExamples.
demonstrateNullPointerExceptionStackTrace(Unknown Source)
at dustin.examples.AvoidingNullPointerExamples.main(Unknown Source)

As the above output demonstrates, there is a method name, but not no line number for the NullPointerException. This makes it more difficult to immediately identify what in the code led to the exception. One way to address this is to provide context information in any thrown NullPointerException. This idea was demonstrated earlier when a NullPointerException was caught and re-thrown with additional context information as a IllegalArgumentException. However, even if the exception is simply re-thrown as another NullPointerException with context information, it is still helpful. The context information helps the person debugging the code to more quickly identify the true cause of the problem.

The following example demonstrates this principle.

final Calendar nullCalendar = null;

try
{
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}

try
{
if (nullCalendar == null)
{
throw new NullPointerException("Could not extract Date from provided Calendar");
}
final Date date = nullCalendar.getTime();
}
catch (NullPointerException nullPointer)
{
log("NullPointerException with useful data", nullPointer, System.out);
}

The output from running the above code looks as follows.

ERROR: NullPointerException encountered while trying to NullPointerException 
with useful data
java.lang.NullPointerException
ERROR: NullPointerException encountered while trying to
NullPointerException with useful data
java.lang.NullPointerException: Could not extract Date from provided Calendar

The first error does not provide any context information and only conveys that it is a NullPointerException. The second error, however, had explicit context information added to it which would go a long way in helping identify the source of the exception.


Use String.valueOf Rather than toString

As described previously, one of the surest methods for avoiding NullPointerException is to check the object being referenced for null first. The String.valueOf(Object) method is a good example of a case where this check for null can be done implicitly without any additional effort on the developer's part. I blogged on this previously, but include a brief example of its use here.

 


Source : Inspired by actual events

Wednesday, June 22, 2011

Avoid subtraction based comparison between integers

Before I say anything I want to share with you a code snippet that is a simplified version of something I have recently wrote in my work. There is a small, yet painful bug in this code… can you see it?

public static class Point implements Comparable<Point> {
    private int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public int compareTo(Point other) {
        if (this.x != other.x) {
            return this.x - other.x;
        } else {
            return this.y - other.y;
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Point)) return false;
        Point other = (Point) obj;
        return (this.x == other.x && this.y == other.y);
    }

    @Override
    public int hashCode() {
        return 31 * x + y;
    }
}

This is a simple value class represanting a point. At first glance everything is good with it: the hash function is not sophisticated, but it is correct and legal. The equals() method is written ‘by the book’ so it is probably OK. The class implements Comparable interface and defines a lexicographic order of the points – the code of compareTo() is standard and fulfills the contract of the interface. All three methods are compatible with each other: hash codes of equal points are equal, comparisons are transitive, if A.compareTo(B) == 0 then A.equals(B)… Basically all is fine, so where is the bug? Is there any bug at all?
Unfortunatelly there is a bug in this code. What is worse you probably read about it many times (’Effective Java’ item 11, ‘Java Puzzlers’ puzzle 65, the list goes on an on…). The problem with this code is that substraction based comparators are BAD as they often exposes you to danger of an overflow. This is what happens in this case – see the following:

public static void main(String[] args) {
    Point pZero  = new Point(0, 0);
    Point pPlus  = new Point(2000000000, 0);
    Point pMinus = new Point(-2000000000, 0);

    System.out.println( pPlus.compareTo(pZero) > 0 );
    System.out.println( pZero.compareTo(pMinus) > 0 );
    System.out.println( pPlus.compareTo(pMinus) > 0 );
  }

We are comparing in this code three points. When you look at the declaration of those object you can already see the order of them: pPlus > pZero > pMinus. Just to be sure we check it by printing to console the result of compareTo() function. If you execute this code you’ll get that as expected ‘true’ for pPlus > pZero and ‘true’ for pZero > pMinus. The suprizing thing is the last comparison that evaluates to false. This is because of the integer overflow: in pPlus.compareTo(pMinus) the result value is 2000000000 – (-2000000000) == -294967296! Scary, right?

Wednesday, April 13, 2011

Pre-java 5 style enums

Enumerations already existed in other languages like C, C++, SmallTalk etc. Enums are used primarily to handle a collection of logically grouped constants.
But in java, in prior releases, the standard way to represent an enumerated type was the int Enum pattern:
// int Enum Pattern - has severe problems!
public static final int SEASON_WINTER = 0;
public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER = 2;
public static final int SEASON_FALL   = 3;

Drawbacks of This Approach:

  • Type Safety: All statuses above may carry some business meaning, but in Java language context, these are just int values. This means any int value is a status for this Java program. So the program using these statuses can break with any int value not defined in this group.
  • Compile Time Constants: All these constants are compiled and used in the program. If you want to add any new constant then you will have to add it to the list and recompile everything.
  • Uninformative: When printed, these are just numbers for a reader. E.g. if a program prints status = 3, the reader will have to go and find out what does it actually mean. Amount of information available with the print is minimal.
  • Restricted Behavior: If you want to use these values in a remote call, or compare them, then you will have to handle it explicitly. Serializable, Comparable interfaces offered by Java for same purpose cannot be used. Also there is no room to add any additional behavior to the statuses, e.g. attaching basic object behavior of hashCode(), toString() and equals() methods.
  • Meaningless Switch-Case Use: When you use statuses above in switch case, you cannot use the variable names; instead you will have to use the meaningless/uninformative numbers to compare. Readability of program goes down considerably in this case.
  • Non-Iterative List: This is a list of values, but you cannot iterate over it the way you can on any collection.
The solution to above problem is Enum data type in Java 5. Concept of Enum is obtained from the counterpart technologies like C, C++, C# etc. and also considering the Typesafe Enum design pattern in Effective Java book by Joshua Bloch:


You can read this pattern here.

Chitika