Effective JAVA

1. Introduction

A method’s signature consists of its name and the types of its formal parameters; the signature does not include the method’s return type.

2. Creating and Destroying Objects

Item 1: Consider static factory methods instead of constructors.

Advantage

One advantage of static factory methods is that, unlike constructors, they have names.

A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked.

A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.

A fourth advantage of static factory methods is that they reduce the verbosity of creating parameterized type instances.

Disadvantage

The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.

A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.

Item 2: Consider a builder when faced with many constructor parameters

Telescoping constructor:the telescoping constructor pattern works, but it is hard to write client code when there are many parameters, and harder still to read it.

A JavaBean may be in an inconsistent state partway through its construction. A related disadvantage is that the JavaBeans pattern precludes the possibility of making a class immutable.

The Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters

Item 3: Enforce the singleton property with a private constructor or an enum type

Disadvantage : Making a class a singleton can make it difficult to test its clients, as it’s impossible to substitute a mock implementation for a singleton unless it implements an interface that serves as its type.

To make a singleton class that is implemented using either of the previous approaches serializable, it is not sufficient merely to add implements Serializable to its declaration. To maintain the singleton guarantee, you have to declare all instance fields transient and provide a readResolve method

A single-element enum type is the best way to implement a singleton.

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

Item 4: Enforce noninstantialbility with a private constructor

Attempting to enforce noninstantiability by making a class abstract does not work.

A class can be made noninstantiable by including a private constructor.

// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
... // Remainder omitted
}

As a side effect, this idiom also prevents the class from being subclassed. All constructors must invoke a superclass constructor, explicitly or implicitly, and a subclass would have no accessible superclass constructor to invoke.

Item 5: Avoid creating unnecessary objects

String declaration.

Prefer primitives to boxed primitives, and watch out for unintentional autoboxing.

Item 6: Eliminate obsolete object reference

If a stack grows and then shrinks, the objects that were popped off the stack will not be garbage collected, even if the program using the stack has no more references to them. This is because the stack main- tains obsolete references to these objects. An obsolete reference is simply a reference that will never be dereferenced again. In this case, any references outside of the “active portion” of the element array are obsolete. The active portion consists of the elements whose index is less than size.

Nulling out object references should be the exception rather than the norm. The best way to eliminate an obsolete reference is to let the variable that contained the reference fall out of scope. This occurs naturally if you define each variable in the narrowest possible scope

Whenever a class manages its own memory, the pro- grammer should be alert for memory leaks.

Another common source of memory leaks is caches.

Remember that WeakHashMap is useful only if the desired lifetime of cache entries is determined by external references to the key, not the value.

A third common source of memory leaks is listeners and other callbacks.

Item 7: Avoid finalizers

Finalizers are unpredictable, often dangerous, and generally unnecessary.

You should never do anything time-critical in a finalizer.

The promptness with which finalizers are executed is primarily a function of the garbage collection algorithm, which varies widely from JVM implementation to JVM implementation.

Not only does the language specification provide no guarantee that finalizers will get executed promptly; it provides no guarantee that they’ll get executed at all. It is entirely possible, even likely, that a program terminates without executing finalizers on some objects that are no longer reachable. As a consequence, you should never depend on a finalizer to update critical persistent state.

Solution:

Just provide an explicit termination method, and require clients of the class to invoke this method on each instance when it is no longer needed.

One detail worth mentioning is that the instance must keep track of whether it has been terminated: the explicit termination method must record in a private field that the object is no longer valid, and other methods must check this field and throw an IllegalStateException if they are called after the object has been terminated.

XIANZHEZ: This is why often counter some termination related problems especially in Bitmap, IO operation or some other circumstances on Android.

Good for

One is to act as a “safety netin case the owner of an object forgets to call its explicit termination method. While there’s no guarantee that the finalizer will be invoked promptly, it may be better to free the resource late than never, in those (hopefully rare) cases when the client fails to call the explicit termination method. But the finalizer should log a warning if it finds that the resource has not been terminated, as this indicates a bug in the client code, which should be fixed.

A second legitimate use of finalizers concerns objects with native peers. A native peer is a native object to which a normal object delegates via native meth- ods. Because a native peer is not a normal object, the garbage collector doesn’t know about it and can’t reclaim it when its Java peer is reclaimed. A finalizer is an appropriate vehicle for performing this task, assuming the native peer holds no critical resources. If the native peer holds resources that must be terminated promptly, the class should have an explicit termination method, as described above.

Important

It is important to note that “finalizer chaining” is not performed automatically. You should finalize the subclass in a try block and invoke the superclass finalizer in the corresponding finally block.

// Manual finalizer chaining
@Override protected void finalize() throws Throwable {
try {
... // Finalize subclass state
} finally {
super.finalize();
} }

Use finalizer guardian (an instance of the anonymous class) to avoid forgetting call for super.finalize() method.

