Effective Java 記錄

Item 1: Consider static factory methods instead of constructors

advantage:

1 unlike constructors, they have names

2 they are not required to create a new object each time they’re invoked.

3 they can return an object of any subtype of their return type

4 they reduce the verbosity of creating parameterized type instances

disadvantage:

1 providing only static factory methods is that classes without public or protected constructors cannot be subclassed.

2 they are not readily distinguishable from other static methods


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

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 aninconsistent state partway through its construction

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

public class Elvis {
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public static Elvis getInstance() { return INSTANCE; }
    public void leaveTheBuilding() { ... }
    private Object readResolve(){return INSTANCE};
}


To maintain the singleton guarantee, you have to declare all instance fields transient and provide a

readResolve method

public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}


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


Item 4: Enforce non instantiability with a private constructor

Attempting to enforce non instantiability by making a class abstract does not work

 a class can be made non instantiable by including a private constructor


// Non instantiable utility class
public class UtilityClass {
    // Suppress default constructor for non instantiability
    private UtilityClass() {
        throw new AssertionError();
    }
    ... // Remainder omitted
}



Item 5: Avoid creating unnecessary objects


Item 6: Eliminate obsolete object references

Nulling out object references should be the exception rather than the norm.

whenever a class manages its own memory, the programmer should be alert for memory leaks

common source of memory leaks is caches

 common source of memory leaks is listeners and other callbacks


Item 7: Avoid finalizers

never do anything time-critical in a finalizer

never depend on a finalizer to update critical persistent state

there is a severe performance penalty for using finalizers

provide an explicit termination method

Explicit termination methods are typically used in combination with the try-finally construct to

ensure termination

It is important to note that “finalizer chaining” is not performed automatically

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


Instead of putting the finalizer on the class requiring finalization, put the finalizer

on an anonymous class whose sole purpose is to finalize its enclosing instance.

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
}

Item 8: Obey the general contract when overriding equals

 The easiest way to avoid problems is not to override the 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.


The equals method implements an equivalence relation. It is: Reflexive, Symmetric, Transitive, Consistent,


Once you’ve violated the equals contract, you simply don’t know how other objects will behave when 

confronted with your object


There is no way to extend an instantiable class and add a value component while preserving the 

equals contract


do not write an equals method that depends on unreliable resources



Putting it all together, here’s a recipe for a high-quality equals method:

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

    Use the instance of operator to check if the argument has the correct type

    Cast the argument to the correct type

    For each “significant” field in the class, check if that field of the argument matches the corresponding

 field of this object

     Is it symmetric? Is it transitive? Is it consistent?

Item 9: Always override hashCode when you override equals

You must override hashCode in every class that overrides equals, equal objectsmust have equal hash codes

1. Store some constant nonzero value, say, 17, in an int variable called result

2. For each significant field f in your object (each field taken into account by the equals method, that is), do the

following:

a. Compute an int hash code c for the field:

i. If the field is a boolean, compute (f ? 1 : 0).

ii. If the field is a byte, char, short, or int, compute (int) f.

iii. If the field is a long, compute (int) (f ^ (f >>> 32)).

iv. If the field is a float, compute Float.floatToIntBits(f).

v. If the field is a double, compute Double.doubleToLongBits(f), and then hash the resulting long as in step 2.a.iii.

vi. If the field is an object reference and this class’s equals method compares the field by recursively invoking equals,

recursively invoke hashCode on the field. If a more complex comparison is required, compute a “canonical

representation” for this field and invoke hashCode on the canonical representation. If the value of the field is null,

return 0 (or some other constant, but 0 is traditional).

vii. If the field is an array, treat it as if each element were a separate field.That is, compute a hash code for each

significant element by applying these rules recursively, and combine these values per step 2.b. If every element

in an array field is significant, you can use one of theArrays.hashCode methods added in release 1.5.b. Combine

the hash code c computed in step 2.a into result as follows: result = 31 * result + c;

3. Return result.

4. When you are finished writing the hashCode method, ask yourself whether equal instances have equal hash codes. 

Do not be tempted to exclude significant parts of an object from the hash code computation to improve

performance

Item 10: Always override toString

providing a good toString implementation makes your class much more pleasant to use

the toString method should return all of the interesting information contained in the object

Whether or not you decide to specify the format, you should clearly document your intentions

provide programmatic access to all of the information contained in the value returned by toString.

Item 11: Override clone judiciously

if you override the clone method in a nonfinal class, you should return an object obtained by invoking super.clone.

In practice,a class that implements Cloneable is expected to provide a properly functioning public clone method

In effect, the clone method functions as another constructor;you must ensure that it does no harm to the original

object and that it properly establishes invariants on the clone

you are better off providing an alternative means of object copying, or simply not providing the capability

A fine approach to object copying is to provide a copy constructor or copy factory

Item 12: Consider implementing Comparable

public interface Comparable<T> {
    int compareTo(T t);
}

By implementingComparable, a class indicates that its instances have a natural ordering

• The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that

x.compareTo(y) must throw an exception if and only if y.compareTo(x) throws an exception.)

• The implementor must also ensure that the relation is transitive: (x.compareTo(y)> 0 && y.compareTo(z) > 0)

implies x.compareTo(z) > 0.• Finally, the implementor must ensure that x.compareTo(y) == 0 implies that

sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.

• It is strongly recommended, but not strictly required, that (x.compareTo(y)== 0) == (x.equals(y)). Generally

speaking, any class that implements theComparable interface and violates this condition should clearly indicate

this fact. The recommended language is “Note: This class has a natural ordering that is inconsistent with equals.”

public int compareTo(PhoneNumber pn) {
    // Compare area codes
    if (areaCode < pn.areaCode)
        return -1;
    if (areaCode > pn.areaCode)
        return 1;
    // Area codes are equal, compare prefixes
    if (prefix < pn.prefix)
        return -1;
    if (prefix > pn.prefix)
        return 1;
    // Area codes and prefixes are equal, compare line numbers
    if (lineNumber < pn.lineNumber)
        return -1;
    if (lineNumber > pn.lineNumber)
        return 1;
    return 0; // All fields are equal
}

public int compareTo(PhoneNumber pn) {
    // Compare area codes
    int areaCodeDiff = areaCode - pn.areaCode;
    if (areaCodeDiff != 0)
        return areaCodeDiff;
    // Area codes are equal, compare prefixes
    int prefixDiff = prefix - pn.prefix;
    if (prefixDiff != 0)
        return prefixDiff;
    // Area codes and prefixes are equal, compare line numbers
    return lineNumber - pn.lineNumber;
}
the difference between the lowest and highest possible field values is less than or equal to Integer.MAX_VALUE

Item 13: Minimize the accessibility of classes and members

make each class or member as inaccessible as possible

Instance fields should never be public 

classes with public mutable fields are not thread-safe

it is wrong for a class to have a public static final array field, or an accessor that returns such a field

// Potential security hole!
public static final Thing[] VALUES = { ... };


private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES =
    Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

private static final Thing[] PRIVATE_VALUES = { ... };
public static final Thing[] values() {
    return PRIVATE_VALUES.clone();
}


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

if a class is accessible outside its package, provide accessor methods

if a class is package-private or is a private nested class, there is nothing inherently wrong with exposing

its data fields


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 inherently thread-safe; they require no synchronization.

immutable objects can be shared freely.

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.


Classes should be immutable unless there’s a very good reason to make them mutable.

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

make every field final unless there is a compelling reason to make it non final.


Item 16: Favor composition over inheritance

Unlike method invocation, inheritance violates encapsulation 

// Wrapper class - uses composition in place of inheritance
public class InstrumentedSet<E> extends ForwardingSet<E> {
    private int addCount = 0;
    public InstrumentedSet(Set<E> s) {
         super(s);
    }
    @Override public boolean add(E e) {
        addCount++;
        return super.add(e);
    }
    @Override public boolean addAll(Collection<? extends E> c) {
        addCount += c.size();
        return super.addAll(c);
    }
    public int getAddCount() {
        return addCount;
    }
}
// Reusable forwarding class
public class ForwardingSet<E> implements Set<E> {
    private final Set<E> s;
    public ForwardingSet(Set<E> s) { this.s = s; }
    public void clear() { s.clear(); }
    public boolean contains(Object o) { return s.contains(o); }
    public boolean isEmpty() { return s.isEmpty(); }
    public int size() { return s.size(); }
    public Iterator<E> iterator() { return s.iterator(); }
    public boolean add(E e) { return s.add(e); }
    public boolean remove(Object o) { return s.remove(o); }
    public boolean containsAll(Collection<?> c)
        { return s.containsAll(c); }
    public boolean addAll(Collection<? extends E> c)
        { return s.addAll(c); }
    public boolean removeAll(Collection<?> c)
        { return s.removeAll(c); }
    public boolean retainAll(Collection<?> c)
        { return s.retainAll(c); }
    public Object[] toArray() { return s.toArray(); }
    public <T> T[] toArray(T[] a) { return s.toArray(a); }
    @Override public boolean equals(Object o)
        { return s.equals(o); }
    @Override public int hashCode() { return s.hashCode(); }
    @Override public String toString() { return s.toString(); }
}


