• 序言

《effective java》可谓是java学习者心中的一本绝对不能不拜读的好书,她对于目标读者(有一点编程基础和开发经验)的人来说,由浅入深,言简意赅。每一章节都分为若干的条目,完全可以利用平时的零碎时间片来阅读和思考。仅仅是阅读了第二章,创建和销毁对象,从静态工厂、构造器等基础得不能再基础的知识,却使我有一种特别的感觉,就如同见到一位会使我怦然心动的女生,那种惊喜,是那么的美妙,却也是那么的震撼。原来女生还能够如此地美,原来书,所谓让人头晕的编程类书籍,可以写得如此地好,直击心灵,让人有相见恨晚的感觉。正如我在朋友圈写到的,阅书如品茗,品酒,如人生。她完全不同于《21天精通xxoo》的粗制滥造,也不像《Think in java》一样对于谁都高不可攀(我读起来有丝丝的苦涩)。

好了说太多了,现在开始正文吧。

更多精彩,请关注:http://muscle1990.com/?p=295

  • 创建和销毁对象

本章主题是讲述创建和销毁对象,何时以及如何创建,何时以及如何销毁对象,如何确保他们能够适时读销毁,,以及如何管理对象销毁之前必须进行的各种清理工作。

  • 第一条:考虑用静态工厂

我们先来看看这个静态工厂方法,返回累的实例:

public static Boolean valueOf(boolean b){
return b?Boolean.TRUE:Boolean.FALSE;
}

通过调用该方法,就可以非常方便地利用工厂得到实例。

静态工厂和构造器不同的优势在于:

  1. 她们有名称,as what you can see。
  2. 不需要每次调用他们的时候都创建一个新的对象。
  3. 她们可以灵活地返回原类型的任何子类型对象。
  4. 在创建参数化实例的时候,她使得代码变得更加的简洁。

for example:

在我们使用带参构造器创建一个map时,需要这样:

Map<String,String> stringMap=new HashMap<String,String>();

但是,假设HashMap提供以下静态工厂:

public static <K,V> HashMap<K,V> newInstance(){
return new HashMap<K,V>();
}

那么我们在创建map的时候,就可以这样写了:

Map<String,String> stringMap =HashMap.newInstance();

倘若你在工作中常需要做创建对象的事,会不会有一丝的惊喜呢?

  • 第二条:遇到多个构造器参数时需要考虑使用构建器:

静态工厂和构造器有个共同的局限性,都不能很好地扩增到大量可选属性。

考虑一个人的资料,有些是必须要的,如Id,name,有些是可选的,如地区、身高,体重等。

方法一,带参构造器

package new_and_destory_object;
/*
* @author 莫仕豪
* moshihao@gmail.com muscle1990.com
* @version:2013-7-31 下午9:53:36
*
*/ public class Person {
private String id;//必选
private String name;//必选 private int height;//可选
private int weight;//可选
//private xxx ooo;//可选
//and so on...//可选 public Person(String id,String name){
this.id=id;
this.name=name;
} public Person(String id,String name,int height){
this.id=id;
this.name=name;
this.height=height;
} public Person(String id,String name,int height,int weight){
this.id=id;
this.name=name;
this.height=height;
this.weight=weight;
}
public Person(String id,String name,int height,int weight,xxx ooo,...){
this.id=id;
this.name=name;
this.height=height;
this.weight=weight;
...
}
}

然而,在我们创建对象的时候,就会这样:

Person Muscle=new Person("helloworld","Muscle",172,55,........);

如果有很多属性呢?我参与的实际项目中,遇到过超过150个属性的。使用构造器设参方法,难道我需要写上百个?再慢慢选?慢慢填数据?再save?oh my god!

方法二:javaBean setter 模式

package new_and_destory_object;
/*
* @author 莫仕豪
* moshihao@gmail.com muscle1990.com
* @version:2013-7-31 下午9:53:36
*
*/
public class Person {
private String id;//必选
private String name;//必选 private int height;//可选
private int weight;//可选
//private xxx ooo;//可选
//and so on...//可选
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
//...
}

这种方法深信大家也不会陌生,然而,同样的情况,属性多呢。。。

Person Muscle = new Person();
Muscle.setId("helloworld");
...

除此之外,因为构造过程被分到几次的调用,所以javaBean会产生不一致的可能状态。

方法三:builder模式

幸运的是,还有第三种替代方法,既能够保持像重叠构造器那样安全,又能像javaBean那样易读灵活。

package new_and_destory_object;

