zoukankan      html  css  js  c++  java
  • 《Effective Java》读书笔记一(创建与销毁对象)

    No1 考虑用静态工厂方法代替构造器

    静态工厂方法优势:

    1. 它们有名称,阅读性增强,如:BigInteger.probablePrime;
    2. 不必每次调用它们的时候都创建一个新对象;
    3. 它们可以返回原返回类型的任何子类型的对象;
    4. 在创建参数化类型实例的时候,它们使代码变得更加简洁。

    静态工厂方法缺点:

    1. 类如果不含公有的或者受保护的构造器,就不能被子类化;
    2. 它们与其他的静态方法实际上没有任何区别。

    惯用名称:

    • getInstance       返回的实例是通过方法的参数来描述的;
    • newInstance     像getInstance一样,但newInstance能够确保返回的每个实例都与所有其它实例不同。

    No2 遇到多个构造器参数时要考虑用构建器

    2.1多个构造器(缺点:许多参数时,客户端代码难写;不易于阅读);

    // Telescoping constructor pattern - does not scale well! - Pages 11-12
    
    public class NutritionFacts {
        private final int servingSize;   // (mL)            required
        private final int servings;      // (per container) required
        private final int calories;      //                 optional
        private final int fat;           // (g)             optional
        private final int sodium;        // (mg)            optional
        private final int carbohydrate;  // (g)             optional
    
        public NutritionFacts(int servingSize, int servings) {
            this(servingSize, servings, 0);
        }
    
        public NutritionFacts(int servingSize, int servings,
                int calories) {
            this(servingSize, servings, calories, 0);
        }
    
        public NutritionFacts(int servingSize, int servings,
                int calories, int fat) {
            this(servingSize, servings, calories, fat, 0);
        }
    
        public NutritionFacts(int servingSize, int servings,
                int calories, int fat, int sodium) {
            this(servingSize, servings, calories, fat, sodium, 0);
        }
    
        public NutritionFacts(int servingSize, int servings,
               int calories, int fat, int sodium, int carbohydrate) {
            this.servingSize  = servingSize;
            this.servings     = servings;
            this.calories     = calories;
            this.fat          = fat;
            this.sodium       = sodium;
            this.carbohydrate = carbohydrate;
        }
    
        public static void main(String[] args) {
            NutritionFacts cocaCola =
                new NutritionFacts(240, 8, 100, 0, 35, 27);
        }
    }

    2.2 JavaBeans模式(缺点:对象可能处于不一致的状态);

    // JavaBeans Pattern - allows inconsistency, mandates mutability - Pages 12-13
    
    public class NutritionFacts {
        // Parameters initialized to default values (if any)
        private int servingSize  = -1;  // Required; no default value
        private int servings     = -1;  //     "     "     "      "
        private int calories     = 0;
        private int fat          = 0;
        private int sodium       = 0;
        private int carbohydrate = 0;
    
        public NutritionFacts() { }
    
        // Setters
        public void setServingSize(int val)  { servingSize = val; }
        public void setServings(int val)     { servings = val; }
        public void setCalories(int val)     { calories = val; }
        public void setFat(int val)          { fat = val; }
        public void setSodium(int val)       { sodium = val; }
        public void setCarbohydrate(int val) { carbohydrate = val; }
    
        public static void main(String[] args) {
            NutritionFacts cocaCola = new NutritionFacts();
            cocaCola.setServingSize(240);
            cocaCola.setServings(8);
            cocaCola.setCalories(100);
            cocaCola.setSodium(35);
            cocaCola.setCarbohydrate(27);
        }
    }

    2.3 Builder模式(用一个专门的对象来存放参数,形如:new NutritionFacts(Builder builder),所有参数封装在Builder类中)。

    // Builder Pattern - Pages 14-15
    
    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 carbohydrate  = 0;
            private int sodium        = 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 carbohydrate(int val)
                { carbohydrate = val;  return this; }
            public Builder sodium(int val)
                { sodium = 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;
        }
    
        public static void main(String[] args) {
            NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
                calories(100).sodium(35).carbohydrate(27).build();
        }
    }

    No5 避免创建不必要的对象

    5.1 String对象的使用

    String s = new String(“stringetee”);         // DON’T DO THIS
    String s = “stringetee”;   // 正确方式,引用常量池中的对象

    5.2 注意某些方法调用频繁生成对象时,应考虑将这些对象放置到类(对象)的局部变量中。

    不好的代码如下:

    // Creates lots of unnecessary duplicate objects - page 20-21
    import java.util.*;
     
    
    public class Person {
    
        private final Date birthDate;
     
    
        public Person(Date birthDate) {
            // Defensive copy - see Item 39
            this.birthDate = new Date(birthDate.getTime());
        }
     
    
        // Other fields, methods omitted
     
    
        // DON'T DO THIS!
        public boolean isBabyBoomer() {
            // Unnecessary allocation of expensive object
            Calendar gmtCal =
                Calendar.getInstance(TimeZone.getTimeZone("GMT"));
            gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
            Date boomStart = gmtCal.getTime();
            gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
            Date boomEnd = gmtCal.getTime();
    
            return birthDate.compareTo(boomStart) >= 0 &&
                   birthDate.compareTo(boomEnd)   <  0;
        }
    }

     优化后的代码如下:

    // Doesn't creates unnecessary duplicate objects - page 21
    import java.util.*;
     
    
    class Person {
    
        private final Date birthDate;
     
    
        public Person(Date birthDate) {
            // Defensive copy - see Item 39
            this.birthDate = new Date(birthDate.getTime());
        }
     
    
        // Other fields, methods
     
    
        /**
         * The starting and ending dates of the baby boom.
         */
        private static final Date BOOM_START;
        private static final Date BOOM_END;
    
        static {
            Calendar gmtCal =
                Calendar.getInstance(TimeZone.getTimeZone("GMT"));
            gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
            BOOM_START = gmtCal.getTime();
            gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
            BOOM_END = gmtCal.getTime();
        }
     
    
        public boolean isBabyBoomer() {
            return birthDate.compareTo(BOOM_START) >= 0 &&
                   birthDate.compareTo(BOOM_END)   <  0;
        }
    }

    5.3 JDK1.5之后,自动装箱功能可能导致代码BUG。

    如下代码:

    // Hideously slow program! Can you spot the object creation?
    public static void main(String[] args) {
        Long sum = 0L;
    
    for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println(sum); }

    这段程序算出的结果是正确的,但是比实际情况要更慢一些,只因为打错了一个字符。变量sum被声明成Long而不是long。要优先使用基本类型而不是装箱基本类型,要当心无意意识的自动装箱。

    No7 避免使用终结方法

    Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行。

    显式终止方法的典型盒子是InputStream,OutputStream和java.sql.Connection上的close方法。另一个例子是java.util.Timer上的cancel方法,它执行必须的状态改变,使得与Timer实例相关联的该线程温和地终止自己。

    显式的终止方法通常与try-finally结构结合起来使用,以确保及时终止。

  • 相关阅读:
    PHP常量
    jquery中的几种常用总结
    jquery中的ajax
    常用的jquery一些总结
    js验证手机号邮箱号用户名
    PHP优化杂烩
    一个php开发的用于路由器的小功能
    HTML <form>
    window.open
    try&catch
  • 原文地址:https://www.cnblogs.com/nayitian/p/3245426.html
Copyright © 2011-2022 走看看