Inheritance is appropriate only in circumstances where the subclass really is a subtype of the 

superclass. In other words, a class B should extend a class A only if an “is-a” relationship exists 

between the two classes


To summarize, inheritance is powerful, but it is problematic because it violates encapsulation. 

It is appropriate only when a genuine subtype relationship exists between the subclass and the 

superclass. Even then, inheritance may lead to fragility if the subclass is in a different package

 from the superclass and the superclass is not designed for inheritance. To avoid this fragility, 

use composition and forwarding instead of inheritance, especially if an appropriate interface to 

implement a wrapper class exists. Not only are wrapper classes more robust than subclasses, 

they are also more powerful.


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

the class must document its self-use of overridable methods

a class may have to provide hooks into its internal workings in the form of judiciously chosen protected 

methods 


The only way to test a class designed for inheritance is to write subclasses.


Constructors must not invoke overridable methods


neither clone nor readObject may invoke an overridable method, directly or indirectly


designing a class for inheritance places substantial limitations on the class


The best solution to this problem is to prohibit subclassing in classes that are not designed and 

documented to be safely subclassed.


You can eliminate a class’s self-use of overridable methods mechanically,without changing its behavior. 

Move the body of each overridable method to a private“helper method” and have each overridable method 

invoke its private helper method. Then replace each self-use of an overridable method with a direct invocation 

of the overridable method’s private helper method.

Item 18: Prefer interfaces to abstract classes

Existing classes can be easily retrofitted to implement a new interface

Interfaces are ideal for defining mixins

Interfaces allow the construction of nonhierarchical type frameworks

Interfaces enable safe, powerful functionality enhancements 


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.

// Concrete implementation built atop skeletal implementation
static List<Integer> intArrayAsList(final int[] a) {
    if (a == null)
        throw new NullPointerException();
    return new AbstractList<Integer>() {
        public Integer get(int i) {
            return a[i]; // Autoboxing (Item 5)
        }
        @Override public Integer set(int i, Integer val) {
            int oldVal = a[i];
            a[i] = val; // Auto-unboxing
            return oldVal; // Autoboxing
        }
        public int size() {
            return a.length;
        }
    };
}


It is far easier to evolve an abstract class than an interface

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.

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { } // Prevents instantiation
    public static final double AVOGADROS_NUMBER = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS = 9.10938188e-31;
}

// Use of static import to avoid qualifying constants
import static com.effectivejava.science.PhysicalConstants.*;
public class Test {
    double atoms(double mols) {
        return AVOGADROS_NUMBER * mols;
    }
    ...
    // Many more uses of PhysicalConstants justify static import
}



Item 20: Prefer class hierarchies to tagged classes

// Tagged class - vastly inferior to a class hierarchy!
class Figure {
    enum Shape { RECTANGLE, CIRCLE };
    // Tag field - the shape of this figure
    final Shape shape;
    // These fields are used only if shape is RECTANGLE
    double length;
    double width;
    // This field is used only if shape is CIRCLE
    double radius;
    // Constructor for circle
    Figure(double radius) {
        shape = Shape.CIRCLE;
        this.radius = radius;
    }
    // Constructor for rectangle
    Figure(double length, double width) {
        shape = Shape.RECTANGLE;
        this.length = length;
        this.width = width;
    }
    double area() {
        switch(shape) {
            case RECTANGLE:
                return length * width;
            case CIRCLE:
                return Math.PI * (radius * radius);
            default:
                throw new AssertionError();
        }
    }
}

In short, tagged classes are verbose, error-prone, and inefficient


A tagged class is just a pallid imitation of a class hierarchy.

// Class hierarchy replacement for a tagged class
abstract class Figure {
    abstract double area();
}
class Circle extends Figure {
    final double radius;
    Circle(double radius) { this.radius = radius; }
    double area() { return Math.PI * (radius * radius); }
}
class Rectangle extends Figure {
    final double length;
    final double width;
    Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
    double area() { return length * width; }
}
class Square extends Rectangle {
    Square(double side) {
        super(side, side);
    }
}


Item 21: Use function objects to represent strategies

In other words, we need to define a strategy interface to go with the concrete strategy class

class StringLengthComparator {
    private StringLengthComparator() { }
    public static final StringLengthComparator
    INSTANCE = new StringLengthComparator();
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
}
// Strategy interface
public interface Comparator<T> {
    public int compare(T t1, T t2);
}

class StringLengthComparator implements Comparator<String> {
... // class body is identical to the one shown above
}
To summarize, a primary use of function pointers is to implement the Strategy pattern. To implement this 

pattern in Java, declare an interface to represent the strategy, and a class that implements this interface 

for each concrete strategy.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

static member classes, nonstatic member classes, anonymous classes, and local classes


 If an instance of a nested class can exist in isolation from an instance of its enclosing class, then the nested 

class must be a static member class: it is impossible to create an instance of a nonstatic member class without 

an enclosing instance


A common use of private static member classes is to represent components of the object represented by 

their enclosing class


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 omit static modifier, each instance will have an extraneous reference to its enclosing instance. 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

Anonymous classes have enclosing instances if and only if they occur in a nonstatic context.But even if they 

occur in a static context, they cannot have any static members


One common use of anonymous classes is to create function objects (Item 21)on the fly

Another common use of anonymous classes is to create process objects, such asRunnable, Thread, or 

TimerTask instances


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

If you use raw types, you lose all the safety and expressiveness benefits of generics.

you lose type safety if you use a raw type like List, but not if you use a parameterized type like List.

you can’t put any element(other than null) into a Collection. 

You must use raw types in class literals.


This is the preferred way to use the instanceof operator with generic types:

// Legitimate use of raw type - instanceof operator
if (o instanceof Set) { // Raw type
    Set<?> m = (Set<?>) o; // Wildcard type
    ...
}


In summary, using raw types can lead to exceptions at runtime, so don’t use them in new code. They are provided 

only for compatibility and interoperability with legacy code that predates the introduction of generics. As a quick review,

Set is a parameterized type representing a set that can contain objects of any type, Set is a wildcard type representing 

a set that can contain only objects of some unknown type, and Set is a raw type, which opts out of the generic type system. 

The first two are safe and the last is not.


Item 24: Eliminate unchecked warnings

If you eliminate all warnings, you are assured that your code is type safe, which is a very good thing. It means that you 

won’t get a ClassCastException at runtime, and it increases your confidence that your program is behaving as you intended


If you can’t eliminate a warning, and you can prove that the code that provoked the warning is type safe, then (and only then) 

suppress the warning with an @SuppressWarnings("unchecked") annotation.


Always use the SuppressWarnings annotation on the smallest scope possible.


Every time you use an @SuppressWarnings("unchecked") annotation,add a comment saying why it’s safe to do so


Item 25: Prefer lists to arrays

 arrays are covariant.This scary-sounding word means simply that if Sub is a subtype of Super, then the array type Sub[] is a 

subtype of Super[]

The second major difference between arrays and generics is that arrays are reified. This means that arrays know and enforce 

their element types at runtime


In summary, arrays and generics have very different type rules. Arrays are covariant and reified; generics are invariant and 

erased. As a consequence, arrays provide runtime type safety but not compile-time type safety and vice versa for generics. 

Generally speaking, arrays and generics don’t mix well. If you find yourself mixing them and getting compile-time errors or 

warnings, your first impulse should be to replace the arrays with lists.


Item 26: Favor generic types

// Initial attempt to generify Stack = won’t compile!
public class Stack<E> {
    private E[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    public Stack() {
        elements = new E[DEFAULT_INITIAL_CAPACITY];
    }
    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }
    public E pop() {
        if (size==0)
            throw new EmptyStackException();
        E result = elements[--size];
        elements[size] = null; // Eliminate obsolete reference
        return result;
    }
    ... // no changes in isEmpty or ensureCapacity
}
You’ll generally get at least one error or warning, and this class is no exception.Luckily, this class generates only one error:

    Stack.java:8: generic array creation elements = new E[DEFAULT_INITIAL_CAPACITY];