/*
* @author 莫仕豪
* moshihao@gmail.com muscle1990.com
* @version:2013-7-31 下午9:53:36
*
*/
public class Person {
private String id;// 必选
private String name;// 必选 private int height;// 可选
private int weight;// 可选 // and so on... public static class Builder {
// 必选属性
private final String id;
private final String name;
// 可选
private int height =0;
private int weight =0;
// and so on... public Builder(String id,String name){
this.id=id;
this.name=name;
}
public Builder height(int height){
this.height=height;
return this;
}
public Builder weight(int weight){
this.weight=weight;
return this;
}
// and so on... public Person build(){
return new Person(this);
}
} public Person(Builder builder) {
id =builder.id;
name =builder.name;
height =builder.height;
weight =builder.weight;
}
}

注意Person是不可变的。下面的创建对象的实现:

Person Muscle = new Person.Builder("helloworld","Muscle").height(173).weight(55).build();

这样的代码,就会变得非常容易编写,并且简洁易懂。

  • 第三条:用私有构造器或者枚举类型强化单例属性。

    public class Singleton{
    private static final Singleton INSTANCE =new Singleton();
    private Singleton(){...} public static Singleton getInstance(){return INSTANCE;}
    }

这部分暂时没多大感觉,单例用得比较少,不过也学习了。

  • 第四条:通过私有构造器,强化不可实例化的能力。

这个讲得不错,在HSBC Gltc的Interview的时候有问到。

  • 第五条:避免创建不必要的对象

这部分写得特别受用,不多说,来码:

String s=new String("String");//永远不要这样写代码,求你了

赋值的String已经为对象实例,这样就是等于多了一个实例,如果是在比较频繁的String操作,这样会产生成千上万无用的实例。

String s="String";//这样就可以了,简洁明了不浪费

还需要将可重用的重用,正如同书中例子一样,起点时间,终点时间设为static final,这样就可以了,完全没有必要每一次调用都实例化。

装箱拆箱问题:

public static void main(String args[]){
//需要拆箱时间:16s
//基本类型时间:2s
Long sum =0L;
for(long i=0;i<Integer.MAX_VALUE;i++){
sum +=1;
}
System.out.println(sum);
}

倘若你还不知道Long和long的区别的话,简单点说就是Long是对象,long是基本类型,他们转换需要装箱拆箱。而效率从上可见一般,优先使用基本类型,不要手滑写错类型。。。

  • 第六条:

消除过期对象引用

package new_and_destory_object;

import java.util.Arrays;
import java.util.EmptyStackException;
/*
* @author 莫仕豪
* moshihao@gmail.com muscle1990.com
* @version:2013-7-31 下午11:13:52
*
*/ public class Stack {
public Object[] elements;
private int size =0;
private static final int DEFAULT_ININAL_CAPACITY =16; public Stack(){
elements=new Object[DEFAULT_ININAL_CAPACITY];
}
public void push(Object e){
ensureCapacity();
elements[size++]=e;
}
public Object pop(){
if(0==size){
throw new EmptyStackException();}
return elements[--size];
} private void ensureCapacity() {
if(elements.length == size){
elements =Arrays.copyOf(elements, 2 *size+1);
}
}
}

因为栈会维护对象的过期引用,了解JVM内存管理的应该明白,有引用的对象,就算明知道是垃圾,一样不会回收。所以这段代码就算运行没有一点问题,但是会有导致内存溢出的风险。

我们需要修改弹出栈的操作:

public Object pop(){
if(0==size){
throw new EmptyStackException();
}
Object result =elements[--size];
elements[size] =null;
return result;
}

一般而言,只要是类自己管理内存,我们就需要警惕内存泄漏的发生。

除此之外,我们还需要注意,内存泄漏的另一个常见的来源是缓存。一旦你把对象放到缓存中,就很容易被淡忘。

  • 第七条:避免使用终结方法:

老实说,没用过,但是了解一下也是好的

  • 结言:

effective java读书小记(一)创建和销毁对象,这篇读书笔记连想带码,用了差不多两个小时的时间,很久没有这样写过读书笔记了,学海无涯,书山有路,加油!

Muscle Mo 2013.7.31.晚写于大学城宿舍

