文章目录
创建和销毁对象
- 用静态工厂方法代替构造器
通过静态工厂方法返回类的实例,通过名称突出静态方法之间的区别
//Boolean类
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
//BigInteger类,产生素数的静态工厂方法
public static BigInteger probablePrime(int bitLength, Random rnd) {
if (bitLength < 2)
throw new ArithmeticException("bitLength < 2");
return (bitLength < SMALL_PRIME_THRESHOLD ?
smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :
largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));
}
- 遇到多个构造器参数时,要考虑使用构建器( 建造者模式 )
静态内部类的使用场景之一
示例代码
public class Car {
private String engine;
private String color;
private int length;
private int price;
public static Builder builder() {
return new Builder();
}
private Car(Builder builder) {
this.engine = builder.engine;
this.color = builder.color;
this.length = builder.length;
this.price = builder.price;
}
//静态内部类Builder
public static class Builder {
private String engine;
private String color;
private int length;
private int price;
//防止直接new一个Car.Builder类,而应通过Car.builder()方法获取
private Builder() {
}
public Builder engine(String engine) {
this.engine = engine;
return this;
}
public Builder color(String color) {
this.color = color;
return this;
}
public Builder length(int length) {
this.length = length;
return this;
}
public Builder price(int price) {
this.price = price;
return this;
}
public Car build() {
return new Car(this);
}
}
@Override
public String toString() {
return "Car{" +
"engine='" + engine + '\'' +
", color='" + color + '\'' +
", length=" + length +
", price=" + price +
'}';
}
}
测试用例
public class Test {
public static void main(String[] args) {
Car car = Car.builder().engine("EngineA")
.color("white")
.length(4)
.price(100000)
.build();
System.out.println(car.toString());
Car car1 = Car.builder().engine("EngineA")
.length(4)
.build();
System.out.println(car1.toString());
}
}
--运行结果
Car{engine='EngineA', color='white', length=4, price=100000}
Car{engine='EngineA', color='null', length=4, price=0}
- 用私有构造器或者枚举类型强化Singleton属性
Singleton指仅仅被实例化一次的类,将构造器设置为private,防止在外部直接new对象。
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() {
}
public static Elvis getInstance() {
return INSTANCE;
}
}
--获取该类的单例对象
Elvis elvis=Elvis.getInstance();
另一种方式是声明一个包含单个元素的枚举类型,更加简洁,是实现Singleton的最佳方法。但需要扩展超类的时候不宜使用。
public enum Elvis {
INSTANCE;
}
--获取该类的单例对象
Elvis elvis=Elvis.INSTANCE;
- 通过私有构造器强化不可实例化的能力
有时候需要编写一种只包含静态方法和静态域的类,例如工具类。这样的类被实例化没有意义,因此不希望被实例化。最好的操作是,让这个类包含一个私有构造器,他就不能被实例化。
public class UtilClass {
//为了使该类不能被实例化,定义private构造器用来覆盖默认的构造器
private UtilClass(){};
/**
* 下面是一些public static方法
*/
...
}
- 优先考虑依赖注入来引用资源
当某个类依赖一个或多个底层资源。例如,拼写检查器会依赖不同的词典。最简单的模式是,每创建一个新的实例,就将该资源传到构造器中。词典就是拼写检查器的一个依赖,创建拼写检查器时就注入词典。
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary){
this.dictionary= Objects.requireNonNull(dictionary);
}
public boolean isValid(String word){...}
}
- 避免创建不必要的对象
一般来说,最好能重用单个对象,而不是在每次需要的时候就创建一个相同功能的对象。
--s1更好,如果是在循环中,s2会创建很多个对象,s1能重用
String s1 = "bikini";
String s2 = new String("bikini");
--valueOf更好,会复用static对象,而构造器每次都会创建新的实例。
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
public Boolean(boolean value) {
this.value = value;
}
以下示例,要查看一个字符串是否与正则表达式相匹配。应该在内部显式定义一个static final实例,而不是在static方法中定义。目的是为了可以重用Pattern对象,而不用每次都重新创建。
public class RomanNumerals {
private static final Pattern ROMAN=Pattern.compile("...");
public static boolean isRomanNumeral(String s){
return ROMAN.matcher(s).matches();
}
}
- 消除过期的对象引用
- 避免使用终结方法和清除方法
- try-with-resources优先于try-finally
在处理必须关闭的资源时,优先用 try-with-resources而不是 try-finally。
public static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(src)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
//有catch子句的try-with-resources
public static String firstLineOfFile(String path,String defaultVal) throws IOException {
try(BufferedReader br = new BufferedReader(
new FileReader(path))){
return br.readLine();
}catch (IOException e){
return defaultVal;
}
}