you can’t create an array of a non-reifiable type, such as E

first solution :

    elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];

// The elements array will contain only E instances from push(E).
// This is sufficient to ensure type safety, but the runtime
// type of the array won't be E[]; it will always be Object[]!
@SuppressWarnings("unchecked")
public Stack() {
    elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}

second solution:

    E result = (E) elements[--size];

// Appropriate suppression of unchecked warning
public E pop() {
    if (size==0)
        throw new EmptyStackException();
    // push requires elements to be of type E, so cast is correct
    @SuppressWarnings("unchecked") E result =
    (E) elements[--size];
    elements[size] = null; // Eliminate obsolete reference
    return result;
}
 in a more realistic generic class than Stack, you would probably be reading from the array at many points in the code, so 

choosing the second solution would require many casts to E rather than a single cast to E[],which is why the first solution is 

used more commonly


In summary, generic types are safer and easier to use than types that require casts in client code. When you design new types, 

make sure that they can be used without such casts. This will often mean making the types generic. Generify your existing types 

as time permits. This will make life easier for new users of these types without breaking existing clients.


Item 27: Favor generic methods

Static utility methods are particularly good candidates for generification.

The type parameter list, which declares the type parameter, goes between the method’s modifiers and its return type.

// Generic method
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
    Set<E> result = new HashSet<E>(s1);
    result.addAll(s2);
    return result;
}

 You can make the method more flexible by using bounded wildcard types.


In summary, generic methods, like generic types, are safer and easier to use than methods that require their clients to cast input 

parameters and return values.Like types, you should make sure that your new methods can be used without casts, which will often 

mean making them generic. And like types, you should generify your existing methods to make life easier for new users without 

breaking existing clients.


Item 28: Use bounded wildcards to increase API flexibility

// 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());
}


For maximum flexibility, use wildcard types on input parameters that represent producers or consumers.


PECS stands for producer-extends, consumer-super.In other words, if a parameterized type represents a T producer, use <? extends T>;if it 

represents a T consumer, use <? super T>. 


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.


If the user of a class has to think about wildcard types, there is probably something wrong with the class’s API.


Set<Number> numbers = Union.<Number>union(integers, doubles);

Comparables are always consumers, so you should always use Comparable in preference to Comparable. The same is true of 

comparators, so you should always use Comparator in preference to Comparator.


if a type parameter appears only once in a method declaration, replace it with a wildcard. 


Item 29: Consider typesafe heterogeneous containers

// Typesafe heterogeneous container pattern - API
public class Favorites {
    public <T> void putFavorite(Class<T> type, T instance);
    public <T> T getFavorite(Class<T> type);
}
// 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));
   }
}
// Achieving runtime type safety with a dynamic cast
public <T> void putFavorite(Class<T> type, T instance) {
    favorites.put(type, type.cast(instance));
}
In summary, the normal use of generics, exemplified by the collections APIs,restricts you to a fixed number of type parameters per 

container. You can get around this restriction by placing the type parameter on the key rather than the container. You can use Class 

objects as keys for such type safe heterogeneous containers. A Class object used in this fashion is called a type token. You can 

also use a custom key type. For example, you could have a DatabaseRow type representing a database row (the container), and a 

generic type Column as its key.

Item 30: Use enums instead of int constants

int enum pattern, has many shortcomings. It provides nothing in the way of type safety and little in the way of convenience.

Programs that use the int enum pattern are brittle. Because int enums are compile-time constants, they are compiled into the clients 

that use them.

String enum pattern, is even less desirable. While it does provide printable strings for its constants, it can lead to performance problems 

because it relies on string comparisons.


 Java’s enum types is simple: they are classes that export one instance for each enumeration constant via a public static final field. Enum 

types are effectively final, by virtue of having no accessible constructors.

 They are a generalization of singletons 

Enums provide compile-time type safety.

Enum types with identically named constants coexist peacefully because each type has its own namespace.

 Enums are by their nature immutable, so all fields should be final .

// Enum type with data and behavior
public enum Planet {
    MERCURY(3.302e+23, 2.439e6),
    VENUS (4.869e+24, 6.052e6),
    EARTH (5.975e+24, 6.378e6),
    MARS (6.419e+23, 3.393e6),
    JUPITER(1.899e+27, 7.149e7),
    SATURN (5.685e+26, 6.027e7),
    URANUS (8.683e+25, 2.556e7),
    NEPTUNE(1.024e+26, 2.477e7);
    private final double mass; // In kilograms
    private final double radius; // In meters
    private final double surfaceGravity; // In m / s^2
    // Universal gravitational constant in m^3 / kg s^2
    private static final double G = 6.67300E-11;
    // Constructor
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
        surfaceGravity = G * mass / (radius * radius);
    }
    public double mass() { return mass; }
    public double radius() { return radius; }
    public double surfaceGravity() { return surfaceGravity; }
    public double surfaceWeight(double mass) {
        return mass * surfaceGravity; // F = ma
    }
}

 enums, has a static values method that returns an array of its values in the order they were declared,the toString method returns the 

declared name of each enum value,


 there is a better way to associate a different behavior with each enum constant: declare an abstract apply method in the enum type, 

and override it with a concrete method for each constant in a constant-specific class body. Such method sare knows as constant-specific

 method implementations:

// 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);
}


abstract methods in an enum type must be overridden with concrete methods in all of its constants.

// Enum type with constant-specific class bodies and data
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; }
    };
    private final String symbol;
    Operation(String symbol) { this.symbol = symbol; }
    @Override public String toString() { return symbol; }
    abstract double apply(double x, double y);
}

Enum constructors aren’t permitted to access the enum’s static fields, except for compile-time constant fields. This restriction is necessary 

because these static fields have not yet been initialized when the constructors run.


// The strategy enum pattern
enum PayrollDay {
    MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY),
    WEDNESDAY(PayType.WEEKDAY), THURSDAY(PayType.WEEKDAY),
    FRIDAY(PayType.WEEKDAY),
    SATURDAY(PayType.WEEKEND), SUNDAY(PayType.WEEKEND);
    private final PayType payType;
    PayrollDay(PayType payType) { this.payType = payType; }
    double pay(double hoursWorked, double payRate) {
        return payType.pay(hoursWorked, payRate);
    }
    // The strategy enum type
    private enum PayType {
        WEEKDAY {
            double overtimePay(double hours, double payRate) {
                 return hours <= HOURS_PER_SHIFT ? 0 :
                      (hours - HOURS_PER_SHIFT) * payRate / 2;
            }
        },
        WEEKEND {
             double overtimePay(double hours, double payRate) {
                 return hours * payRate / 2;
             }
        };
        private static final int HOURS_PER_SHIFT = 8;
        abstract double overtimePay(double hrs, double payRate);
        double pay(double hoursWorked, double payRate) {
            double basePay = hoursWorked * payRate;
            return basePay + overtimePay(hoursWorked, payRate);
        }
    }
}


So when should you use enums? Anytime you need a fixed set of constants.


Item 31: Use instance fields instead of ordinals

Never derive a value associated with an enum from its ordinal; store it in an instance field instead:

public enum Ensemble {
    SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
    SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),
    NONET(9), DECTET(10), TRIPLE_QUARTET(12);
    private final int numberOfMusicians;
    Ensemble(int size) { this.numberOfMusicians = size; }
    public int numberOfMusicians() { return numberOfMusicians; }
}


Item 32: Use EnumSet instead of bit fields

// 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) { ... }
}


In summary, just because an enumerated type will be used in sets, there is no reason to represent it with bit fields. The EnumSet class 

combines the conciseness and performance of bit fields with all the many advantages of enum types described in Item 30. The one real 

disadvantage of EnumSet is that it is not, as of release 1.6, possible to create an immutable EnumSet, but this will likely be remedied in 

an upcoming release. In the meantime, you can wrap an EnumSet withCollections.unmodifiableSet, but conciseness and performance 

will suffer.


Item 33: Use EnumMap instead of ordinal indexing

In summary, it is rarely appropriate to use ordinals to index arrays: useEnumMap instead. If the relationship that you are representing is 

multidimensional,use EnumMap<..., EnumMap<...>>. This is a special case of the general principle that application programmers should 

rarely, if ever, use Enum.ordinal.


Item 34: Emulate extensible enums with interfaces

