Chapter02. Creating and Destroyi
aim: when and how to create, when and how to avoid creating, how to ensure they are destroyed in a timely manner, how to manage any cleanup actions that must precede their destruction.
Item1. Consider static factory methods instead of constructors
A class can provide its client with static factory methods instead of public constructors.
public Boolean valueOf(boolean b){
return b ? Boolean.TRUE : Boolean.False;
}
Advantages:
Unlike constructors, they have names.
A static well-chosen method name is easier to use and the resulting client code easier to read;
A class can have only a single Constructor with a given signature, a static factory can return multi different objects with well-chosen method name(to highlight differences) and same method signature.
Unlike constructors, they are not required to create a new object each time they're invoked.
This allows immutable classes to use preconstructed instances or to cache instances as they're constructed, and avoid creating unnecessary duplicate objects(similar to FlyWeight pattern);
The ability to return the same object from repeated invocations allows classes to maintain strict control over what instances exist at any time.【This classes are said to be instance-controlled】【reasons: singleton, noninstantiable, no two equal instances exist-a.equals(b) if and only if a==b】
Unlike constructors, they can return an object of any subtype of their return type.
Interface-based frameworks. Hiding implementation classed in this fashion leads to a very compact API.
[Type 待写]
The class of returned object can vary from call to call as a function of the input parameters.
Any subtype of the declared return type is permissible. The class of the returned object can vary from release to release.
EnumSet, no public constructor only static factories. In OpenJDK, they return an instance of one of two subclasses, depending on the size of the underlying enum type: 64 or fewer elements, return a RegularEnumSet instance, backed by a single long(64 bit); 65 or more elements, return a JumboEnumSet instance, backed by a long array. The existence of these two implementation is invisible to clients. So a future release could add a third or fourth implementation of EnumSet if it proved beneficial for performance. Clients neither know nor care about the class of the object they get back from the factory, they care only that it is some subclass of EnumSet.
The class of the returned object need not exist when the class containing the method is written.
Such flexible static factory method form the basis of service provider frameworks【SPI, like java Database Connectivity API, JDBC】, A service provider framework is a system in which multi service providers implement a service, and the system makes the implementation available to clients, decoupling the clients from the implementation.
There are 3 essential components in a service provider framework: service interface, which represents an implementation【Connection】;provider registration API, which providers use to register implementations【DriverManager.registerDriver】;service access API, which clients use to obtain instances of the service【DriverManager.getConnection】. The service access API is the flexible static factory that forms the basis of the service provider framework.
An optional forth component of a service provider framework is aservice provider interface, which describes a factory object that produce instances of the service interface【Driver】.
Bridge pattern【service access API return a richer service interface to clients than the one furnished by providers.】;Dependency injectionframeworks can be viewed as powerful service providers.
Since Java 6, the platform includes a general-purpose service provider framework, java.util.ServiceLoader, so you needn't and shouldn't write your own.【JDBC not use ServiceLoader, as the former predates the latter】.
Disadvantage
Providing only static factory methods without public or protected constructors cannot be subclassed.
They are hard for programmers to find.
Common names for static factory methods:
from--- type-conversion method: Date d = Date.from(instant);
of--- aggregation method: Set faceCards = EnumSet.of(JACK, QUEEN, KING);
valueOf--- BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
instance or getInstance--- StackWalker luke = StackWalker.getInstace(options);
create or newInstance--- guarantee each call returns a new instance,
Object newArray = Array.newInstance(classObject, arrayLen);
getType--- factory method is in a different class.
FileStore fs = Files.getFileStore(Path);
newType--- factory method is in a different class.
BufferedReader br = Files.newBufferedReader(path);
type--- concise alternative to getType and newType.
List<Complaint> litany = Collections.list(legacyLitany);
Summary
Avoid the reflex to provide public constructors without first considering static factories.
Item 2. Consider a builder when faced with many constructor parameters.
telescoping constructor pattern: provider a constructor with only the required parameters, another with a single optional parameter, a third with two optional parameters, and so on.
The telescoping constructor pattern works, but it is hard to write client code when there are many parameters, and harder still to read it.
JavaBeans pattern, call a parameterless constructor to create the object and then call setter methods to set each required parameter.
A JavaBean may be in an inconsistent state partway through its construction【每次set都改变object的状态】. And the JavaBeans pattern precludes the possibility of making a class immutable.
Builder pattern. Client calls a constructor(or static factory) with all of the required parameters and gets a builder object, then client calls setter-like methods on the builder object to set each optional parameter, finally client falls a parameterless build method to generate the object, which is typically immutable.
The Builder pattern simulates named optional parameters.
The Builder pattern is well suited to class hierarchies.
Builder hierarchy code example
generic type with a recursive type parameter.[待]
simulated self-type idiom.【待】
covariant return typing: A subclass method is declared to return a subtype of the return type declared in the superclass.
advantage
Builders can have multi varargs parameters because each parameter is specified in its own method.
A single builder can be used repeatedly to build multi objects.
disadvantage
In order to create object, you must first create its builder, could be a problem in performance-critical situations.
Builder pattern is verbose, so it should be used only if there are enough parameters.(>=4)
Summary
The Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters.
Item 3: Enforce the singleton property with a private constructor or an enum type
A singleton is simply a class that is instantiated exactly once. Making a class a singleton can make it difficult to test its client.
There are three ways to implement singletons.
public class Elvis{
public static final Elvis INSTANCE = new Elvis();
private Elvis(){}
private Object readResolve(){
return INSTANCE;
}
}
public class Elvis{
private final static Elvis INSTANCE = new Elvis();
private Elvis(){}
public static Elvis getInstance(){
return INSTANCE;
}
private Object readResolve(){
return INSTANCE;
}
}
public enum Elvis{
INSTANCE;
}
To make a singleton class (approach 1, 2) serializable, it is not sufficient to add implements Serializable to its declaration. Need declare all instance fields transient and provide a readResolve method, otherwise each time a serialized instance is deserialized, a new instance will be created.
Summary
A single-element enum type is often the best way to implement a singleton.
Item 4: Enforce noninstantiability with a private constructor
Attempting to enforce noninstantiability by making a class abstract does not work, because the class can be subclassed(the subclass instantiated) and mislead user into thinking the class was designed for inheritance.
A class can be made noninstantiable by including a private constructor.
// Noninstantiable utility class
public class UtilityClass{
// Suppress default constructor for noninstantiablity
private UtilityClass(){
throw new AssertionError();
}
}
As a side effect, this prevent the class from being subclassed.[all constructors must invoke a superclass constructor, explicitly or implicitly]
Item 5: Prefer dependency injection to hardwiring resources
Static utility classes and singletons are inappropriate for classes whose behavior is parameterized by an underlying resource.
Dependency injection: pass the resource into the constructor when creating a new instance.
Dependency injection preserves immutability, so multiple clients can share dependent objects.
代码【待】
Item 6: Avoid creating unnecessary objects
Don't create a new object when you should reuse an existing one.
Prefer Pattern.matcher.matches to Sting.matches because former can cache Pattern when loop multi times.
Autoboxing blurs but does not erase the distinction between primitive and boxed primitive types.
Prefer primitives to boxed primitives, and watch out for unintentional autoboxing.
Creating additional objects to enhance the clarity, simplicity, or power of a program is generally a good thing【the creation and reclamation of small objects whose constructors do little explicit work is cheap, especially on modern JVM implementation】.
Avoiding object creation by maintaining your own object pool is a bad idea unless the objects in the pool are extremely heavyweight.
Item 7: Eliminate obsolete(过时的) object references
An obsolete references is simply a reference that will never be dereferenced(间接引用) again.
Memory leaks(unintentional(无意的) object retentions(残留)) in garbage-collected languages are insidious(隐藏的), If an object reference is retained, not only is that object excluded from garbage collection, but so too are any objects referenced by that object, and so on.
"Obsolete_reference=null" to nulling out obsolete reference.
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. Whenever an element is freed, any object references contained in the element should be nulled out.
Another common source of memory leaks is caches. WeakHashMap
A third common source of memory leaks is listeners and other callbacks.
Item 8: Avoid finalizers and cleaners
Finalizers are unpredictable, often dangerous, and generally unnecessary. You should avoid them.
Cleaners are less dangerous than finalizers, but still unpredictable, slow, and generally unnecessary.
There is no guarantee they'll be executed promptly(立即). Never do anything time-critical in a finalizer or cleaner.
Providing a finalizer for a class can arbitrarily delay reclamation(回收) of its instances.
There is also no guarantee that finalizers or cleaners will run at all. Never depend on a finalizer or cleaner to update persistent state.
An uncaught exception thrown during finalization is ignored, and finalization of that object terminates. Uncaught exception can leave other objects in a corrupt(腐败的) state. An uncaught exception thrown during finalization will not terminate the thread nor print a warning.
There is a severe performance penalty for using finalizers and cleaners. This is primarily because finalizers inhibit(抑制) efficient garbage collection. (执行两次gc)
Finalizers have a serious security problem: they open your class up to finalizer attacks. If an exception is thrown from a constructor or its serialization equivalents---the readObject and readResolve methods, the finalizer of a malicious(恶意的) subclass can run on the partially constructed object that should have "died on the vine." This finalizer can record a reference to the object in a static field, preventing it from being garbage collected. Final class are immune(免疫的) to finalizer attacks. To protect nonfinal classed from finalizer attacks, write a final finalize method that does nothing.
Throwing an exception from a constructor should be sufficient to prevent an object form coming into existence; in the presence of finalizers, it is not.
Have your class implement AutoCloseable.
Usages
To act as a safety net in case the owner of a resource neglects(疏忽) to call its close method.【FileInputStream, FileOutputStream, ThreadPoolExecutor, java.sql.Connection have finalizers that serve as safety nets】
Native peers.【待】
Cleaner code[待]
Summary
Don't use cleaners, or in releases prior to Java 9, finalizers, except as a safety net or to terminate noncritical native resources. Even then, beware the indeterminacy and performance consequences.
Item 9: Prefer try-with-resources to try-finally
try-finally: exception in finally will completely obliterates the previous exception[result to debug hardly].
try-with-resources: resource implement the AutoCloseable interface.shorter and more readable, and provide far better diagnostics[latter exception is suppressed in favor of the former, and these suppressed are printed in the stack trace with a notation saying the were supressed].