Effective Java 读书笔记1

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

    静态工厂方法的好处:
    1> 有名称 -> 可以根据静态工厂方法的类型构造不同的名称,更易于阅读
    2> 不必在每次调用它们的时候都创建一个新对象 ->  单例、享元模式
    3> 可以返回原返回类型的任何子类型的对象 -> EnumSet
    4> 简化代码 -> eg, HashMap.newInstance() 替代 new HashMap()
    缺点:
    1> 类如果不含公有的或者受保护的构造器,就不能被子类化
    2> 与其他的静态方法实际上没有区别。-> 遵守标准的命名习惯: valueOf / of / getInstance / newInstance / getType / newType



2> 遇到多个构造器参数时要考虑用构建器
    e.g
package com.chal.builder1;

/**
 * @author Chal Nan 
 */
public class NutritionFacts {
  private int arg1;
  private int arg2;
  private int arg3;

  public static class NutritionBuilder implements Builder<NutritionFacts> {
    private int arg1;
    private int arg2;
    private int arg3;

    public NutritionBuilder setArg1(int arg1) {
      this.arg1 = arg1;
      return this;
    }

    public NutritionBuilder setArg2(int arg2) {
      this.arg2 = arg2;
      return this;
    }

    public NutritionBuilder setArg3(int arg3) {
      this.arg3 = arg3;
      return this;
    }

    @Override
    public NutritionFacts build() {
      return new NutritionFacts(this);
    }
  }

  public NutritionFacts(NutritionBuilder builder) {
    this.arg1 = builder.arg1;
    this.arg2 = builder.arg2;
    this.arg3 = builder.arg3;
  }

  @Override
  public String toString() {
    return "NutritionFacts{" +
        "arg1=" + arg1 +
        ", arg2=" + arg2 +
        ", arg3=" + arg3 +
        '}';
  }

  public static void main(String[] args) {
    NutritionFacts nutritionFacts = new NutritionBuilder().setArg1(1).setArg2(2).setArg3(3).build();
    System.out.println(nutritionFacts);
  }
}
package com.chal.builder1;

/**
 * Created by Chal Nan on 6/30/14.
 */
public interface Builder<T> {
  T build();
}


3> 用私有构造器或者枚举类型强化Singleton属性
     1> 公有静态成员是个final域
package com.chal.singleton;


/**
 * Created by Chal Nan on 7/20/14.
 * SuccessFactors.
 */
public class Singleton1 {
  public static final Singleton1 INSTANCE = new Singleton1();

  private Singleton1() {
  }
}
Note: 享有特权的客户端可以借助AccessibleObject.setAccessible 方法通过反射机制调用私有构造器。


2> 公有的成员是个静态工厂方法
package com.chal.singleton;

/**
 * Created by Chal Nan on 7/20/14.
 * SuccessFactors.
 */
public class Singleton2 {
  private static final Singleton2 INSTANCE = new Singleton2();

  private Singleton2() {

  }

  public Singleton2 getInstance() {
    return INSTANCE;
  }
}
3> 编写一个包含单个元素的枚举类型
package com.chal.singleton;

/**
 * Created by Chal Nan on 7/20/14.
 * SuccessFactors.
 */
public enum Singleton3 {
  INSTANCE;
  
  // method...
}
单元素的枚举类型已经成为实现Singleton的最佳方法。


4> 通过私有构造器强化不可实例化的能力

5> 避免创建不必要的对象
e.g
String  s = new String("test")  // DON'T DO THIS !

1> 要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱
e.g
/**
 * Created by Chal Nan on 6/30/14.
 */
public class Test {
  public static void main(String[] args) {
    Long sum = 0L;
    for (long i = 0; i < Integer.MAX_VALUE; i++) {
      sum += i;
    }
    System.out.println(sum);
  }

}

这段代码中会无意识中创建大量多余的Long实例,将sum的声明从Long改成long会是性能得到提升。


6> 消除过期的对象引用
长生命周期的对象持有短生命周期的对象引用会造成内存泄露。

1> 内存自己管理的数据对象,一旦数组元素变成了非活动部分的一分部,程序员需要手动的置空这些数据元素
2> 缓存 -> WeakHashMap: 当除了自身有对key的引用外,此key没有被其他引用持有,那么map会自动丢弃这个 Map.Entry
3> 监听器和其他回调


7> 避免使用终结(finalize)方法
1> finalize方法通常情况下是不可预测的,也是很危险的,一般情况下避免使用该方法。
2> 一般情况下,finalize方法的执行时间不确定,也不能保证该方法一定会被执行,因此不能当做析构方法来使用
3> 使用finalize方法有一个非常严重的性能损失
4> 除非是作为安全网,或者是为了终止非关键的本地资源,否则请不要使用终结方法。
5> 若使用了终结方法,就要记得调用super.finalize。

8> 覆盖equals时请遵守通用约定
equals方法需要实现等价关系:
1> 自反性, x.equals(x) == true (x != null)
2> 对称性, x.equals(y) == true, y.equals(x) == true
3> 传递性, x.equals(y) == true, y. equals(z) == true, x.equals(z) == true
4> 一致性, 只要对象信息没有被修改,多次调用 x.equals(y)就会一致地返回true,或者false。
x.equals(null) == false


9> 覆盖equals时总要覆盖hashCode方法
1> 在每个覆盖了 equals方法的类中,也必须覆盖hashCode方法
2> 两个相等的对象(x.equals(y) == true),这个两个对象的hashCode必须要相等。(x.hashCode() == y.hashCode())
3> 两个hashCode相等的对象,不一定是相等的两个对象。但不同的对象能产生不同的hashCode,有可能提高hash table的性能


10> 始终覆盖toString方法


11> 谨慎地覆盖clone
1> 浅拷贝和深拷贝: http://blog.csdn.net/bluescorpio/article/details/4322682 
2> 实现对象拷贝的好方法是提供一个拷贝构造器或者拷贝工厂。


12> 考虑实现Comparable接口
1> 考虑equals方法的实现原则。
2> compareTo() 方法的返回类型是int,需要确保该方法的返回值不会溢出。(Integer.MIN_VALUE)


13> 使类和成员的可访问性最小化
1> 类具有公有的静态final数据域,或者返回这种域的访问方法,这几乎总是错误的。因为客户端可以修改数组中的内容。
 e.g 使用Collections.unmodifiableList()方法把不可变数组变成不可变列表。


14> 在公有类中使用访问方法而非公有域
1> 公有类不应该直接暴露数据域,而是提供getter/setter方法。
正确的例子:
public class Test {
  private int arg1;
  private String arg2;

  public int getArg1() {
    return arg1;
  }

  public void setArg1(int arg1) {
    this.arg1 = arg1;
  }

  public String getArg2() {
    return arg2;
  }

  public void setArg2(String arg2) {
    this.arg2 = arg2;
  }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值