Effective Java 3rd

Creating and Destroying Object

Consider static factory methods instead of constructors

advantage

1.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.->static factory methods for an interface named Type were put in a noninstantiable companion class named Types.(java.util.Collection and java.util.Collections) The returned objects are all nonpublic.
As of Java 8, it`s necessary to put the bulk of the implementation code behind these static methods in a separate package-private class.
Java 9 allows private static methods, but static fields and static member classes are still required to be public.
4.the class of the returned object can vary from call to call as a function of the input parameters.
In the OpenJDK implementation, they return an instance of one of two subclasses, depending on the size of the underlying enum type: if it has sixty-four or fewer elements, as most enum types do, the static factories return a RegularEnumSet instance, which is backed by a single long; if the enum type has sixty-five or more elements, the factories return a JumboEnumSet instance, backed by a long array.
5.the class of the returned object need not exist when the class containing the method is written.

disadvantage

1.classes without public or protected constructors cannot be subclassed.
2.they are hard for programmers to find.

Consider a builder when faced with many constructor parameters

// Builder Pattern
public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;
    public static class Builder {
        // Required parameters
        private final int servingSize;
        private final int servings;
        // Optional parameters - initialized to default values
        private int calories      = 0;
        private int fat           = 0;
        private int sodium        = 0;
        private int carbohydrate  = 0;
        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings    = servings;
        } 
        public Builder calories(int val)
            { calories = val;      return this; }
        public Builder fat(int val)
            { fat = val;           return this; }
        public Builder sodium(int val)
            { sodium = val;        return this; }
        public Builder carbohydrate(int val)
            { carbohydrate = val;  return this; }
        public NutritionFacts build() {
            return new NutritionFacts(this);
        } 
    } 
    private NutritionFacts(Builder builder) {
        servingSize  = builder.servingSize;
        servings     = builder.servings;
        calories     = builder.calories;
        fat          = builder.fat;
        sodium       = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
}

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
           .calories(100).sodium(35).carbohydrate(27).build();
public abstract class Pizza {
    public enum Topping { HAM, MUSHROOM, ONION, PEPPER, SAUSAGE }
    final Set<Topping> toppings; 
    
    abstract static class Builder<T extends Builder<T>> {
        EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class); 
        public T addTopping(Topping topping) {
            toppings.add(Objects.requireNonNull(topping));
            return self();
        }
        abstract Pizza build();
        // Subclasses must override this method to return "this"
        protected abstract T self();
    }
    Pizza(Builder<?> builder) {
        toppings = builder.toppings.clone(); // See Item 50
    }
} 

public class NyPizza extends Pizza {
    public enum Size { SMALL, MEDIUM, LARGE }
    private final Size size;
    
    public static class Builder extends Pizza.Builder<Builder> {
        private final Size size;
        public Builder(Size size) {
            this.size = Objects.requireNonNull(size);
        }
        @Override 
        public NyPizza build() {
            return new NyPizza(this);
        }
        @Override 
        protected Builder self() { return this; }
    }
        private NyPizza(Builder builder) {
            super(builder);
            size = builder.size;
        }
}
public class Calzone extends Pizza {
    private final boolean sauceInside;
    public static class Builder extends Pizza.Builder<Builder> {
        private boolean sauceInside = false; // Default
        public Builder sauceInside() {
            sauceInside = true;
            return this;
        }
        @Override
        public Calzone build() {
            return new Calzone(this);
        }
        @Override
        protected Builder self() { return this; }
    }
    private Calzone(Builder builder) {
        super(builder);
        sauceInside = builder.sauceInside;
    }
} 

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

Singletons typically represent either a stateless object or a system component that is intrinsically unique.

Method of Singleton:

  1. public field approach
    it clear that the class is a singleton.
    it’s simpler
  2. static factory approach
    it gives you the flexibility to change your mind about whether the class is a singleton without changing its API.
    you can write a generic singleton factory if your application requires it
    a method reference can be used as a supplier
  3. declare a single-element enum
    can against serializable.
    a single-element enum type is often the best way to implement a singleton.
    Note that you can’t use this approach if your singleton must extend a superclass other than Enum

Enforce noninstantiability with a private constructor

Util class should be noninstantiability

Prefer dependency injection to hardwiring resources

It preserves immutability (Item 17), so multiple clients can share dependent objects (assuming the clients desire the same underlying resources).
Dependency injection is equally applicable to constructors, static factories (Item 1), and builders (Item 2).
do not use a singleton or static utility class to implement a class that depends on one or more underlying resources whose behavior affects that of the class, and do not have the class create these resources directly.

Mosaic create(Supplier<? extends Tile> tileFactory) { ... }

Avoid creating unnecessary objects

String s = new String("bikini"); // DON'T DO THIS! 

While String.matches is the easiest way to check if a string matches a regular expression, it’s not suitable for repeated use in performance-critical situations. The problem is that it internally creates a Pattern instance for the regular expression and uses it only once, after which it becomes eligible for garbage collection.
Creating a Pattern instance is expensive because it requires compiling the regular expression into a finite state machine.

As is often the case with lazy initialization, it would compli- cate the implementation with no measurable performance improvement

 // Hideously slow! Can you spot the object creation?
private static long sum() {
    Long sum = 0L; should-> long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++)
        sum += i;
    return sum; 
} 

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

Avoiding object creation by maintaining your own object pool is a bad idea unless the objects in the pool are extremely heavyweight.

Eliminate obsolete object references

This occurs naturally if you define each variable in the narrowest possible scope

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

  1. make obsolete object null
  2. use WeakHashMap and EG->LinkedHashMap.removeEldestEntry

where will occur

  1. a class managers its own memory
  2. caches
  3. listeners and callbacks

Avoid finalizers and cleaners

Cleaners are a bit better than finalizers in this regard because class authors have control over their own cleaner threads, but cleaners still run in the background, under the control of the garbage collector, so there can be no guarantee of prompt cleaning.

Normally, an uncaught exception will terminate the thread and print a stack trace, but not if it occurs in a finalizer—it won’t even print a warning. Cleaners do not have this problem because a library using a cleaner has control over its thread.

To protect nonfinal classes from finalizer attacks, write a final finalize method that does nothing.

So what should you do instead of writing a finalizer or cleaner for a class whose objects encapsulate resources that require termination, such as files or threads? Just have your class implement AutoCloseable, and require its clients to invoke the close method on each instance when it is no longer needed, typically using try-with-resources to ensure termination even in the face of exceptions (Item 9).

==JAVA9 Cleaner will be read next time==

Prefer try-with-resources to try-finally

under try-finally circumstances, the second exception will completely obliterate the first one

implements AutoCloseable interface

These suppressed exceptions are not merely discarded; they are printed in the stack trace with a notation saying that they were suppressed.

You can also access them programmatically with the getSuppressed method, which was added to Throwable in Java 7.

Methods Common to All Objects

Obey the general contract when overriding equals

The easiest way to avoid problems is not to override the equals method, in which case each instance of the class is equal only to itself. This is the right thing to do if any of the following conditions apply:

  • Each instance of the class is inherently unique.
  • There is no need for the class to provide 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.If you are extremely risk-averse, you can over- ride the equals method to ensure that it isn’t invoked accidentally:
@Override public boolean equals(Object o) {
    throw new AssertionError(); // Method is never called.
}

The Contract of overriding equals method is:
• Reflexive:For any non-null reference value x, x.equals(x)must return true.
• Symmetric:For any non-null reference values x and y, x.equals(y)must return true if and only if y.equals(x) returns true.
• Transitive:For any non-null reference values x, y, z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must return true.
• Consistent: For any non-null reference values x and y, multiple invocations of x.equals(y) must consistently return true or consistently return false, provided no information used in equals comparisons is modified.
• For any non-null reference value x, x.equals(null) must return false.

The equals implementation for Timestamp does violate symmetry and can cause erratic behavior if Timestamp and Date objects are used in the same collection or are otherwise intermixed.

equals methods should perform only deterministic computations on memory-resident objects.

the instanceof operator is specified to return false if its first operand is null, regardless of what type appears in the second operand

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

  1. Use the == operator to check if the argument is a reference to this object.
  2. Use the instanceof operator to check if the argument has the correct type. If not, return false.
  3. Cast the argument to the correct type.
  4. For each “significant” field in the class, check if that field of the argument matches the corresponding field of this object.

Here are a few final caveats:

  • When you are finished writing your equals method, ask yourself three questions: Is it symmetric? Is it transitive? Is it consistent?
  • Always override hashCode when you override equals.
  • Don’t try to be too clever.
  • Don’t substitute another type for Object in the equals declaration.

An excellent alternative to writing and testing these methods manually is to use Google’s open source AutoValue framework, which automatically generates these methods for you, triggered by a single annotation on the class .

Always override hashCode when you override equals

Even if the two instances happen to hash to the same bucket, the get method will almost certainly return null, because HashMap has an optimization that caches the hash code associated with each entry and doesn’t bother checking for object equality if the hash codes don’t match.

Luckily it’s not too hard to achieve a fair approximation. Here is a simple recipe:

  1. Declare an int variable named result, and initialize it to the hash code c for the first significant field in your object, as computed in step 2.a. (Recall from Item 10 that a significant field is a field that affects equals comparisons.)

  2. For every remaining significant field f in your object, do the following:

    1. Compute an int hash code c for the field:
      1. If the field is of a primitive type, compute Type.hashCode(f), where Type is the boxed primitive class corresponding to f’ s type.
      2. 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, use 0 (or some other constant, but 0 is traditional).
      3. If the field is an array, treat it as if each significant element were a separate field. That is, compute a hash code for each significant element by applying these rules recursively, and combine the values per step 2.b. If the array has no significant elements, use a constant, preferably not 0. If all elements are significant, use Arrays.hashCode.
    2. Combine the hash code c computed in step 2.a into result as follows: result = 31 * result + c;
  3. Return result.

You must exclude any fields that are not used in equals com- parisons

A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance on some architectures: 31 * i == (i << 5) - i. Modern VMs do this sort of optimi- zation automatically.

If you have a bona fide need for hash functions less likely to produce collisions, see Guava’s com.google.common.hash.Hashing [Guava].

This style of hash function is recommended for use only in situations where performance is not critical.

@Override public int hashCode() {
    return Objects.hash(lineNum, prefix, areaCode);
} 

If a class is immutable and the cost of computing the hash code is significant, you might consider caching the hash code in the object rather than recalculating it each time it is requested.

If you believe that most objects of this type will be used as hash keys, then you should calculate the hash code when the instance is created.

Don’t provide a detailed specification for the value returned by hashCode, so clients can’t reasonably depend on it; this gives you the flexibility to change it.

Always override toString

The toString method is automatically invoked when an object is passed to println, printf, the string concatenation operator, or assert, or is printed by a debugger.

If you specify the format, it’s usually a good idea to provide a matching static factory or constructor so programmers can easily translate back and forth between the object and its string representation.

Whether or not you specify the format, provide programmatic access to the information contained in the value returned by toString.

Override clone judiciously

Creates and returns a copy of this object. The precise meaning of “copy” may depend on the class of the object. The general intent is that, for any object x, the expression

x.clone() != x 

will be true, and the expression

x.clone().getClass() == x.getClass()

will be true, but these are not absolute requirements. While it is typically the
case that

x.clone().equals(x)

will be true, this is not an absolute requirement.
By convention, the object returned by this method should be obtained by calling super.clone. If a class and all of its superclasses (except Object) obey this convention, it will be the case that

x.clone().getClass() == x.getClass(). 

By convention, the returned object should be independent of the object being cloned. To achieve this independence, it may be necessary to modify one or more fields of the object returned by super.clone before returning it.

covariant return types : An overriding method’s return type can be a subclass of the overridden method’s return type

So what does Cloneable do, given that it contains no methods? It determines the behavior of Object’s protected clone implementation: if a class implements Cloneable, Object’s clone method returns a field-by-field copy of the object; otherwise it throws CloneNotSupportedException. This is a highly atypical use of interfaces and not one to be emulated. Normally, implementing an interface says something about what a class can do for its clients. In this case, it modifies the behavior of a protected method on a superclass.

the Cloneable architecture is incompatible with normal use of final fields referring to mutable objects

invoking itself recursively will occus a stack overflow

Object’s clone method is declared to throw CloneNotSupportedException, but overriding methods need not. Public clone methods should omit the throws clause, as methods that don’t throw checked exceptions are easier to use (Item 71).

If you write a thread-safe class that implements Cloneable, remember that its clone method must be properly syn- chronized, just like any other method (Item 78).

A final approach to cloning complex mutable objects is to call super.clone, set all of the fields in the resulting object to their initial state, and then call higher- level methods to regenerate the state of the original object.

Alternatively, you may choose not to implement a working clone method, and to prevent subclasses from implementing one, by providing the following degenerate clone implementation:

// clone method for extendable class not supporting Cloneable
@Override
protected final Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
}

To recap, all classes that implement Cloneable should override clone with a public method whose return type is the class itself. This method should first call super.clone, then fix any fields that need fixing. Typically, this means copying any mutable objects that comprise the internal “deep structure” of the object and replacing the clone’s references to these objects with references to their copies.While these internal copies can usually be made by calling clone recursively, this is not always the best approach. If the class contains only primitive fields or refer- ences to immutable objects, then it is likely the case that no fields need to be fixed. There are exceptions to this rule. For example, a field representing a serial number or other unique ID will need to be fixed even if it is primitive or immutable.

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

As a rule, copy functionality is best provided by constructors or factories. A notable exception to this rule is arrays, which are best copied with the clone method.

Consider implementing Comparable

• The implementor must ensure that 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 required, that (x.compareTo(y) == 0) == (x.equals(y)). Generally speaking, any class that implements the Comparable 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.”
This is because the general contracts for these interfaces are defined in terms of the equals method, but sorted collections use the equality test imposed by compareTo in place of equals. It is not a catastrophe if this happens, but it’s something to be aware of.

the BigDecimal class, whose compareTo method is inconsistent with equals.

In a compareTo method, fields are compared for order rather than equality. To compare object reference fields, invoke the compareTo method recursively. If a field does not implement Comparable or you need a nonstandard ordering, use a Comparator instead. You can write your own comparator or use an existing one, as in this compareTo method for CaseInsensitiveString in Item 10:

Prior editions of this book recommended that compareTo methods compare integral primitive fields using the relational operators < and >, and floating point primitive fields using the static methods Double.compare and Float.compare. In Java 7, static compare methods were added to all of Java’s boxed primitive classes. Use of the relational operators < and > in compareTo methods is verbose and error-prone and no longer recommended.

In Java 8, the Comparator interface was outfitted with a set of comparator construction methods, which enable fluent construction of comparators. These comparators can then be used to implement a compareTo method, as required by the Comparable interface. Many programmers prefer the conciseness of this approach, though it does come at a modest performance cost

Comparator provides a way for you to provide custom comparison logic for types that you have no control over.

Summary Of Chapter 2 And 3

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343