effective java读书小记(一)创建和销毁对象的更多相关文章

  1. 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器

    类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...

  2. Effective Java 读书笔记之一 创建和销毁对象

    一.考虑用静态工厂方法代替构造器 这里的静态工厂方法是指类中使用public static 修饰的方法,和设计模式的工厂方法模式没有任何关系.相对于使用共有的构造器来创建对象,静态工厂方法有几大优势: ...

  3. Effective Java(1)-创建和销毁对象

    Effective Java(1)-创建和销毁对象

  4. effective java 第2章-创建和销毁对象 读书笔记

    背景 去年就把这本javaer必读书--effective java中文版第二版 读完了,第一遍感觉比较肤浅,今年打算开始第二遍,顺便做一下笔记,后续会持续更新. 1.考虑用静态工厂方法替代构造器 优 ...

  5. Effective Java——(一)创建和销毁对象

    第一条 考虑用静态工厂方法代替构造器 什么叫静态工厂方法,就是通过在类中通过静态方法对对象初始化. 比如说 public class StaticFactory { private String na ...

  6. Effective Java 学习笔记之创建和销毁对象

    一.考虑用静态工厂方法代替构造器 1.此处的静态工厂方法是指返回指为类的对象的静态方法,而不是设计模式中的静态工厂方法. 2.静态工厂方法的优势有: a.使用不同的方法名称可显著地表明两个静态工厂方法 ...

  7. Effective Java(一)—— 创建和销毁对象

    在客户端(调用端)获取自身实例的方法: 公有的构造器: 类的静态工厂方法: 1. 使用静态工厂方法代替构造器 Boolean 是对基本类型 boolean 的包装类: public final cla ...

  8. 【Effective Java】第二章-创建和销毁对象——1.考虑用静态工厂方法代替构造器

    静态工厂方法的优点: 可以赋予一个具有明确含义的名称 可以复用唯一实例,不必每次新建 可以返回原实例类型的子类对象 可以在返回泛型实例时更加简洁 缺点: 类如果不含有共有的或者受保护的构造器,就不能被 ...

  9. 《Effective Java》读书笔记 - 2.创建和销毁对象

    Chapter 2 Creating and Destroying Objects item 1:Consider static factory methods instead of construc ...

随机推荐

  1. 3D数学学习笔记——笛卡尔坐标系

    本系列文章由birdlove1987编写.转载请注明出处. 文章链接: http://blog.csdn.net/zhurui_idea/article/details/24601215 1.3D数学 ...

  2. Is it always safe to call getClass() within the subclass constructor?(转)

    14down votefavorite   An article on classloading states that the method getClass() should not be cal ...

  3. c#有关udp可靠传输(包传输数据包) 升级

    在c#有关udp可靠传输(包传输数据包)我们讨论,UDP包的发送,可是上一个程序有一个问题.就是数据比較大.一个Message类序列化后都有2048B,而实际的数据量也就只是 50B罢了,这就说明当中 ...

  4. 至linuxNIC添加多个IP

    由于工作的需要,只是有一个2以太网端口server构造3个月IP.制linux. 整理如以下的现在的过程,有离开后,,学生们也将不能够引用. IP1:10.110.97.68 IP2:10.115.2 ...

  5. uva10827-Maximum sum on a torus(矩阵最大和的变形)

    题目;uva10827-Maximum sum on a torus(矩阵最大和的变形) 题目大意:就是uva108的变形,矩阵能够连通,就是能够从后面连到前面.这里把矩阵复制三遍,然后又一次生成一个 ...

  6. StyleCop中有一些官方自己写好的检测规则下面就是英文的解释

    在StyleCop中有一些官方自己写好的检测规则下面就是英文的解释 文档规则 1.SA1600:ElementsMustBeDocumented元素必须添加注释 2.SA1601: PartialEl ...

  7. linux_vim_快捷键

    1.vim ~/.vimrc 进入配置文件 如果不知道vimrc文件在哪,可使用 :scriptnames 来查看 set nu #行号 set tabstop=4 #一个tab为4个空格长度 set ...

  8. Metrics监控应用

    使用Metrics监控应用程序的性能   在编写应用程序的时候,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析.在很多时候,我们可能需要了解整个系统在当前 ...

  9. 【转】UiAutomator简要介绍

    原文地址:http://blog.csdn.net/g19920917/article/details/16131565 3.1.必备条件: 1.JDK    2.SDK(API高于15)    3. ...

  10. 【百度地图API】如何进行地址解析与反地址解析?——模糊地址能搜索到精确地理信息!

    原文:[百度地图API]如何进行地址解析与反地址解析?--模糊地址能搜索到精确地理信息! 摘要: 什么是地址解析? 什么是反地址解析? 如何运用地址解析,和反地址解析? 可以同时运用地址解析,和反地址 ...