// Emulated extensible enum using an interface
public interface Operation {
    double apply(double x, double y);
}
public enum BasicOperation implements Operation {
    PLUS("+") {
        public double apply(double x, double y) { return x + y; }
    },
    MINUS("-") {
        public double apply(double x, double y) { return x - y; }
    },
    TIMES("*") {
        public double apply(double x, double y) { return x * y; }
    },
    DIVIDE("/") {
        public double apply(double x, double y) { return x / y; }
    };
    private final String symbol;
    BasicOperation(String symbol) {
        this.symbol = symbol;
    }
    @Override public String toString() {
        return symbol;
    }
}
In summary, while you cannot write an extensible enum type, you can emulate it by writing an interface to go with a basic enum type that 

implements the interface. This allows clients to write their own enums that implement the interface. These enums can then be used wher-

ever the basic enum type can be used, assuming APIs are written in terms of the interface.

Item 35: Prefer annotations to naming patterns


naming patterns:

First, typographical errors may result in silent failures.

A second disadvantage of naming patterns is that there is no way to ensure that they are used only on appropriate program elements. 

A third disadvantage of naming patterns is that they provide no good way to associate parameter values with program elements.


// Marker annotation type declaration
import java.lang.annotation.*;
/**
 * Indicates that the annotated method is a test method.
 * Use only on parameterless static methods.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
}

// Program to process marker annotations
import java.lang.reflect.*;
public class RunTests {
public static void main(String[] args) throws Exception {
    int tests = 0;
    int passed = 0;
    Class testClass = Class.forName(args[0]);
    for (Method m : testClass.getDeclaredMethods()) {
        if (m.isAnnotationPresent(Test.class)) {
            tests++;
            try {
                m.invoke(null);
                passed++;
            } catch (InvocationTargetException wrappedExc) {
                Throwable exc = wrappedExc.getCause();
                System.out.println(m + " failed: " + exc);
            } catch (Exception exc) {
                System.out.println("INVALID @Test: " + m);
            }
        }
    }
    System.out.printf("Passed: %d, Failed: %d%n",
    passed, tests - passed);
}
}

// Annotation type with a parameter
import java.lang.annotation.*;
/**
 * Indicates that the annotated method is a test method that
 * must throw the designated exception to succeed.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
    Class<? extends Exception> value();
}


if (m.isAnnotationPresent(ExceptionTest.class)) {
    tests++;
    try {
        m.invoke(null);
        System.out.printf("Test %s failed: no exception%n", m);
    } catch (InvocationTargetException wrappedEx) {
        Throwable exc = wrappedEx.getCause();
        Class<? extends Exception> excType =
        m.getAnnotation(ExceptionTest.class).value();
        if (excType.isInstance(exc)) {
            passed++;
        } else {
            System.out.printf(
                "Test %s failed: expected %s, got %s%n",
                m, excType.getName(), exc);
        }
   } catch (Exception exc) {
        System.out.println("INVALID @Test: " + m);
   }
}


// Annotation type with an array parameter
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
    Class<? extends Exception>[] value();
}


if (m.isAnnotationPresent(ExceptionTest.class)) {
    tests++;
    try {
        m.invoke(null);
        System.out.printf("Test %s failed: no exception%n", m);
    } catch (Throwable wrappedExc) {
        Throwable exc = wrappedExc.getCause();
        Class<? extends Exception>[] excTypes =
        m.getAnnotation(ExceptionTest.class).value();
        int oldPassed = passed;
        for (Class<? extends Exception> excType : excTypes) {
            if (excType.isInstance(exc)) {
                passed++;
                break;
            }
        }
        if (passed == oldPassed)
            System.out.printf("Test %s failed: %s %n", m, exc);
    }
}


That said, with the exception of toolsmiths, most programmers will have no need to define annotation types. All programmers should, 

however, use the predefined annotation types provided by the Java platform (Items 36 and Item24). Also, consider using any annotations 

provided by your IDE or static analysis tools. Such annotations can improve the quality of the diagnostic information provided by these tools. 

Note, however, that these annotations have yet to be standardized,so you will have some work to do if you switch tools, or if a standard

emerges.


Item 36: Consistently use the Override annotation


 you should use the Override annotation on every method declaration that you believe to override a superclass declaration.


In summary, the compiler can protect you from a great many errors if you use the Override annotation on every method declaration that you 

believe to override a super type declaration, with one exception. In concrete classes, you need not annotate methods that you believe to override 

abstract method declarations(though it is not harmful to do so).


Item 37: Use marker interfaces to define types


A marker interface is an interface that contains no method declarations, but merely designates (or “marks”) a class that implements the interface 

as having some property.


marker interfaces define a type that is implemented by instances of the marked class; marker annotations do not.

Another advantage of marker interfaces over marker annotations is that they can be targeted more precisely. 


The chief advantage of marker annotations over marker interfaces is that it is possible to add more information to an annotation type after it is 

already in use, by adding one or more annotation type elements with defaults

Another advantage of marker annotations is that they are part of the larger annotation facility. 


Clearly you must use an annotation if the marker applies to any program element other than a class or interface, as only classes and interfaces 

can be made to implement or extend an interface. 

 Might I want to write one or more methods that accept only objects that have this marking? If so, you should use a marker interface in preference 

to an annotation. 

 Do I want to limit the use of this marker to elements of a particular interface, forever? If so, it makes sense to define the marker as a sub interface 

of that interface. 


Item 38: Check parameters for validity


 it is not uncommon that index values must be non-negative and object references must be non-null. You should clearly document all such restrictions 

and enforce them with checks at the beginning of the method body. 


For public methods, use the Javadoc @throws tag to document the exception that will be thrown if a restriction on parameter values is violated (Item 62). 

Typically the exception will be IllegalArgumentException, IndexOutOfBoundsException, or NullPointerException 


/**
* Returns a BigInteger whose value is (this mod m). This method
* differs from the remainder method in that it always returns a
* non-negative BigInteger.
*
* @param m the modulus, which must be positive
* @return this mod m
* @throws ArithmeticException if m is less than or equal to 0
*/
public BigInteger mod(BigInteger m) {
    if (m.signum() <= 0)
        throw new ArithmeticException("Modulus <= 0: " + m);
    ... // Do the computation
}


nonpublic methods should generally check their parameters using assertions, as shown below:

// Private helper function for a recursive sort
private static void sort(long a[], int offset, int length) {
    assert a != null;
    assert offset >= 0 && offset <= a.length;
    assert length >= 0 && length <= a.length - offset;
    ... // Do the computation
}


Unlike normal validity checks, assertions throw AssertionError if they fail.

Constructors represent a special case of the principle that you should check the validity of parameters that are to be stored away for later use. 

Note, however, that indiscriminate reliance on implicit validity checks can result in a loss of failure atomicity 


To summarize, each time you write a method or constructor, you should think about what restrictions exist on its parameters. You should document 

these restriction sand enforce them with explicit checks at the beginning of the method body.It is important to get into the habit of doing this. The 

modest work that it entails will be paid back with interest the first time a validity check fails.


Item 39: Make defensive copies when needed


In a safe language, it is possible to write classes and to know with certainty that their invariants will remain true, no matter what happens in any other 

part of the system.


You must program defensively, with the assumption that clients of your class will do their best to destroy its invariants.


it is essential to make a defensive copy of each mutable parameter to the constructor 


 Note that defensive copies are made before checking the validity of the parameters (Item 38), and the validity check is performed on the copies rather 

than on the originals.


do not use the clone method to make a defensive copy of a parameter whose type is subclassable by untrusted parties.


 merely modify the accessors to return defensive copies of mutable internal fields


 If a class trusts its caller not to modify an internal component,perhaps because the class and its client are both part of the same package, then it may be 

appropriate to dispense with defensive copying.


In summary, if a class has mutable components that it gets from or returns to its clients, the class must defensively copy these components. If the cost of 

the copy would be prohibitive and the class trusts its clients not to modify the components inappropriately, then the defensive copy may be replaced by 

documentation outlining the client’s responsibility not to modify the affected components.


Item 40: Design method signatures carefully

Choose method names carefully. 

Don’t go overboard in providing convenience methods. 

Avoid long parameter lists. 


One is to break the method up into multiple methods, each of which requires only a subset of the parameters. 

A second technique for shortening long parameter lists is to create helper classes to hold groups of parameters. 

A third technique that combines aspects of the first two is to adapt the Builder pattern (Item 2) from object construction to method invocation. 


For parameter types, favor interfaces over classes 

Prefer two-element enum types to boolean parameters.


Item 41: Use overloading judiciously

the choice of which overloading to invoke is made at compile time. 

