Effective Java2读书笔记-创建和销毁对象(三)
第5条:避免创建不必要的对象
本条主要讲的是一些反面教材,希望大家引以为鉴。
①无意中使用自动装箱导致多创建对象。
public class Sum {
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,意味着每次i都要被自动装箱(创建Long实例),因此速度会慢很多。
②可以重用不会被修改的可变对象。
也就是说,有些看起来是变量,但是实际上它的值一旦计算出来之后就不再变化,这种也应该视作常量,而不是每次都计算。
下面先看一段代码。
public class Person {
//生日
private final Date birthDate;
public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}
public boolean isBabyBoomer() {
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实例,这是没有必要的(所以,在平时写方法时也要注意,有很多对象是可以提取出来的)。下面看如何改进。
public class Person {
private final Date birthDate;
public Person(Date birthDate) {
this.birthDate = new Date(birthDate.getTime());
}
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;
}
}
改进之后Person类仅在初始化时创建了实例,后面调用isBabyBoomer方法时,就没有生成对象的消耗了。
第6条:消除过期的对象引用
下面的例子对java中的栈进行一个简单的模拟,看起来逻辑上没什么问题,却隐藏着一个问题。
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)
throw new EmptyStackException();
Object result = elements[--size];
//如果没有这一步,会产生很大的问题
//elements[size] = null;
return result;
}
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
问题就在于,当栈先增长,然后再收缩。从栈中弹出来的对象并不会被当做垃圾回收,这是因为栈内还维护着这些对象的引用。弹出之后,使用栈的程序不再需要它,只能人为清理掉。一般而言,只要类是自己管理内存,程序员就应该警惕内存泄漏问题。
文中还还提到在使用回调时,确保回调立即被当作垃圾回收的最佳方法时只保存它们的弱引用,例如,只将它们保存成WeakHashMap中的键(这个平时很少用到,只作为了解)。
弱引用与强引用的区别在于,即使内存不足,强引用也不会被回收掉。而弱引用不管内存足不足,一旦被垃圾回收线程发现,就会被回收掉。
Effective Java2读书笔记-创建和销毁对象(三)的更多相关文章
- Effective Java2读书笔记-创建和销毁对象(一)
第1条:考虑用静态工厂方法代替构造器 通常情况下,我们创建一个对象采取new的形式,但是还有一种方法也是经常使用到的,它的名称叫做静态工厂方法. 例如,java中基本类型boolean的包装类Bool ...
- Effective Java2读书笔记-创建和销毁对象(四)
第7条:避免使用终结方法 这一条讲的简直是不知所云.先简单记下来其中说出的几条: ①显式终止方法的典型例子有InputStream.OutputStream和java.sql.Connection上的 ...
- Effective Java2读书笔记-创建和销毁对象(二)
第3条:用私有构造器或者枚举类型强化Singleton属性 这一条,总体来说,就是讲了一个小技巧,将构造器声明为private,可以实现单例.具体有以下几种实现的方式. ①最传统的单例实现模式,可能有 ...
- Effective Java读书笔记--创建和销毁对象
1.优先考虑用静态工厂方法代替构造器2.遇到多个构造器参数时要考虑使用构建器Builder解决参数过多,不可变类型.私有构造方法,静态类的构造方法提供必要参数,剩下可选.new xxx.build() ...
- Effective Java学习笔记--创建和销毁对象
创建和销毁对象 一.静态工厂方法代替构造器 静态工厂方法的优缺点 优点: 1.可以自定义名称(可以将功能表述的更加清晰) 2.不必每次调用都创建新的对象(同一对象重复使用) 3.返回的类型可以是原返回 ...
- Effective Java2读书笔记-类和接口(三)
第17条:要么为继承而设计,并提供文档说明,要么就禁止继承 第18条:接口优于抽象类 这两条中,提到了一个很重要的概念骨架实现.也就是说,抽象类实现接口的形式.这样的好处是,接口本来不能提供默认的实现 ...
- [Effective Java]第二章 创建和销毁对象
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Effective Java2读书笔记-对于所有对象都通用的方法(二)
第10条:始终要覆盖toString 这一条没什么好讲的,就是说默认的toString方法打印出来的是类名+@+十六进制哈希码的值.我们应该覆盖它,使它能够展示出一些更为详细清晰的信息,这个看实际情况 ...
- Effective Java2读书笔记-对于所有对象都通用的方法(一)
第8条:覆盖equals时请遵守通用约定 ①约定的内容 自反性.对于任何非null的引用值x.x.equals(x)必须返回true. 对称性.对于任何非null的引用值x和y.当且仅当y.equal ...
随机推荐
- PHP中$_GET['name']与$_POST['name']变量直接用变量名$name的php配置
php中,可以直接使用参数名称作为变量来接收get或post的传参,条件是php.ini中register_global设置成On 另外一种方法: if(!ini_get('register_glob ...
- C51工具是怎么进行覆盖分析的
C51工具针对8051微控制器的有限存储器资源进行了优化设计. 为了最有效地利用存储器,根据一个很容易解释的方法,自动变量和函数参数在存储器中均进行覆盖处理. 首先,连接器根据源程序生成调用树.例如: ...
- MVC 增加统一异常处理机制
原文地址:http://www.cnblogs.com/leoo2sk/archive/2008/11/05/1326655.html 摘要 本文将对“MVC公告发布系统”的发布公告功能添加 ...
- Check whether a given Binary Tree is Complete or not 解答
Question A complete binary tree is a binary tree in which every level, except possibly the last, is ...
- HHKB Professional 2
今天买了一副号称程序员专用的静电容键盘 HHBK Pro2无刻版,简单上手了一下,确实名不虚传,打起字来酣畅淋漓,毫不拖泥带水,感觉自己的技术提高了不少呢!!!! 由于是无刻版,需要一些时间来适应,尤 ...
- Linux usb子系统(二):USB设备驱动usb-skeleton.c
usb驱动分为通过usbfs操作设备的用户空间驱动,内核空间的内核驱动.两者不能同时进行,否则容易引发对共享资源访问的问题,死锁!使用了内核驱动,就不能在usbfs里驱动该设备. 下面转载的一篇分析u ...
- qt画刷和画笔
# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #画刷和画笔:QBrush 定义了 QPainter 的填充模式,具 ...
- python之路-模块安装 paramiko
paramiko介绍(全是洋文,看不懂啊,赶紧有道翻译吧,等有朝一日,我去报个华尔街): "Paramiko" is a combination of the esperanto ...
- iPhone图形开发绘图小结
iPhone图形开发绘图教程是本文要介绍的内容,介绍了很多关于绘图类的使用,先来看详细内容讲解. 1.绘图总结: 绘图前设置: CGContextSetRGBFillColor/CGContextSe ...
- Android 加速Gradle构建项目
1. 升级gradle 进入项目文件夹$project/gradle/wrapper/gradle-wrapper.properties, 使用最新的gradle. 修改替换为最新的 distribu ...