java避免重复创建对象_《EffctiveJava》创建和销毁对象

创建和销毁对象

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

相比构造器的优点:

有名称:可以更明确方法的功能;

不必在调用时重复创建实例:使不可变类预先创建实例,或将实例缓存起来,避免重复创建对象,提高性能。

返回原返回类型的子类型的对象。

在创建参数化类型实例时,代码更简洁Map> map = new HashMap>();

// 用静态工厂方法实现

Map map = HashMap.newInstence();

相比构造器的缺点:

类如果不含共有的或者受保护的构造器,将不能被子类化。

与其他的静态方法没任何区别。

静态工厂方法的一些命名习惯

– valueOf:类型转换方法

– of:更简洁的替代,在EnumSet中使用并流行起来

– getInstance:对于Singleton来说,该方法没有参数,只会返回一个实例。

– newInstance:与getInstance一样,但newInstance能够确保每个新实例与其他实例不同。

– getType:像getInstance一样,返回对象类型

– newType:想newInstance一样,返回对象类型

综上:构造器和静态工厂方法各有优缺点,优先使用静态工厂方法。

遇到多个构造器参数时要考虑用构建器

Builder模式:利用多个builder构建多个对象。推荐在多参数且参数大多数都是可选的的情况下使用。

优点:易于阅读和编写,比JavaBean更安全。

缺点:比重叠构造器冗长。

Builder模式示例:

public class NutritionFacts {

private final int servingSize;

private final int servings;

private final int colorings;

private final int fat;

private final int sodium;

private final int carbohydrate;

public static class Builder {

// 必须的

private int servingSize = 0;

private int servings = 0;

// 非必须的

private int colorings = 0;

private int fat = 0;

private int sodium = 0;

private int carbohydrate = 0;

public Builder(int servingSize, int servings) {

this.servings = servings;

this.servingSize = servingSize;

}

public Builder calories(int colorings) {

this.colorings = colorings;

return this;

}

public Builder carbohydrate(int carbohydrate) {

this.carbohydrate = carbohydrate;

return this;

}

public Builder sodium(int sodium) {

this.sodium = sodium;

return this;

}

public Builder fat(int fat) {

this.fat = fat;

return this;

}

public NutritionFacts build() {

return new NutritionFacts(this);

}

}

private NutritionFacts(Builder builder) {

this.servingSize = builder.servingSize;

this.servings = builder.servings;

this.colorings = builder.colorings;

this.fat = builder.fat;

this.sodium = builder.sodium;

this.carbohydrate = builder.carbohydrate;

}

}

调用:

NutritionFacts nutritionFacts = new NutritionFacts.Builder(1, 2)

.calories(3).carbohydrate(4).fat(5).sodium(6)

.build();

用私有构造器或枚举类型强化Singleton属性

Singleton是指仅仅被实例化一次的类。Singleton通常被用来表示那些本质上唯一的系统组件,例如窗口管理器或文件系统。

方式一:

public class Elvis {

private Elvis() {

// 初始化相关操作

}

public static final Elvis INSTANCE = new Elvis();

public void leaveTheBuilding() {

// ...

}

}

使用:

Elvis.INSTANCE;

方式二:

public class Elvis {

private Elvis() {

// 初始化相关操作

}

private static final Elvis INSTANCE = new Elvis();

public static Elvis getInstance() {

return INSTANCE;

}

}

使用:

Elvis.getInstance();

通过私有构造器强化不可实例化的能力

一些工具类不希望被实例化,实例化对它没有任何意义。

public class UtilityClass {

/**

* 私有构造方法,保证在任何情况下都不会被实例化

*/

private UtilityClass() {

// 防止在当前类调用构造方法

throw new AssertionError();

}

public static boolean empty(String message) {

if (message == null || "".equals(message)) {

return Boolean.TRUE;

}

return Boolean.FALSE;

}

}

使用:

UtilityClass.empty("hello Word");

避免创建不必要的对象

正确使用String

反例:

String s = new String("hello");// hello本来就是字符串

正确:

String s = "hello";

自动装箱

优先使用基本类型。

消除过期的对象引用

一般而言,只要类是自己管理内存,就应该警惕内存泄漏的问题。

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) {

}

Object e = elements[--size];

elements[size] = null;

return e;

}

private void ensureCapacity() {

if (elements.length == size) {

elements = Arrays.copyOf(elements, 2 * size+1);

}

}

}

避免使用终结方法

try finally

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值