selection among overloaded methods is static, while selection among overridden methods is dynamic.

 avoid confusing uses of overloading.

 A safe, conservative policy is never to export two overloadings with the same number of parameters. 


To summarize, just because you can overload methods doesn’t mean you should. You should generally refrain from overloading methods with 

multiple signatures that have the same number of parameters. 


Item 42: Use varargs judiciously

// The right way to use varargs to pass one or more arguments
static int min(int firstArg, int... remainingArgs) {
    int min = firstArg;
    for (int arg : remainingArgs)
        if (arg < min)
            min = arg;
    return min;
}


Varargs were designed for printf, which was added to the platform in release 1.5, and for the core reflection facility (Item 53)


Don’t retrofit every method that has a final array parameter; use varargs only when a call really operates on a variable-length sequence of values.


Exercise care when using the varargs facility in performance-critical situations.Every invocation of a varargs method causes an array allocation 

and initialization.If you have determined empirically that you can’t afford this cost but you need the flexibility of varargs, there is a pattern that lets 

you have your cake and eat it too. Suppose you’ve determined that 95 percent of the calls to a method have three or fewer parameters. 

public void foo() { }
public void foo(int a1) { }
public void foo(int a1, int a2) { }
public void foo(int a1, int a2, int a3) { }
public void foo(int a1, int a2, int a3, int... rest) { }


In summary, varargs methods are a convenient way to define methods that require a variable number of arguments, but they should not be overused. 

They can produce confusing results if used inappropriately.


Item 43: Return empty arrays or collections, not nulls


It is errorprone,because the programmer writing the client might forget to write the specialcase code to handle a null return. Such an error may go 

unnoticed for years, as such methods usually return one or more objects. Less significant, but still worthy of note, returning null in place of an empty 

array also complicates the method that returns the array or collection.


First, it is inadvisable to worry about performance at this level unless profiling has shown that the method in question is a real contributor to performance

problems (Item 55). Second, it is possible to return the same zero-length array from every invocation that returns no items because zero-length arrays 

are immutable and immutable objects may be shared freely 

// The right way to return an array from a collection
private final List<Cheese> cheesesInStock = ...;
private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];
/**
* @return an array containing all of the cheeses in the shop.
*/
public Cheese[] getCheeses() {
     return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
}
In this idiom, an empty-array constant is passed to the toArray method to indicate the desired return type. Normally the toArray method allocates there 

turned array, but if the collection is empty, it fits in the zero-length input array,and the specification for Collection.toArray(T[]) guarantees that the input 

array will be returned if it is large enough to hold the collection. Therefore the idiom never allocates an empty array.


In summary, there is no reason ever to return null from an array- or collection-valued method instead of returning an empty array or collection.


Item 44: Write doc comments for all exposed API elements

。。。。


Item 45: Minimize the scope of local variables

The most powerful technique for minimizing the scope of a local variableis to declare it where it is first used. 


Declaring a local variable prematurely can cause its scope not only to extend too early, but also to end too late.


Nearly every local variable declaration should contain an initializer.  

 One exception to this rule concerns try catch statements. If a variable is initialized by a method that throws a checked exception, it must be initialized 

inside a try block. If the value must be used outside of the try block, then it must be declared before the try block, where it cannot yet be “sensibly initialized.” 


prefer for loops to while loops, assuming the contents of the loop variable aren’t needed after the loop terminates.

Moreover, if you use a for loop, it’s much less likely that you’ll make the cutand-paste error, as there’s no incentive to use different variable names in the 

two loops. 


A final technique to minimize the scope of local variables is to keep methods small and focused. 


Item 46: Prefer for-each loops to traditional for loops


Not only does the for-each loop let you iterate over collections and arrays, it lets you iterate over any object that implements the Iterable interface. 


In summary, the for-each loop provides compelling advantages over the traditional for loop in clarity and bug prevention, with no performance penalty. You

should use it wherever you can. Unfortunately, there are three common situations where you can’t use a for-each loop:

1. Filtering—If you need to traverse a collection and remove selected elements,then you need to use an explicit iterator so that you can call its remove 

method.

2. Transforming—If you need to traverse a list or array and replace some or all of the values of its elements, then you need the list iterator or array index in

order to set the value of an element.

3. Parallel iteration—If you need to traverse multiple collections in parallel,then you need explicit control over the iterator or index variable, so that all iteratorsor 

index variables can be advanced in lockstep (as demonstrated unintentionally in the buggy card and dice examples above).


Item 47: Know and use the libraries


By using a standard library,you take advantage of the knowledge of the experts who wrote it and the experience of those who used it before you.

A second advantage of using the libraries is that you don’t have to waste your time writing ad hoc solutions to problems that are only marginally related to your

work.

A third advantage of using standard libraries is that their performance tends to improve over time, with no effort on your part.  


but every programmer should be familiar with the contents of java.lang, java.util, and, to a lesser extent, java.io. Knowledge of other libraries can be acquired 

on an as-needed basis.


Item 48: Avoid float and double if exact answers are required


The float and double types are particularly illsuited for monetary calculations because it is impossible to represent 0.1 (or any other negative power of ten) as 

a float or double exactly.


The right way to solve this problem is to use BigDecimal, int, or long for monetary calculations.


 it’s less convenient than using a primitive arithmetic type, and it’s slower. The latter disadvantage is irrelevant if you’re solving a single short problem, but the 

former may annoy you.


An alternative to using BigDecimal is to use int or long, depending on the amounts involved, and to keep track of the decimal point yourself. 


Item 49: Prefer primitive types to boxed primitives


First, primitives have only their values, whereas boxed primitives have identities distinct from their values. In other words, two boxed primitive instances can have

the same value and different identities. Second, primitive types have only fully functional values, whereas each boxed primitive type has one nonfunctional value,

which is null, in addition to all of the functional values of its corresponding primitive type. Last, primitives are generally more time- and space-efficient than boxed

primitives.


// Broken comparator - can you spot the flaw?
Comparator<Integer> naturalOrder = new Comparator<Integer>() {
    public int compare(Integer first, Integer second) {
        return first < second ? -1 : (first == second ? 0 : 1);
    }
};

 If first and second refer to distinct Integer instances that represent the same int value, this comparison will return false

Applying the == operator to boxed primitives is almost always wrong.


It throws a NullPointerException when evaluating the expression (i == 42). The problem is that i is an Integer, not an int, and like all object reference fields, its initial 

value is null. 


In nearly every case when you mix primitives and boxed primitives in a single operation, the boxed primitive is auto unboxed, and this case is no exception. If a null 

object reference is auto-unboxed,you get a NullPointerException.


and the variable is repeatedly boxed and unboxed, causing the observed performance degradation.


So when should you use boxed primitives? 

The first is as elements, keys, and values in collections. 

Finally, you must use boxed primitives when making reflective method invocations.


 Autoboxing reduces the verbosity, but not the danger, of using boxed primitives. 


Item 50: Avoid strings where other types are more appropriate


Strings are poor substitutes for other value types. 

Strings are poor substitutes for enum types. 

Strings are poor substitutes for aggregate types. 

Strings are poor substitutes for capabilities.


To summarize, avoid the natural tendency to represent objects as strings when better data types exist or can be written. Used inappropriately, strings are more 

cumbersome, less flexible, slower, and more error-prone than other types. Types for which strings are commonly misused include primitive types, enums, and 

aggregate types.


Item 51: Beware the performance of string concatenation


Using the string concatenation operator repeatedly to concatenate n strings requires time quadratic in n. 

To achieve acceptable performance, use a StringBuilder in place of a String


The moral is simple: don’t use the string concatenation operator to combine more than a few strings unless performance is irrelevant. Use StringBuilder’s append 

method instead. Alternatively, use a character array, or process the strings one at a time instead of combining them.


Item 52: Refer to objects by their interfaces


 If appropriate interface types exist, then parameters,return values, variables, and fields should all be declared using interface types. 


If you get into the habit of using interfaces as types, your program will be much more flexible. 


If you depend on any special properties of an implementation, document these requirements where you declare the variable.


It is entirely appropriate to refer to an object by a class rather than an interface if no appropriate interface exists. 


Item 53: Prefer interfaces to reflection


 Given a Class object, you can obtain Constructor,Method, and Field instances representing the constructors, methods, and fields of the class represented by the 

Class instance.


You lose all the benefits of compile-time type checking

The code required to perform reflective access is clumsy and verbose.

Performance suffers

As a rule, objects should not be accessed reflectively in normal applications at runtime.