// Finalizer Guardian idiom
public class Foo {
// Sole purpose of this object is to finalize outer Foo object
private final Object finalizerGuardian = new Object() {
@Override protected void finalize() throws Throwable {
... // Finalize outer Foo object
}
};
... // Remainder omitted
}

#3. Methods Common to All Objects

Item 8: Obey the general contract when overriding equals()

Conditions not to override equals() method:

  • Each instance of the class is inherently unique.
  • You don’t care whether the class provides a “logical equality” test.
  • A superclass has already overridden equals, and the superclass behavior is appropriate for this class.
  • The class is private or package-private, and you are certain that its equals method will never be invoked.

When a class has a notion of logical equality that differs from mere object identity, and a superclass has not already overridden equals to implement the desired behavior.

Not only to find out whether they are logically equivalent, not whether they refer to the same object; it enables instances to serve as map keys or set elements with predictable, desirable behavior.

Contract:

  • Reflexive: x.equals(x) must return true.
  • Symmetric : x.equals(y) must return true if and only if y.equals(x) returns true.
  • Transitive: if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.
  • Consistent: multiple invocations of x.equals(y) consistently return true or consistently return false.
  • “Non-nullity”: x.equals(null) must return false.

Recipe for a high-quality equals method:

  1. Use the == operator to check if the argument is a reference to this object.

  2. Use the instanceof operator to check if the argument has the correct type.

  3. Cast the argument to the correct type.

  4. For each “significant” field in the class, check if that field of the argument matches the corresponding field of this object. For primitive fields whose type is not float or double, use the == operator for comparisons; for object reference fields, invoke the equals method recursively; for float fields, use the Float.compare method; and for double fields, use Double.compare. The special treatment of float and double fields is made necessary by the existence of Float.NaN, -0.0f and the analogous double constants. For array fields, apply these guidelines to each element.

  5. When you are finished writing your equals method, ask yourself three questions: Is it symmetric? Is it transitive? Is it consistent?

Caveats

  • Always override hashCode when you override equals.
  • Don’t try to be too clever.
  • Don’t substitute another type for Object in the equals declaration.

Item 9: Always override hashCode when you override equals

