java创建和销毁对象总结

在读effective java的过程中,让我了解到即使是最常见的创建和销毁对象,也是有讲究,有操作的。故对此做一个小结,将作者想告诉我们的主要思想记录一下。

第一章,创建和销毁对象总结

1、以静态工厂方法替代构造器

这一节作者主要想表达的意思是:静态工厂方法可以重新定义名称,比起单纯的使用构造方法而言,更能清楚的描述当前的使用的情景。静态工厂方法可以控制返回的实例,是重复使用已有实例还是重新new一个,还是返回该类型的子类对象,甚至是使用反射返回某一个类的对象,这些都是一个静态工厂方法就可以完成的。

总结:当我们想要创建一个实例时,使用静态工厂方法可以更加直观的看出这个对象的含义,而且通过静态工厂方法可以更加灵活的获取所需对象。

2、当构造器含有多个参数时要考虑使用构建器

当一个类的构造方法有很多个参数时。 但当你实例化时,也许当前情景下并不是每一个参数都要有实际意义的值,为此我们一般会使用重叠构造器模式,javaBeans模式来简化类的实例化。但他们都不太清晰直观,后者还有多线程下数据不一致的隐患。为此作者推荐,当一个类有很多参数时,使用建造者模式来实例化对象。 使用建造者的优势在于, 解决了javabeans模式在多线程下的隐患问题, 比起重叠构造器模式更加简单灵活且可靠。

总结:作者建议如果类的构造器或静态工厂中有多个参数,且大多参数很多情况下都不是必要的,那么可以使用builder模式。注意,如果对性能要求很高的情况下,建议别使用builder模式。

3、使用枚举类型强化singleton属性

singleton我们都知道,是为了提供该类只有唯一实例的一种设计模式。但我们常常忽略的有几点,一是它可以被反射机制调用构造方法,二是反序列化时,你没做处理的话还是会生成一个新的实例。 一可以通过修改构造器,在其视图调用第二次的时候抛出异常来解决。二是需要在序列化时重写readResolve方法。
在这里插入图片描述
此外,还有第三种比较好的方法,就是单元素的枚举。这种方法经常成为实现singleton的最佳方法。
在这里插入图片描述
总结:如果条件允许,建议使用单枚举形式来实现singleton。

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

在日常开发中,我们经常使用到一些“工具类”,他们往往是只包含静态方法和静态域的类。使用这种类不需要实例化对象,然而在缺少显式构造器的情况下,编译器会自动加一个公有的,无参构造器。因此,这个类还是可以被实例化的。 但是这样做不好,因为这个类是只有静态方法和静态域的,我们不需要这个类的实例, 因此我们应该将这种类的构造方法声明为私有, 而且只要你声明了构造方法,那么编译器就不会再自动追加构造方法了。

public class TestUtil{
    private static String name xxxxx;
    private TestUtil(){
        throw new AssertionError();
    }
    private static void method(){}
}

总结:只包含静态方法和静态域的类,应该将其构造方法声明为私有的,并添加注释说明,这个类是无法被外部实例化的。

5、优先使用依赖注入来引用资源

在一个类中,某个依赖实例化时使用外部注入的方式比直接在这个类中创建该依赖要好。不过依赖注入太多会导致项目比较难以管理,因此大型项目中一般使用dagger,spring等框架来管理依赖。
在这里插入图片描述
总结:当类中的某个成员变量需要实例时,就将该实例通过构造方法传入。即在类创建时,从构造方法中将该成员变量赋值。如上图所示。这就是依赖注入的一种形式。总之,能使用依赖注入来引用资源的地方,就使用依赖注入方式,这将大大提升类的灵活性和可复用性。

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

(1)就是说完全可以复用的对象,就别创建新实例了。
(2)对于一些重量级对象,应该使用缓存,例:
在这里插入图片描述
(3)使用懒加载方式,在需要时才创建所需对象
(4)小心自动装箱带来的多余对象,不要混用基本数据类型和装箱基本类型,以优先使用基本数据类型为上
(5)一些小对象的创建和回收的代价是很小的,有时为了提升程序的可读性,简洁性,而多创建了几个小对象是完全可以的。
(6)当理应使用新对象时,就别再考虑复用对象了。(这在保护性拷贝一节中有讲)

7、消除过期对象的引用

在使用java开发过程中,java虚拟机会自动帮我们回收不需要的对象。但鉴于它的回收机制,如果某一个对象一直被引用,那么它就不会被回收。比如我们常用的stack数据结构,如果我们使用栈时是先增长后收缩,那么当我们出栈一个元素时,即使以后程序没有再使用这个元素了,但它也不会被回收,因为栈中还依然维护着这个对象的过期引用。要解决这个问题就是在出栈时,将原来该位置的元素置为null。当然在java的stack类的pop方法中,已经处理了这个问题,置为null后就可以被gc了。
在这里插入图片描述
总结:内存泄露主要来源于 自己管理内存的类,缓存,监听器和其他回调。建议用一些工具来帮助分析对象有没有被的回收。

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

终结和清除方法会导致性能降低,行为不稳定,且在不同平台表现可能不相同,不可预测等问题,应该尽量少的使用。只有在资源的所有者忘记调用close方法的时候,终结或清除方法可以充当“安全网”,迟一点释放资源也比永远不释放要好。

总结:非必要不要使用这两个方法。 终结方法的实现是通过重写finalize(),清除方法的实现是实现AutoCloseable接口。

9、优先使用try-with-resource,而不是try-finally

在java常用库,如InputStream,OutputStream,java.sql.Connection中,我们可能经常会忘了关闭资源(没调用close)。由第八条我们可知,那几个类都有终结方法做安全网。为了安全的关闭资源,我们应该使用try-with-resource方法, 它的使用用例如下:
在这里插入图片描述
在try中写我们需要关闭的类,然后在try的括号内进行正常的操作,同时它也支持正常的catch操作。需要注意的是,那个类必须实现AutoCloseable接口。

结论:在处理必须关闭的资源时,始终优先使用try-with-resource,这样写的代码更将简洁,清晰。

END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值