《Effective Java》笔记(一)--创建和销毁对象

文章目录

创建和销毁对象

  1. 用静态工厂方法代替构造器

通过静态工厂方法返回类的实例,通过名称突出静态方法之间的区别

//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));
    }
  1. 遇到多个构造器参数时,要考虑使用构建器( 建造者模式 )

静态内部类的使用场景之一

示例代码

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}
  1. 用私有构造器或者枚举类型强化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;
  1. 通过私有构造器强化不可实例化的能力

有时候需要编写一种只包含静态方法和静态域的类,例如工具类。这样的类被实例化没有意义,因此不希望被实例化。最好的操作是,让这个类包含一个私有构造器,他就不能被实例化。

public class UtilClass {

    //为了使该类不能被实例化,定义private构造器用来覆盖默认的构造器
    private UtilClass(){};

    /**
     * 下面是一些public static方法
     */
     ...
}
  1. 优先考虑依赖注入来引用资源

当某个类依赖一个或多个底层资源。例如,拼写检查器会依赖不同的词典。最简单的模式是,每创建一个新的实例,就将该资源传到构造器中。词典就是拼写检查器的一个依赖,创建拼写检查器时就注入词典。

public class SpellChecker {
    private final Lexicon dictionary;
    
    public SpellChecker(Lexicon dictionary){
        this.dictionary= Objects.requireNonNull(dictionary);
    }
    
    public boolean isValid(String word){...}
}
  1. 避免创建不必要的对象

一般来说,最好能重用单个对象,而不是在每次需要的时候就创建一个相同功能的对象。

--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();
    }
}
  1. 消除过期的对象引用
  2. 避免使用终结方法和清除方法
  3. 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值