Effective Java(一)
来源:互联网 发布:行知中学住宿条件 编辑:程序博客网 时间:2024/06/11 07:34
一.遇到多个构造器参数时要考虑使用构建器
当一个类有多个参数的时候,如果使用构造器初始化实例会很麻烦,这样我们需要提供很多很多构造器,当参数足够多后再加一个参数我们就需要添加很多构造器函数。
此外如果使用重叠构造器模式,会很难理解,如果不小心颠倒了两个参数顺序也很难发现。
当出现这种问题时,我们通常会使用JavaBeans模式,调用一个无参构造器创建对象,然后调用setter方法设置必要参数。这种模式有一个很严重的缺点,因为构造郭恒被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。此外,JavaBeans模式阻止了把类做成不可变的可能,这就需要我们自己确保它的线程安全。
在这种情况下,我们可以使用Builder模式保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式的可读性。示例代码如下:
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 static class Builder{ private final int servingSize; private final int servings; private int calories = 0; private int fat = 0; private int carbohydrate = 0; private int sodium = 0; public Builder(int servingSize ,int servings){ this.servingSize = servingSize ; this.servings = servings ; } public Builder calories(int val){ calories = val; return this ; } public Builder fat(int val){ fat = val; return this ; } public Builder carbohydrate(int val){ carbohydrate = val ; return this ; } public Builder sodium(int val){ sodium = val; return this ; } public NutritionFacts build(){ return new NutritionFacts(this); } } private NutritionFacts(Builder builder){ servingSize = builder .servingSize ; servings = builder. servings; calories = builder. calories; fat = builder. fat; sodium = builder. sodium; carbohydrate = builder .carbohydrate ; }}
在我的Builder实现中,我会用Builder的构造函数而不是set方法传递客户需要的属性。这样做的好处在于,对象总是能被一次完整的实例化,而不是靠开发人员调用时用set方法补充额外的属性完成实例化。这也体现了不可变性带来的好处。
二.使用枚举类型强化Singleton
传统单例实现:
public class Singleton1 { private static final Singleton1 instance = new Singleton1(); private Singleton1(){ } public static Singleton1 getInstance(){ return instance ; }}
此外还有二次检查锁实现,静态内部类实现等。
从Java1.5版本起,产生另一种Singleton实现方式,使用枚举来实现,代码如下
public enum Singleton2 { INSTANCE;}
实现起来非常简洁,且是线程安全,也避免了序列化破坏单例。
三.通过私有构造器强化不可实例化的能力
简单来说,我们编写的一些util工具类,不希望被实例化,因为编译器会自动提供一个公有的误餐的构造器,因此我们需要通过私有构造器来避免被实例化,甚至有时候可以在构造器中抛出异常。
四.避免创建不必要的对象
典型示例:判断出生日期是否在1946到1965年之间
public class Person { private Date birthDate; public boolean isBabyBoomer(){ Calendar cal = Calendar.getInstance(TimeZone. getTimeZone("GMT" )); cal.set(1946, Calendar. JANUARY,1,0,0,0); Date boomStart = cal .getTime(); cal.set(1965, Calendar. JANUARY,1,0,0,0); Date boomEnd = cal.getTime(); return birthDate .compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd ) < 0; }}
isBabyBoomer每次被调用的时候都会创建一个Calendar一个TimeZone和两个Date示例,改进写法:
public class Person { private Date birthDate; private static final Date BOOM_START; private static final Date BOOM_END; static{ Calendar cal = Calendar.getInstance(TimeZone. getTimeZone("GMT" )); cal.set(1946, Calendar. JANUARY,1,0,0,0); BOOM_START = cal .getTime(); cal.set(1965, Calendar. JANUARY,1,0,0,0); BOOM_END = cal .getTime(); } public boolean isBabyBoomer(){ return birthDate .compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0; }}
改进后的person类只在初始化的时候创建Calendar,TimeZone和Date示例一次。
五.消除过期的对象引用
如下代码存在内存泄露隐患:
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){ return new Exception("栈为空"); } return elements [--size ]; } private void ensureCapacity(){ if(elements .length == size ){ elements = Arrays. copyOf(elements,2 * size + 1); } }}
内存泄露地方:如果一个栈先是增长,然后再收缩,那么从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的程序不在引用这些对象。这是因为栈内部维护者对这些对象的过期引用。所谓过期引用,是指永远不会再被解除的引用。在本例中凡是在elements数组的"活动部分"之外任何引用都是过期的。活动部分是指elements中下标小于size的那些元素。
改进方法:一旦对象引用已经火气,清空这些引用。如下所示:
public Object pop(){ if(size == 0){ return new Exception("栈为空"); } Object result = elements[-- size]; elements[ size] = null;//清空引用,防止内存泄露 return result ; }
0 0
- Effective Java读书笔记一
- effective java读书笔记一
- 《Effective Java》读书笔记一
- Effective java 读书笔记(一)
- Effective Java读书笔记一
- Effective Java读书笔记一
- 《Effective Java》笔记(一)
- Effective Java(一)
- effective java摘抄(一)
- 【effective java】(一)
- 重读Effective Java(一)
- effective java 学习笔记(一)
- Effective Java 读书笔记(一)
- Effective Java 笔记(一)
- Effective Java 笔记(一)
- Effective Java读书笔记(一)
- 《Effective Java》 读后感(一)
- effective java 笔记(一)
- 小博老师解析JavaWeb核心技术 ——AJAX第一弹
- GitHub上的markdown格式一些利于排版的用法
- Jenkins构建Android项目持续集成之findbugs的使用
- BootStrap:去除BootStrap所有圆角效果-----说真的看到圆角我就有点烦躁
- bzoj1043 [HAOI2008]下落的圆盘
- Effective Java(一)
- Minix 1.0文件系统的实现
- OpenCV API应用手册(1)- OpenCV各个功能模块介绍
- LeetCode 398. Random Pick Index(C++)
- final关键字--Java基础052
- bzoj1019 [SHOI2008]汉诺塔
- MySQL存储引擎总结
- SRM 551 ColorfulCupcakesDivTwo
- 011213笔记