第一章节
1)利用静态工厂方法代替构造器
//com.insanus.OldNews.java
package com.insanus;
public class OldNews {
//private static OldNews object = null;
private OldNews() {
}
public static OldNews createOldNews() {
//if (object != null)
// return object;
return new OldNews();
}
//public static <T, V> HashMap<T, V> createOldNews() {
//}
}
注释部分使代码更像singleton
四大优点:
- 静态工厂方法具有名字,使用起来更加清楚
- 可以不用每次调用时都创建新的对象
- 可以返回任何子对象的实例
- 在构造参数化类型实例可以使代码变得简洁
缺点:
- 如果不存在不受保护的构造器,会导致无法构造子对象实例
- 静态工厂方法和其他静态方法没什么区别
2)构建器1
//com.insanus.People.java
package com.insanus;
public class People {
private int year;
private String name;
private float weight;
private float height;
//构建器
public static class Builder {
private int year;
private String name;
private float weight = 0;
private float height = 0;
public Builder(int year, String name) {
this.year = year;
this.name = name;
}
public Builder setWeight(float weight) {
this.weight = weight;
return this;
}
public Builder setHeight(float height) {
this.height = height;
return this;
}
public People createPeople() {
return new People(this);
}
}
private People(Builder builder) {
year = builder.year;
name = builder.name;
weight = builder.weight;
height = builder.height;
}
}
这样就能使代码变得非常简洁,可扩展性也大大提升
People people = new People.Builder(18, "insanus").setHeight(180).createPeople();
相比于JavaBean和重叠构造器。构建器拥有更多优点
3)私有构造器或枚举强化singleton属性
第一种写法
//com.insanus.Singleton1.java
public class Singleton1 {
public static final Singleton1 INSTANCE = new Singleton1();
private Singleton1() {
}
public void method() {
}
}
第二种写法
//com.insanus.Singleton2.java
public class Singleton2 {
private static final Singleton2 INSTANCE = new Singleton2();
private Singleton2() {
}
//静态工厂方法
public static Singleton2 getSingleton() {
return INSTANCE;
}
public void method() {
}
}
第三种写法
//com.insanus.Singleton3.java
public enum Singleton2 {
INSTANCE;
public void method() {
}
}
扩展:enum2
4)通过私有构造器强化不可实例化
我们甚至可以在私有构造器中抛出异常
//com.insanus.UtilityClass.java
package com.insanus;
public class UtilityClass {
private UtilityClass() {
throw new AssertionError();
}
}
5)避免创建不必要的对象
不要这样写String s = new String("Text");
这样写会使编译器创建更多的String实例,正确的写法是
String s = "Text";
重用已知不会被修改的可变对象
//effective java例子
import java.util.Date;
import java.util.TimeZone;
import java.util.Calendar;
class Person {
private final Date birthDate;
//这里还没设置birthDate数据
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;
}
}
利用静态域,使代码不必重复创建对象,极大提高性能
使用基本类型而不是装箱基本类型
观察Long i
和long i
的区别
两者性能千差万别,所以要优先使用基本类型而不是装箱基本类型
6)消除过期的对象引用
众所周知,java是一种具有垃圾回收回收的语言。然而,我们依旧得关注内存管理的问题。
//com.insanus.List.java
package com.insanus;
public class List {
private Object[] elements;
private int size = 0;
private static final int MAX = 1000;
public List() {
elements = new Object[MAX];
}
//...
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
return elements[--size];
//我们关注在这里
}
}
但你确定不再引用这些对象的时候,编译器却不知道,它依旧勤勤恳恳的维护这些过期的对象。所以,我们应该消除这些过期的对象引用。
//升级版的pop
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
Object i = elements[--size];
elements[size] = null;
//我们从这里消除了过期的对象引用
return Object;
}
7)避免使用finalize()
首先提几个缺陷:
- 你不能保证finalize一定被执行,当然,这不是你的原因。
- finalize的优先级太低,大概可以比喻成,饭都盛进去了,而碗还没有洗
- 使用finalize会导致严重的性能缺失
但我们确实需要一个终止功能时,该如何编写终止方法。
显式的终结
//com.insanus.Died.java
package com.insanus;
public class Died {
private boolean isDie;
//我们在私有域中写了这么一句话,当我要引用这个对象的方法是,想检查一下是不是被终结了
public void cancel() {
isDie = true;
}
}
当我确定要使用finalize时,请确保super.finalize()
,因为终结方法链不会自动执行。