《Effective Java》读书笔记04--避免创建不必要的对象
来源:互联网 发布:网络发展趋势 编辑:程序博客网 时间:2024/09/21 09:08
一、Java的String对象
java中String对象很特殊,因为它是个不可变对象。每次对String进行截取,拼接都会返回一个新的String对象。正因为这个原因,初学者经常陷入对字符串操作的误区,包括我,呵呵。
两种生成字符串的方式:
String s = new String("strubgette"); //每次执行都会创建一个新的String实例,即使它们在功能方面是等同的。何必呢,呵呵,又不是内存用不完。。。
String s = "strubgtte"; //如果JVM常量池中有该字符串字面常量,则直接将引用赋给s,否则创建一个新的,基本可以保证只用到一个String实例。
二、重用对象之道
1、不可变对象(immutable object)始终应该被重用。
2、不会被修改的可变对象也应该被重用。
反面示例:
public class Person { private final Date birthDate; public Person(Date birthDate) { // 保护性拷贝,Date是可变对象,否则,哈哈,有你受的 this.birthDate = new Date(birthDate.getTime()); } // DON'T DO THIS!//判断一个是是否在生育高峰期出生(1946~1964) 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; }}这里每调用isBabyBoomer()方法都会创建一个Calendar,一个TimeZone和两个Date,这玩意可不是闹着玩的,一个Calendar实例的创建可以买头猪。。。
修正版:
class Person { private final Date birthDate; public Person(Date birthDate) { //保护性拷贝 this.birthDate = new Date(birthDate.getTime()); } /** * 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; }}两个Date做成了final静态域,Calendar和TimeZone也只会在Person类初始化时创建一次,不仅代码逻辑上清晰了,而且性能貌似也有了提高。当然,还可以延迟初始化BOOM_START和BOOM_END,但没必要这样做,因为延迟初始化是有风险的。
三、有个名词叫自动装箱(autoboxing)
Java1.5发行版中,一个牛叉的概念出现了,自动装箱。它允许程序员将基本类型和装箱基本类型(Boxed Primitive Type)混用,按需要自动装箱和拆箱。这貌似成了我们Java菜鸟的福音,动不动就来个Integer,它会装箱哈,多牛叉。殊不知,性能刷刷的滑,这回臭大了。。。
来看一个不小心就会犯的错误:
public class Sum { // Hideously slow program! Can you spot the object creation? public static void main(String[] args) { Long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println(sum); }}变量sum被声明成Long而不是long,打错一个字符,意味着程序需要额外构造大约2^31个多余的Long实例,很蛋疼吧?!
四、最佳编程实践
1、对于同时提供静态工厂方法和构造器的不可变类,通常可以使用静态工厂方法而不是构造器,以避免创建不必要的对象。静态的是类级的,跟对象没啥关系,创不创建都能调用里面的方法。
2、不可变对象(immutable object)始终应该被重用。
3、不会被修改的可变对象也应该被重用。
4、要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱。
- 《Effective Java》读书笔记04--避免创建不必要的对象
- Effective Java -- 避免创建不必要的对象
- 《Effective java》读书笔记1——避免创建不必要的对象
- Effective Java第五条:避免创建不必要的对象
- Effective Java 第5条:避免创建不必要的对象
- Effective Java (5) - 避免创建不必要的对象
- Effective Java 第5条 避免创建不必要的对象
- Effective Java (5) 避免创建不必要的对象
- Effective Java 学习 第五条 避免创建不必要的对象
- Effective Java 第五条:避免创建不必要的对象
- [Effective Java] - 1,避免创建不必要的对象
- Effective Java 2.5——避免创建不必要的对象
- effective java(5) 之避免创建不必要的对象
- Effective Java之避免创建不必要的对象(五)
- effective--避免创建不必要的对象
- 学习effective java-5创建和销毁对象之避免创建不必要的对象
- 【Effective Java】Ch2_创建销毁对象:Item5_避免创建不必要的对象
- Effective Java(避免创建不必要的对象、消除过期的引用对象)
- 实验一 Linux基本环境
- Android源码目录结构详解
- java基础第13天
- Android里Service的bindService()和startService()混合使用深入分析
- java基础第14天
- 《Effective Java》读书笔记04--避免创建不必要的对象
- 大数据
- 嵌入式Linux笔记
- 如何诊断oralce 运行突然变慢
- 2013.3.23-5简介struct cmsghdr结构
- vim基本命令
- java基础第15天
- vim——打开多个文件、同时显示多个文件、在文件之间切换
- java 集合