The general contract for Object.hashCode:

  • Whenever it is invoked on the same object more than once during an execu- tion of an application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execu- tion of an application to another execution of the same application.
  • If two objects are equal according to the equals (Object) method,then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals (Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

If a class is immutable and the cost of computing the hash code is significant, you might consider caching the hash code in the object rather than recalculating it each time it is requested. If you believe that most objects of this type will be used as hash keys, then you should calculate the hash code when the instance is created. Otherwise, you might choose to lazily initialize it the first time hashCode is invoked

Item 10: Always override toString

The toString contract goes on to say, “It is recommended that all subclasses override this method.”

Whether or not you decide to specify the format, you should clearly docu- ment your intentions.

Item 11: Override clone judiciously

If a class implements Cloneable, Object’s clone method returns a field-by-field copy of the object; otherwise it throws CloneNotSupportedException.

To recap, all classes that implement Cloneable should override clone with a public method whose return type is the class itself. This method should first call super.clone and then fix any fields that need to be fixed.

The copy constructor approach and its static factory variant have many advantages over Cloneable/clone.

Given all of the problems associated with Cloneable, it’s safe to say that other interfaces should not extend it, and that classes designed for inheritance (Item 17) should not implement it. Because of its many shortcomings, some expert programmers simply choose never to override the clone method and never to invoke it except, perhaps, to copy arrays.

Item 12: Consider implementing Comparable

Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Throws ClassCastException if the specified object’s type prevents it from being compared to this object.

It is strongly recommanded that the consistent of equals() and compareTo(). But it is not neccessary.

4. Classes and Interfaces

Item 13: Minimize the accessibility of classes and members

The rule of thumb is simple: make each class or member as inaccessible as possible.

For top-level (non-nested) classes and interfaces, there are only two possible access levels: package-private and public.

If a package-private top-level class (or interface) is used by only one class, consider making the top-level class a private nested class of the sole class that uses it (Item 22).

Item 14: In public classes, use accessor methods, not public field

In summary, public classes should never expose mutable fields. It is less harmful, though still questionable, for public classes to expose immutable fields. It is, however, sometimes desirable for package-private or private nested classes to expose fields, whether mutable or immutable.

Item 15: Minimize mutability

To make a class immutable, follow these five rules:

  1. Don’t provide any methods that modify the object’s state.
  2. Ensure that the class can’t be extended.
  3. Make all fields final.
  4. Make all fields private.
  5. Ensure exclusive access to any mutable components.

Immutable objects are simple. Immutable objects are inherently thread-safe; they require no synchronization.

Not only can you share immutable objects, but you can share their internals.

Immutable objects make great building blocks for other objects.

The only real disadvantage of immutable classes is that they require a separate object for each distinct value.

To guarantee immutability, a class must not permit itself to be subclassed. Typically this is done by making the class final, but there is another, more flexible way to do it. The alternative to making an immutable class final is to make all of its constructors private or package-private, and to add public static factories in place of the public constructors.

Static factories have many other advantages over constructors, as discussed in Item 1. For example, suppose that you want to provide a means of creating a com- plex number based on its polar coordinates. This would be very messy using constructors because the natural constructor would have the same signature that we already used: Complex(double, double). With static factories it’s easy.

One caveat should be added concerning serializability.

If a class cannot be made immutable, limit its mutability as much as possible.

Don’t provide a “reinitialize” method that enables an object to be reused as if it had been constructed with a different initial state. Such methods generally provide little if any performance benefit at the expense of increased complexity.

Item 16: Favor composition over inheritance

Instead of extending an existing class, give your new class a private field that references an instance of the existing class. This design is called composition because the existing class becomes a component of the new one. Each instance method in the new class invokes the corresponding method on the contained instance of the existing class and returns the results. This is known as forwarding, and the meth- ods in the new class are known as forwarding methods.

Inheritance will also propagate the flaws which exsiting in super class to the sub class. Consider composition and forwarding when you want to hide these flaws.

XIANZHEZ: Inheritance violates encapsulation.

XIANZHEZ: Compositon and forwarding can be considered as Decorator pattern.

Item 17: Design and document for inheritance or else prohibit it

The class must document its self-use of overridable methods. For each public or protected method or constructor, the documentation must indicate which overridable methods the method or constructor invokes, in what sequence, and how the results of each invocation affect subsequent processing.

The description begins with the phrase “This implementation.”

The only way to test a class designed for inheritance is to write subclasses. Experience shows that three subclasses are usually sufficient to test an extendable class.

As of this writing, there is little in the way of tools or commenting conventions to separate ordinary API documentation from information of interest only to programmers implementing subclasses.

Constructors must not invoke overridable methods, directly or indirectly. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will get invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

Neither clone nor readObject may invoke an overridable method, directly or indirectly. If you decide to implement Serializable in a class designed for inheritance and the class has a readResolve or writeReplace method, you must make the readResolve or writeReplace method protected rather than private. If these methods are private, they will be silently ignored by subclasses. This is one more case where an implementation detail becomes part of a class’s API to permit inheritance.

Item 18: Prefer interfaces to abstract classes

You can combine the virtues of interfaces and abstract classes by providing an abstract skeletal implementation class to go with each nontrivial interface that you export.

Once an interface is released and widely implemented, it is almost impossible to change.

Item 19: Use interfaces only to define types

The constant interface pattern is a poor use of interfaces.

Export the constants with a noninstantiable utility class.

In summary, interfaces should be used only to define types. They should not be used to export constants.

Item 20: Prefer class hierarchies to tagged classes

Tagged classes are verbose, error-prone, and inefficient.

Item 21: Use function objects to represent strategies

Strategy pattern.

All instances of the class are functionally equivalent. Thus it should be a singleton to save on unnecessary object creation costs if it will be executed repeatedly.

When a concrete strategy is used only once, it is typically declared and instantiated as an anonymous class. When a concrete strategy is designed for repeated use, it is generally implemented as a private static member class and exported in a public static final field whose type is the strategy interface.

Item 22: Favor static member classes over nonstatic

A nested class should exist only to serve its enclosing class.

There are four kinds of nested classes:

  • static member classes
  • nonstatic member classes
  • anonymous classes
  • local classes

One common use of a static member class is as a public helper class, useful only in conjunction with its outer class.

It is impossible to create an instance of a nonstatic member class without an enclosing instance.

One common use of a nonstatic member class is to define an Adapter that allows an instance of the outer class to be viewed as an instance of some unrelated class.

If you declare a member class that does not require access to an enclosing instance, always put the static modifier in its declaration.

Storing this reference costs time and space, and can result in the enclosing instance being retained when it would otherwise be eligible for garbage collection.

XIANZHEZ: Nonstatic member class will keep the reference to enclosing class object, which wastes more space and time; if this nonstatic member class is accessible by outer objects, the invocation of its constructor looks very wired and the reference to this nonstatic member class object may result in memory leak, as the eclosing class is referred by the inner nonstatic class and not be eligible for garbage collection.

There are many limitations on the applicability of anonymous classes. You can’t instantiate them except at the point they’re declared. You can’t perform instanceof tests or do anything else that requires you to name the class. You can’t declare an anonymous class to implement multiple interfaces, or to extend a class and implement an interface at the same time. Clients of an anonymous class can’t invoke any members except those it inherits from its supertype. Because anonymous classes occur in the midst of expressions, they must be kept short— about ten lines or fewer—or readability will suffer.

One common use of anonymous classes is to create function objects on the fly. Another common use of anonymous classes is to create process objects, such as Runnable, Thread, or TimerTask instances. A third common use is within static factory methods.

Local classes are the least frequently used of the four kinds of nested classes. A local class can be declared anywhere a local variable can be declared and obeys the same scoping rules.

5. Generics

Item 23: Don't use raw types in new code