《Effective Java》 Chapter2 创建和销毁对象

本文探讨了对象创建的最佳实践,包括使用静态工厂方法代替构造器、Builder模式处理多参数、私有构造确保单例和不可实例化、依赖注入的运用、避免资源浪费和过期引用的管理。还强调了避免终结方法和清除方法,提倡try-with-resources的使用。
摘要由CSDN通过智能技术生成

本章要点
1.何时以及如何创建对象;
2.何时以及如何避免创建对象;
3.如何保证对象能够适时地销毁;
4.如何管理对象销毁之前必须进行的各种清理动作。

第1条:用静态工厂方法代替构造器

把常用的构造逻辑封装成对应名字的方法,然后通过这些方法来实例化而非构造函数。

构造函数: Customer customer = new Customer(name, age, sex);
静态工厂方法: Customer customer = Customer.getCommonCustomer(name, age, sex);
第2条:遇到多个构造器参数时要考虑使用构建器

使用Builder模式实例化对象,尤其是多构造参数时(@Builder注解即可实现功能)。

普通构造: Customer customer = new Customer(name, age, sex);
Builder模式: Customer customer = Customer.builder().name(name).age(age).sex(sex).build();
第3条:用私有构造器或者枚举类型强化Singleton属性

构造函数设为私有且返回自身,或者直接将该class转换为enum来实现功能,以强调当前类是个“单例”。

私有构造函数: private Customer() {return INSTANCE;}
枚举类: public enum Customer {INSTANCE;}
第4条:通过私有构造器强化不可实例化的能力

所有构造函数设为私有且返回为空甚至抛出异常,强调当前类“不可被实例”(通常针对各种Utils类)。

private Customer(){
    throw new AssertionError();
}
第5条:优先使用依赖注入来引用资源

创建实例A时将该实例的具体依赖B和C注入,而不是直接写死,不过书中还是主推Spring依赖注入框架来引入各种需要重复使用的资源。

private final Name name;
private final Age age;
public Customer(Name name, Age age){
    this.name = name;
    this.age = age;
}
第6条:避免创建不必要的对象

1.通用的对象不要重复创建,最典型的为常量字符串的String;

2.优先使用基本类型而非装箱基本类型,当心无意识的自动装箱。

错误示范1 new常量String: String customerName = new String("Jack");
错误示范2 装箱类型使用不当: Long num = 1000000; for(...) {num += 2}
第7条:消除过期的对象引用

一个容器比如栈,对象先弹出再收缩,被弹出的对象不会被垃圾回收,因为栈内部维护着对这些已弹出对象的“过期引用”,需要对容器中的这些过期引用进行消除。

public Object pop(){
    Object result = elements[--size];
    elements[size] = null; //清除对应数据
    return result;
}
第8条:避免使用终结方法和清除方法

终结方法finalizer和Java9的清除方法cleaner的缺点如下,所以如果需要两方法的功能效果,最好是让调用资源的类实现AutoCloseable方法后用try-with-resources来实现。

1.在于“不能保证会被及时执行”,所以最好“永远不应该依赖终结方法或者清除方法来更新重要的持久状态”;

2.存在非常严重的性能损失,因为两者阻止了有效的垃圾回收;

3.为终结方法攻击打开了类型的大门。

第9条:try-with-resource优先于try-finally

try-finally中try和finally语句块均会抛出异常,而finally中的异常会完全抹除try中的异常,故现在均要求使用资源的类必须实现AutoCloseable接口,然后通过try-with-resource来实现相关功能。

//try-finally多资源嵌套时代码很乱,并且存在异常覆盖问题(out.close的异常会完全抹除out.wrire的异常):
InputStream in = new FileInputStream(src);
try{
    OutputStream out = new FileOutputStream(dst);
    try{
        out.wirte(...)
    } finally {
        out.close();
    }
} finally {
    in.close();
}

//try-with-resource通用情况(FileInputStream与FileOutputStream均实现了AutoCloseable接口):
try (InputStream in = new FileInputStream(src);
     OutputStream out = new FileOutputStream(dst);){
        out.wirte(...);
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值