You can obtain many of the benefits of reflection while incurring few of its costs by using it only in a very limited form.


In summary, reflection is a powerful facility that is required for certain sophisticated system programming tasks, but it has many disadvantages. If you are writing a 

program that has to work with classes unknown at compile time, you should,if at all possible, use reflection only to instantiate objects, and access the objects using 

some interface or superclass that is known at compile time.


Item 54: Use native methods judiciously 

native methods have had three main uses. They provided accessto platform-specific facilities such as registries and file locks. They providedaccess to libraries of 

legacy code, which could in turn provide access to legacydata. Finally, native methods were used to write performance-critical parts ofapplications in native languages 

for improved performance


It is rarely advisable to use native methods for improved performance. In summary, think twice before using native methods. Rarely, if ever, use them for improved 

performance. If you must use native methods to access low-level resources or legacy libraries, use as little native code as possible and test it thoroughly.A single 

bug in the native code can corrupt your entire application.


Item 55: Optimize judiciously

 it is easy to do more harm than good, especially if you optimize prematurely.

Strive to write good programs rather than fast ones

Strive to avoid design decisions that limit performance

Consider the performance consequences of your API design decisions


It is a very bad idea to warp an API to achieve good performance. measure performance before and after each attempted optimization.


To summarize, do not strive to write fast programs—strive to write good ones;speed will follow. Do think about performance issues while you’re designing system sand 

especially while you’re designing APIs, wire-level protocols, and persistent data formats. When you’ve finished building the system, measure its performance. If it’s fast 

enough, you’re done. If not, locate the source of the problems with the aid of a profiler, and go to work optimizing the relevant parts of the system. The first step is to 

examine your choice of algorithms: no amount of low level optimization can make up for a poor choice of algorithm. Repeat this process as necessary, measuring the

 performance after every change, until you’re satisfied.


Item 56: Adhere to generally accepted naming conventions 

Identifier  Type Examples

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

exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow

A well-designed API must not force its clients to use exceptions for ordinary control flow

 If an object is to be accessed concurrently without external synchronization or is subject to externally induced state transitions, you must use a distinguished return value


Item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors


 use checked exceptions for conditions from which the caller can reasonably be expected to recover


There are two kinds of unchecked throwables: runtime exceptions and errors.They are identical in their behavior: both are throwables that needn’t, and generally shouldn’t, 

be caught. If a program throws an unchecked exception or an error,it is generally the case that recovery is impossible and continued execution would do more harm than 

good. If a program does not catch such a throwable, it will cause the current thread to halt with an appropriate error message.


Use runtime exceptions to indicate programming errors


Because checked exceptions generally indicate recoverable conditions, it’s especially important for such exceptions to provide methods that furnish informationthat could 

help the caller to recover


Item 59: Avoid unnecessary use of checked exceptions


 they force the programmer to deal with exceptional conditions,greatly enhancing reliability. That said, overuse of checked exceptions can make anAPI far less pleasant to use


Item 60: Favor the use of standard exceptions

 it makes your API easier to learn and use because it matches established conventions with which programmers are already familiar.

programs using your API are easier to read because they aren’t cluttered with unfamiliar exceptions

fewer exception classes mean a smaller memory footprint and less time spent loading classes


Item 61: Throw exceptions appropriate to the abstraction


higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction

// Exception Translation
try {
    // Use lower-level abstraction to do our bidding
    ...
} catch(LowerLevelException e) {
    throw new HigherLevelException(...);
}

A special form of exception translation called exception chaining is appropriate in cases where the lower-level exception might be helpful to someone debugging the problem 

that caused the higher-level exception.

// Exception Chaining
try {
    ... // Use lower-level abstraction to do our bidding
} catch (LowerLevelException cause) {
    throw new HigherLevelException(cause);
}
The higher-level exception’s constructor passes the cause to a chaining-aware superclass constructor, so it is ultimately passed to one of Throwable’s chaining aware constructors, such as Throwable


Most standard exceptions have chaining-aware constructors. For exceptions that don’t, you can set the cause using Throwable’s initCause method

While exception translation is superior to mindless propagation of exceptions from lower layers, it should not be overused


In summary, if it isn’t feasible to prevent or to handle exceptions from lowerlayers, use exception translation, unless the lower-level method happens to guaranteethat all 

of its exceptions are appropriate to the higher level. Chaining providesthe best of both worlds: it allows you to throw an appropriate higher-levelexception, while capturing 

the underlying cause for failure analysis


Item 62: Document all exceptions thrown by each method

Always declare checked exceptions individually, and document precisely the conditions under which each one is thrown using the Javadoc @throwstag

Use the Javadoc @throws tag to document each unchecked exception thata method can throw, but do not use the throws keyword to include uncheckedexceptions in 

the method declaration

It should be noted that documenting all of the unchecked exceptions that eachmethod can throw is an ideal, not always achievable in the real world

If an exception is thrown by many methods in a class for the same reason,it is acceptable to document the exception in the class’s documentation comment rather than 

documenting it individually for each method

If you fail to document the exceptions that your methods can throw, it will be difficultor impossible for others to make effective use of your classes and interfaces


Item 63: Include failure-capture information in detail messages

 it is critically important that the exception’s toString method return as much information as possible concerning the cause of the failure.

To capture the failure, the detail message of an exception should contain the values of all parameters and fields that “contributed to the exception.”

The detail message of an exception should not be confused with a user-level error message, which must be intelligible to end users. 

One way to ensure that exceptions contain adequate failure-capture information in their detail messages is to require this information in their constructors instead of a 

string detail message.

/**
* Construct an IndexOutOfBoundsException.
*
* @param lowerBound the lowest legal index value.
* @param upperBound the highest legal index value plus one.
* @param index the actual index value.
*/
public IndexOutOfBoundsException(int lowerBound, int upperBound,
int index) {
    // Generate a detail message that captures the failure
    super("Lower bound: " + lowerBound +
        ", Upper bound: " + upperBound +
        ", Index: " + index);
    // Save failure information for programmatic access
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
    this.index = index;
}
 it may be appropriate for an exception to provide accessor methods for its failure-capture information 

Item 64: Strive for failure atomicity

Generally speaking, a failed method invocation should leave the object in the state that it was in prior to the invocation. A method with this property is said to be failure 

atomic.

 The simplest is to design immutable objects (Item 15). If an object is immutable, failure atomicity is free. If an operation fails, it may prevent a new object from getting 

created, but it will never leave an existing object in an inconsistent state, because the state of each object is consistent when it is created and can’t be modified thereafter

For methods that operate on mutable objects, the most common way to achieve failure atomicity is to check parameters for validity before performing the operation

A closely related approach to achieving failure atomicity is to order the computation so that any part that may fail takes place before any part that modifies the object

A third and far less common approach to achieving failure atomicity is to write recovery code that intercepts a failure that occurs in the midst of an operation and causes 

the object to roll back its state to the point before the operation began

A final approach to achieving failure atomicity is to perform the operation on a temporary copy of the object and to replace the contents of the object with the temporary copy

 once the operation is complete

As a rule, errors (as opposed to exceptions)are unrecoverable, and methods need not even attempt to preserve failure atomicity when throwing errors

As a rule, any generated exception that is part of a method’s specification should leave the object in the same state it was in prior to the method invocation.


Item 65: Don’t ignore exceptions

An empty catch block defeats the purpose of exceptions, which is to force you to handle exceptional conditions

 At the very least, the catch block should contain a comment explaining why it is appropriate to ignore the exception

The advice in this item applies equally to checked and unchecked exceptions.Whether an exception represents a predictable exceptional condition or a programming error,

 ignoring it with an empty catch block will result in a program that continues silently in the face of error. The program might then fail at an arbitrary time in the future, at a point 

in the code that bears no apparent relation to the source of the problem. Properly handling an exception can avert failure entirely.Merely letting an exception propagate outward

 can at least cause the program to fail swiftly, preserving information to aid in debugging the failure


Item 66: Synchronize access to shared mutable data

Not only does synchronization prevent a thread from observing an object in an inconsistent state, but it ensures that each thread entering a synchronized method or block 

sees the effects of all previous modifications that were guarded by the same lock.

The language specification guarantees that reading or writing a variable is atomic unless the variable is of type long or double. In other words,reading a variable other than 

a long or double is guaranteed to return a value that was stored into that variable by some thread, even if multiple threads modify the variable concurrently and without

 synchronization

Synchronization is required for reliable communication between threads as well as for mutual exclusion

synchronization has no effect unless both read and write operations are synchronized

