创建和销毁对象

创建和销毁对象

本文为阅读effective java的总结



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

优点:

  1. 有名称,更语义化
  2. 可以不用每次都新创建对象,缓存实例后,进行重复利用
  3. 可以返回原返回类型的任何子类型对象
  4. 可以通过参数值,让返回对象的类随着每次调用发生变化
  5. 方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在

缺点:

  1. 类中如果不含公有或者受保护的构造器,那么就不能被子类化
  2. 文档中标识不明确

常用静态工厂方法命名

  1. from–类型转换方法,它只有单个参数,返回该类型的一个相对应的实例
  2. of–聚合方法,带有多个参数,返回该类型的一个实例,把它们合并起来
  3. valueOf–比from和of更繁琐的一种替代方法
  4. instance和getInstance–返回的实例是通过方法的(如有)参数来描述的,但是不能说与参数具体同样的值
  5. create和newInstance–和上面一样,但是每次返回的都是新的实例
  6. getType–和getInstance一样,当工厂方法处于不同类的时候使用
  7. newType–和newInstance一样,当工厂方法处于不同类的时候使用
  8. type–getType和newType的简版

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

静态工厂和构造器共同的局限性:它们都不能很好的扩展大量的可选参数

public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    public NutritionFacts(int servingSize, int servings) {
        this.servingSize = servingSize;
        this.servings = servings;
    }

    public NutritionFacts(int servingSize, int servings, int calories) {
        this.servingSize = servingSize;
        this.servings = servings;
        this.calories = calories;
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat) {
        this.servingSize = servingSize;
        this.servings = servings;
        this.calories = calories;
        this.fat = fat;
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
        this.servingSize = servingSize;
        this.servings = servings;
        this.calories = calories;
        this.fat = fat;
        this.sodium = sodium;
    }

    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
        this.servingSize = servingSize;
        this.servings = servings;
        this.calories = calories;
        this.fat = fat;
        this.sodium = sodium;
        this.carbohydrate = carbohydrate;
    }
}

当创建实例时,就利用参数列表最短的构造器,但该列表包含了要设置的所有参数。这个构造器调用通常包含有许多你不想传递的参数,但还是不得不为它们传递值。
重叠构造器的方式并不适用于有大量参数的场景,则应该使用javabean模式。
但javabean也是有缺陷的,因为构造过程是在多次调用中的,所以javabean可能处于一个不一致的状态,javabean也把类做成不可变的可能性不复存在。
如果构造器参数过多可以使用builder模式。

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

在使用单例模式的时候,通常会私有化构造方法,常规的调用不会产生新的对象,但是通过反射机制还是可以调用到私有的构造函数,如果需要避免这类问题,修改构造器,让它在被要求创建第二个实例时抛出异常。
为了让上述方法实现的Singleton类变成可序列化的,仅仅在声明中加上 implements Serializable 是不够的 为了维护并保证Singleton,必须 明所有实例域都是瞬时( transient )的,并提供一个 readResolve 方法.否则,每次反序列化都会创建一个新的实例。

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

工具类记得私有化构造函数

五、优先考虑依赖注入来引用资源

静态工厂和Sigleton类不适用于需要引用底层资源的类。
最基础的依赖注入就是,创建一个新的实例时,将资源传入构造器中。

六、避免创建不必要的对象

优先使用基本类型而不是装箱基本类型,当心无意识的自动装箱

七、消除过期的对象引用

public class Stack {

    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        ensureCapacity();
        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];
    }

    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }


}

上面的程序,如果一个栈先增长,然后再收缩,那么从栈中弹出来的对象不会被当作垃圾回收,即使使用栈的程序不再引用这个对象,他们也不会被回收。那是因为栈内部维护着对这些对象的过期引用,过期引用是指永远不会被解除的引用。在本例中,凡是在elements中下标小于size的那部分元素都是过期的。解决上述问题只需要在弹栈后清空引用。


public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        Object e=elements[--size];
        elements[size] =null;
        return e;
    }

内存泄漏的另一个可能性来自于缓存
内存泄漏的第三个来源是监听器和其它回调,确保回调立即被当作垃圾回收的方式是只保存弱引用。

八、避免使用终结方法和清除方法

不行就不行,懒得说

九、try-with-resources优先于try-finally

优先就优先,不想解释

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值