非完整翻译,仅是阅读英文原版时的笔记,如对你有所帮助,不甚荣幸,建议阅读英文原版,生僻词汇相对较少,相对阅读翻译版本,也能减少一些误读
可返回原类型的任意子类型
编写该方法时,返回类型不需存在
Service Provider Framework, e.g. JDBC
很多Service Provider Framework的变种,Service Access API可以返回一个比Service Provider提供的更丰富的服务接口
限制
常用方法
要考虑创建一个对象的Builder带来的 性能损失
// Builder pattern for class hierarchies
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();
}
}
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;
}
}
以下方式两种好处:
简单
// Singleton with static factory
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public static Elvis getInstance() {
return INSTANCE;
}
public void leaveTheBuilding() { ... }
}
对于采用上述任一一种方式创建的Singleton类,若要使其可序列化
Singleton的方式是声明一个包含单个元素的枚举
通过做成抽象类以强制不可实例化是 行不通 的
因此用private constructor
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
... // Remainder omitted
}
使用方法
所以代码中内存泄露的部分在哪里?
// Can you spot the "memory leak"?
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
/**
* Ensure space for at least one more element, roughly
* doubling the capacity each time the array needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
pop的正确方法
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
不要被 System.gc 和 System.runFinalization 两个方法给诱惑了。
有两个方法可以保证一旦被调用就执行终结方法和清理方法:
Finallizer的合理用法:
当Java 7引入try-with-resources语句时,所有问题突然一下子解决了。若要使用这个语句,一个资源必须实现AutoCloseable接口
// try-with-resources on multiple resources - short and sweet
static void copy(String src, String dst) throws IOException {
try (
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)
) {
byte[] buf = new byte[BUFFER_SIZE]; int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
比起try-finally,try-with-resources语句不仅更简短和更可读,而且它们更容易排查问题。