While the volatile modifier performs no mutual exclusion, it guarantees that any thread that reads the field will see the most recently written value

The best way to avoid the problems discussed in this item is not to share mutable data. Either share immutable data (Item 15), or don’t share at all. In other words, confine

 mutable data to a single thread.

In summary, when multiple threads share mutable data, each thread that reads or writes the data must perform synchronization. Without synchronization,there is no guarantee

 that one thread’s changes will be visible to another. The penalties for failing to synchronize shared mutable data are liveness and safety failures. These failures are among the

 most difficult to debug. They can be intermittent and timing-dependent, and program behavior can vary radically from one VM to another. If you need only inter-thread

 communication, and not mutual exclusion, the volatile modifier is an acceptable form of synchronization, but it can be tricky to use correctly


Item 67: Avoid excessive synchronization

To avoid liveness and safety failures, never cede control to the client within a synchronized method or block. In other words, inside a synchronized region, do not invoke a 

method that is designed to be overridden, or one provided by a client in the form of a function object 

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.Another hidden cost of over synchronization is that it can limit the VM’s ability to optimize code execution

You should make a mutable class thread-safe (Item 70) if it is intended for concurrent use and you can achieve significantly higher concurrency by synchronizing internally than

 you could by locking the entire object externally

If you do synchronize your class internally, you can use various techniques to achieve high concurrency, such as lock splitting, lock striping, and nonblocking concurrency control

If a method modifies a static field, you must synchronize access to this field,even if the method is typically used only by a single thread

In summary, to avoid deadlock and data corruption, never call an alien method from within a synchronized region. More generally, try to limit the amount of work that you do from

 within synchronized regions. When you are designing a mutable class, think about whether it should do its own synchronization. In the modern multicore era, it is more important

 than ever not to synchronize excessively.Synchronize your class internally only if there is a good reason to do so,and document your decision clearly 


Item 68: Prefer executors and tasks to threads


Item 69: Prefer concurrency utilities to wait and notify

Given the difficulty of using wait and notify correctly, you should use the higher-level concurrency utilities instead

The higher-level utilities in java.util.concurrent fall into three categories:the Executor Framework, which was covered only briefly in Item 68; concurrent collections; and

 synchronizers

 it is impossible to exclude concurrent activity from a concurrent collection; locking it will have no effect but to slow the program

Unless you have a compelling reason to do otherwise, use ConcurrentHashMap in preference to Collections.synchronizedMap or Hashtable. Simply replacing old-style

 synchronized maps with concurrent maps can dramatically increase the performance of concurrent applications. More generally,use concurrent collections in preference to

externally synchronized collections.

Synchronizers are objects that enable threads to wait for one another, allowing them to coordinate their activities. The most commonly used synchronizers are CountDown

-Latch and Semaphore. Less commonly used are CyclicBarrier and Exchanger

Countdown latches are single-use barriers that allow one or more threads to wait for one or more other threads to do something. The sole constructor for CountDownLatch 

takes an int that is the number of times the countDown method must be invoked on the latch before all waiting threads are allowed to proceed.

The executor that is passed to the time method must allow for the creation of at least as many threads as the given concurrency level, or the test will never complete. This is

 known as a thread starvation deadlock

For interval timing, always use System.nanoTime in preference to System.currentTimeMillis. System.nanoTime is both more accurate and more precise, and it is not affected

by adjustments to the system’s real-time clock

The wait method is used to make a thread wait for some condition. It must be invoked inside a synchronized region that locks the object on which it is invoked

Always use the wait loop idiom to invoke the wait method; never invoke it outside of a loop.

It is often said that you should always use notifyAll. This is reasonable, conservative advice

using notifyAll in place of notify protects against accidental or malicious waits by an unrelated thread

In summary, using wait and notify directly is like programming in “concurrency assembly language,” as compared to the higher-level language provided by java.util.concurrent.

There is seldom, if ever, a reason to use wait and notify in new code. If you maintain code that uses wait and notify, make sure that it always invokes wait from within a while loop

using the standard idiom.The notifyAll method should generally be used in preference to notify. If notify is used, great care must be taken to ensure liveness.


Item 70: Document thread safety

 The presence of the synchronized modifier in a method declaration is an implementation detail, not a part of its exportedAPI. It does not reliably indicate that a method is thread-

safe

To enable safe concurrent use, a class must clearly document what level of thread safety it supports


immutable—Instances of this class appear constant. No external synchronization is necessary. Examples include String, Long, and BigInteger

unconditionally thread-safe—Instances of this class are mutable, but the class has sufficient internal synchronization that its instances can be used concurrently without the need

 for any external synchronization. Examples include Random and ConcurrentHashMap.

conditionally thread-safe—Like unconditionally thread-safe, except that some methods require external synchronization for safe concurrent use.Examples include the collections

 returned by the Collections.synchronized wrappers, whose iterators require external synchronization

• not thread-safe—Instances of this class are mutable. To use them concurrently,clients must surround each method invocation (or invocation sequence)with external synchro-

nization of the clients’ choosing. Examples include the general-purpose collection implementations, such as ArrayList and HashMap

thread-hostile—This class is not safe for concurrent use even if all method invocations are surrounded by external synchronization. Thread hostility usually results from modifying

 static data without synchronization. No one writes a thread-hostile class on purpose; such classes result from the failure to consider concurrency. Luckily, there are very few

 thread-hostile classes or methods in the Java libraries. The System.runFinalizersOnExit method is thread-hostile and has been deprecated

// Private lock object idiom - thwarts denial-of-service attack
private final Object lock = new Object();
public void foo() {
    synchronized(lock) {
        ...
    }
}
Because the private lock object is inaccessible to clients of the class, it is impossible for them to interfere with the object’s synchronization. In effect, we are applying the advice

 of Item 13 by encapsulating the lock object within the object it synchronizes

Note that the lock field is declared final. This prevents you from inadvertently changing its contents, which could result in catastrophic unsynchronized access to the containing

 object (Item 66). We are applying the advice of Item 15,by minimizing the mutability of the lock field

To reiterate, the private lock object idiom can be used only on unconditionally thread-safe classes. Conditionally thread-safe classes can’t use this idiom because they must

 document which lock their clients are to acquire when performing certain method invocation sequences.


Item 71: Use lazy initialization judiciously

Lazy initialization is the act of delaying the initialization of a field until its value is needed. If the value is never needed, the field is never initialized. This technique is applicable to

 both static and instance fields. While lazy initialization is primarily an optimization, it can also be used to break harmful circularities in class and instance initialization

That said, lazy initialization has its uses. If a field is accessed only on a fraction of the instances of a class and it is costly to initialize the field, then lazy initialization may be

 worthwhile

Under most circumstances, normal initialization is preferable to lazy initialization

// Normal initialization of an instance field
private final FieldType field = computeFieldValue();
If you use lazy initialization to break an initialization circularity, use a synchronized accessor

// Lazy initialization of instance field - synchronized accessor
private FieldType field;
synchronized FieldType getField() {
    if (field == null)
        field = computeFieldValue();
    return field;
}

If you need to use lazy initialization for performance on a static field, use the lazy initialization holder class idiom

// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
    static final FieldType field = computeFieldValue();
}
static FieldType getField() { return FieldHolder.field; }

The beauty of this idiom is that the getField method is not synchronized and performs only a field access, so lazy initialization adds practically nothing to the cost of access

If you need to use lazy initialization for performance on an instance field,use the double-check idiom

// 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;
}

While you can apply the double-check idiom to static fields as well, there is no reason to do so: the lazy initialization holder class idiom is a better choice

Occasionally, you may need to lazily initialize an instance field that can tolerate repeated initialization. If you find yourself in this situation, you can use a variant of the double-

check idiom that dispenses with the second check

// Single-check idiom - can cause repeated initialization!
private volatile FieldType field;
private FieldType getField() {
    FieldType result = field;
    if (result == null)
        field = result = computeFieldValue();
    return result;
}
In summary, you should initialize most fields normally, not lazily. If you must initialize a field lazily in order to achieve your performance goals, or to break a harmful initialization

 circularity, then use the appropriate lazy initialization technique.For instance fields, it is the double-check idiom; for static fields, the lazy initialization holder class idiom. For

 instance fields that can tolerate repeated initialization,you may also consider the single-check idiom


Item 72: Don’t depend on the thread scheduler

 Any program that relies on the thread scheduler for correctness or performance is likely to be nonportable

Threads should not run if they aren’t doing useful work

 resist the temptation to “fix” the program by putting in calls to Thread.yield

