Effective Java 笔记(二) - ilibaba的专栏 - CSDNBlog

来源:百度文库 编辑:神马文学网 时间:2024/04/20 05:14:12
NO.4 避免创建重复的对象
如果一个对象是非可变的,那么他中上可以被重用的,如:
//不推荐,"test"本来就是一个String实例,如果此方法在一个循环中或者被频繁的调用,将会严重影响性能 String s = new String("test"); //推荐方式 String s = "test";
对于提供静态方法和构造函数的非可变类,推荐使用静态方法,这样可以避免重复创建对象,如:Boolean.vauleOf(String)方法优于构造函数Boolean(String)
如下Person类在每次调用isBabyBoomer()方法时都需新创建对象,极大的影响了性能
import java.util.*; public class Person {     private final Date birthDate;     public Person(Date birthDate) {         // Defensive copy - see Item 39         this.birthDate = new Date(birthDate.getTime());     }     // Other fields, methods omitted     // DON'T DO THIS!     public boolean isBabyBoomer() {         // Unnecessary allocation of expensive object         Calendar gmtCal =             Calendar.getInstance(TimeZone.getTimeZone("GMT"));         gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);         Date boomStart = gmtCal.getTime();         gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);         Date boomEnd = gmtCal.getTime();         return birthDate.compareTo(boomStart) >= 0 &&                birthDate.compareTo(boomEnd)   <  0;     } }
改进方案如下:
import java.util.*; class Person {     private final Date birthDate;     public Person(Date birthDate) {         // Defensive copy - see Item 39         this.birthDate = new Date(birthDate.getTime());     }     // Other fields, methods     /**      * The starting and ending dates of the baby boom.      */     private static final Date BOOM_START;     private static final Date BOOM_END;     static {         Calendar gmtCal =             Calendar.getInstance(TimeZone.getTimeZone("GMT"));         gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);         BOOM_START = gmtCal.getTime();         gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);         BOOM_END = gmtCal.getTime();     }     public boolean isBabyBoomer() {         return birthDate.compareTo(BOOM_START) >= 0 &&                birthDate.compareTo(BOOM_END)   <  0;     } }
这样类变量在类在初始化创建Calendar、Date、TimeZone时只需创建一次,已经初始化的不再进行初始化操作,性能好于前一种方法一百倍。【static变量在系统没有调用isBabyBoomer() 方法之前,不会进行初始化(延迟初始化)】
类初始化的顺序:先初始化父类的静态代码--->初始化子类的静态代码-->初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函数。
NO.5 消除过期的对象引用
垃圾回收器不会对“过期引用”(永远不会在被解除的引用)的对象进行回收。如:数组中的元素先增加再减少这种情况,下标大于size()的那一部分就是过期引用的对象。
解决方法:
public Object pop(){
if(size == 0){
throw new EmptyStackException();
}
Object result = elements[--size];
//自减后把原来的引用置为null elements[size] = null;
return result;
}
优点:1、避免内存泄漏而造成的系统崩溃(内存泄漏也常见于缓存,由于缓存没有及时清除无用的条目而出现,可以使用weakHashMap来避免这种情况,参考:利用WeakHashMap避免因缓存条目过期而造成的内存泄漏问题);
2、程序能在第一时间抛出空指针异常;
NO.6 避免使用终结函数
终结函数(finalizer)可以用来回收不可到达的对象,就是说对象的生命周期结束后,可以用终结函数来回收为该对象分配的资源。
但是,终结函数执行线程的优先级很低,以至于我们不敢把对时间要求比较高的对象回收让终结函数来回收。JVM总是会延迟终结函数的执行。
对于急需回收对象,可以使用tyr finally,在finally写回收对象的代码,这样就保证对象能及时被回收。
终结函数其实也是有用的。第一种情况是当作安全网,当忘了对对象显示回收的时候,用终结函数作为最后的安全屏障。第二种情况是:普通对象通过一个本地方法委托给本地对象叫本地对等体。本地对等体不是普通对象,所以当委托给他的对象被回收的时候本地对等体并不会被回收,所以这时候终结函数就派上用场了。
最后要注意的是,当子类改写覆盖了超类的终结函数时候,如果不显示调用超类的终结函数,那么超类的终结函数将不会被执行。
总结:尽量不使用终结函数,除非作为安全网或者是用来回收不关键的本地资源。
Effective Java 笔记(二) - ilibaba的专栏 - CSDNBlog Effective Java 笔记(五) - ilibaba的专栏 - CSDNBlog Effective Java 笔记(六) - ilibaba的专栏 - CSDNBlog Effective Java 笔记(七) - ilibaba的专栏 - CSDNBlog java clone方法使用详解 - ilibaba的专栏 - CSDNBlog 散列表(哈希表)工作原理 - ilibaba的专栏 - CSDNBlog 排序算法小结 - ilibaba的专栏 - CSDNBlog 《POJOS in Action》读书笔记 - ilibaba的专栏 - CSDNBlog java排序算法 - 大海的专栏 - CSDNBlog 学习Java的30个基本概念 - 刀目村的专栏 - CSDNBlog java正则表达式入门文档 - lenhan12345的专栏 - CSDNBlog 如何迅速成为Java高手 - paulfong的专栏 - CSDNBlog Java学习总论(转) - popkiler的专栏 - CSDNBlog Java 设计模式:代理模式Proxy - hsyj_0001的专栏 - CSDNBlog Java程序员面试宝典 - 飞鸟的专栏 - CSDNBlog Java 设计模式:代理模式Proxy - hsyj_0001的专栏 - CSDNBlog 享受JAVA的空气: Struts学习笔记(二) 解决Java Applet和Java Script通信问题 - complayer的专栏 - CSDNBlog 读《Effective java 中文版》(44) J2EE笔记(二) — Java web AOP以及其在Spring中的应用(二) - hesan的专栏 - CSDNBlog 一个Dijkstra算法的完整Java程序实现,算法初学者必看! - brokencar的专栏 - CSDNBlog 基于WEB应用开发的java程序员必备工具 - 辛佳雨的专栏 - CSDNBlog 深入剖析Java编程中的中文问题及建议最优解决方法 - mayabuluo的专栏 - CSDNBlog