Thread priorities are among the least portable features of the Java platform

In summary, do not depend on the thread scheduler for the correctness of your program. The resulting program will be neither robust nor portable. As a corollary,do not rely on

 Thread.yield or thread priorities. These facilities are merely hints to the scheduler. Thread priorities may be used sparingly to improve the quality of service of an already working

 program, but they should never be used to “fix” a program that barely works


Item 73: Avoid thread groups

To summarize, thread groups don’t provide much in the way of useful functionality,and much of the functionality they do provide is flawed. Thread groups are best viewed as an

 unsuccessful experiment, and you should simply ignore their existence. If you design a class that deals with logical groups of threads, you should probably use thread pool

 executors (Item 68)


Item 74: Implement Serializable judiciously

 While the immediate cost to make a class serializable can be negligible, the long-term costs are often substantial

A major cost of implementing Serializable is that it decreases the flexibility to change a class’s implementation once it has been released

In other words, if you accept the default serialized form, the class’s private and package-private instance fields become part of its exported API, and the practice of minimizing

 access to fields (Item 13) loses its effectiveness as a tool for information hiding

Therefore, you should carefully design a high-quality serialized form that you are willing to live with for the long haul (Items 75, 78)

 Every serializable class has a unique identification number associated with it. If you do not specify this number explicitly by declaring a static final long field named

 serialVersionUID, the system automatically generates it at runtime by applying a complex procedure to the class

A second cost of implementing Serializable is that it increases the likelihood of bugs and security holes.

A third cost of implementing Serializable is that it increases the testing burden associated with releasing a new version of a class

 In other words, you must ensure both that the serialization-deserialization process succeeds and that it results in a faithful replica of the original object

Implementing the Serializable interface is not a decision to be undertaken lightly

 As a rule of thumb, value classes such as Date and BigInteger should implement Serializable, as should most collection classes. Classes representing active entities, such as

 thread pools, should rarely implement Serializable

Classes designed for inheritance (Item 17) should rarely implement Serializable, and interfaces should rarely extend it

// readObjectNoData for stateful extendable serializable classes
private void readObjectNoData() throws InvalidObjectException {
    throw new InvalidObjectException("Stream data required");
}


Therefore, you should consider providing a parameterless constructor on nonserializable classes designed for inheritance

// Nonserializable stateful class allowing serializable subclass
public abstract class AbstractFoo {
    private int x, y; // Our state
    // This enum and field are used to track initialization
    private enum State { NEW, INITIALIZING, INITIALIZED };
    private final AtomicReference<State> init = new AtomicReference<State>(State.NEW);
    public AbstractFoo(int x, int y) { initialize(x, y); }
    // This constructor and the following method allow
    // subclass's readObject method to initialize our state.
    protected AbstractFoo() { }
    protected final void initialize(int x, int y) {
        if (!init.compareAndSet(State.NEW, State.INITIALIZING))
            throw new IllegalStateException("Already initialized");
        this.x = x;
        this.y = y;
        ... // Do anything else the original constructor did
        init.set(State.INITIALIZED);
    }
    // These methods provide access to internal state so it can
    // be manually serialized by subclass's writeObject method.
    protected final int getX() { checkInit(); return x; }
    protected final int getY() { checkInit(); return y; }
    // Must call from all public and protected instance methods
    private void checkInit() {
        if (init.get() != State.INITIALIZED)
            throw new IllegalStateException("Uninitialized");
    }
    ... // Remainder omitted
}

Inner classes (Item 22) should not implement Serializable.

Therefore, the default serialized form of an inner class is illdefined.

To summarize, the ease of implementing Serializable is specious. Unless a class is to be thrown away after a short period of use, implementing Serializableis a serious

 commitment that should be made with care. Extra caution is warranted if a class is designed for inheritance. For such classes, an intermediate design point between

 implementing Serializable and prohibiting it in subclasses is to provide an accessible parameterless constructor. This design point permits, but does not require, subclasses

 to implement Serializable


Item 75: Consider using a custom serialized form

Do not accept the default serialized form without first considering whether it is appropriate.  Generally speaking, you should accept the default serialized form only if it is largely

 identical to the encoding that you would choose if you were designing a custom serialized form

The default serialized form is likely to be appropriate if an object’s physical representation is identical to its logical content.

Even if you decide that the default serialized form is appropriate, you often must provide a readObject method to ensure invariants and security.

Using the default serialized form when an object’s physical representation differs substantially from its logical data content has four disadvantages:

• It permanently ties the exported API to the current internal representation.

• It can consume excessive space.

• It can consume excessive time.

• It can cause stack overflows.

// StringList with a reasonable custom serialized form
public final class StringList implements Serializable {
    private transient int size = 0;
    private transient Entry head = null;
    // No longer Serializable!
    private static class Entry {
        String data;
        Entry next;
        Entry previous;
    }
    // Appends the specified string to the list
    public final void add(String s) { ... }
    /**
    * Serialize this {@code StringList} instance.
    *
    * @serialData The size of the list (the number of strings
    * it contains) is emitted ({@code int}), followed by all of
    * its elements (each a {@code String}), in the proper
    * sequence.
    */
    private void writeObject(ObjectOutputStream s)
        throws IOException {
        s.defaultWriteObject();
        s.writeInt(size);
        // Write out all elements in the proper order.
        for (Entry e = head; e != null; e = e.next)
             s.writeObject(e.data);
    }
    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        int numElements = s.readInt();
        // Read in all elements and insert them in list
        for (int i = 0; i < numElements; i++)
            add((String) s.readObject());
        }
        ... // Remainder omitted
    }
If all instance fields are transient, it is technically permissible to dispense with invoking defaultWriteObject and defaultReadObject, but it is not recommended. 

Whether or not you use the default serialized form, every instance field that is not labeled transient will be serialized when the defaultWriteObject method is invoked. 

Before deciding to make a field nontransient,convince yourself that its value is part of the logical state of the object. If you use a custom serialized form, most or all of the instance

fields should be labeled transient, as in the StringList example shown above.

If you are using the default serialized form and you have labeled one or more fields transient, remember that these fields will be initialized to their default values when an instance

is deserialized: null for object reference fields, zero for numeric primitive fields, and false for boolean fields [JLS, 4.12.5]. If these values are unacceptable for any transient fields,

you must provide a readObjectmethod that invokes the defaultReadObject method and then restores transient fields to acceptable values (Item 76). Alternatively, these fields can

be lazily initialized the first time they are used (Item 71).

Whether or not you use the default serialized form, you must impose any synchronization on object serialization that you would impose on any other method that reads the entire

state of the object.

Regardless of what serialized form you choose, declare an explicit serial version UID in every serializable class you write.

Declaring a serial version UID is simple. Just add this line to your class:
private static final long serialVersionUID = randomLongValue ;

To summarize, when you have decided that a class should be serializable(Item 74), think hard about what the serialized form should be. Use the default serialized form only if it is

a reasonable description of the logical state of the object; otherwise design a custom serialized form that aptly describes the object.You should allocate as much time to designing

the serialized form of a class as you allocate to designing its exported methods (Item 40). Just as you cannot eliminate exported methods from future versions, you cannot

eliminate fields from the serialized form; they must be preserved forever to ensure serialization compatibility.Choosing the wrong serialized form can have a permanent, negative

impact on the complexity and performance of a class.


Item 76: Write readObject methods defensively

The problem is that the readObject method is effectively another public constructor,and it demands all of the same care as any other constructor.

Loosely speaking, readObject is a constructor that takes a byte stream as its sole parameter. In normal use, the byte stream is generated by serializing a normally constructed

 instance. 

When an object is deserialized, it is critical to defensively copy any field containing an object reference that a client must not possess. 

Here is a simple litmus test for deciding whether the default readObject method is acceptable for a class: would you feel comfortable adding a public constructor that took as

 parameters the values for each nontransient field in the object and stored the values in the fields with no validation whatsoever? If not, you must provide a readObject method,

 and it must perform all the validity checking and defensive copying that would be required of a constructor. Alternatively, you can use the serialization proxy pattern (Item 78).

Here, in summary form, are the guidelines for writing a bulletproof readObject method:

• For classes with object reference fields that must remain private, defensively copy each object in such a field. Mutable components of immutable classes fall into this category.

• Check any invariants and throw an InvalidObjectException if a check fails.The checks should follow any defensive copying.

• If an entire object graph must be validated after it is deserialized, use theObjectInputValidation interface [JavaSE6, Serialization].

• Do not invoke any overridable methods in the class, directly or indirectly.











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章