effective java读书小记(一)创建和销毁对象
- 序言
《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;
}
通过调用该方法,就可以非常方便地利用工厂得到实例。
静态工厂和构造器不同的优势在于:
- 她们有名称,as what you can see。
- 不需要每次调用他们的时候都创建一个新的对象。
- 她们可以灵活地返回原类型的任何子类型对象。
- 在创建参数化实例的时候,她使得代码变得更加的简洁。
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读书小记(一)创建和销毁对象的更多相关文章
- 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器
类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...
- Effective Java 读书笔记之一 创建和销毁对象
一.考虑用静态工厂方法代替构造器 这里的静态工厂方法是指类中使用public static 修饰的方法,和设计模式的工厂方法模式没有任何关系.相对于使用共有的构造器来创建对象,静态工厂方法有几大优势: ...
- Effective Java(1)-创建和销毁对象
Effective Java(1)-创建和销毁对象
- effective java 第2章-创建和销毁对象 读书笔记
背景 去年就把这本javaer必读书--effective java中文版第二版 读完了,第一遍感觉比较肤浅,今年打算开始第二遍,顺便做一下笔记,后续会持续更新. 1.考虑用静态工厂方法替代构造器 优 ...
- Effective Java——(一)创建和销毁对象
第一条 考虑用静态工厂方法代替构造器 什么叫静态工厂方法,就是通过在类中通过静态方法对对象初始化. 比如说 public class StaticFactory { private String na ...
- Effective Java 学习笔记之创建和销毁对象
一.考虑用静态工厂方法代替构造器 1.此处的静态工厂方法是指返回指为类的对象的静态方法,而不是设计模式中的静态工厂方法. 2.静态工厂方法的优势有: a.使用不同的方法名称可显著地表明两个静态工厂方法 ...
- Effective Java(一)—— 创建和销毁对象
在客户端(调用端)获取自身实例的方法: 公有的构造器: 类的静态工厂方法: 1. 使用静态工厂方法代替构造器 Boolean 是对基本类型 boolean 的包装类: public final cla ...
- 【Effective Java】第二章-创建和销毁对象——1.考虑用静态工厂方法代替构造器
静态工厂方法的优点: 可以赋予一个具有明确含义的名称 可以复用唯一实例,不必每次新建 可以返回原实例类型的子类对象 可以在返回泛型实例时更加简洁 缺点: 类如果不含有共有的或者受保护的构造器,就不能被 ...
- 《Effective Java》读书笔记 - 2.创建和销毁对象
Chapter 2 Creating and Destroying Objects item 1:Consider static factory methods instead of construc ...
随机推荐
- Linux IPC(Inter-Process Communication,进程间通信)之管道学习
1.标准流管道 管道操作支持文件流模式,用来创建链接还有一个进程的管道,通过函数popen和pclose popen的详细介绍在本blog:Linux 多进程学习中有具体介绍 2.无名管道(PIPE) ...
- C# Windows Schedule task此次收购task下一步执行时间
最近进行了一次需求和Windows Schedule task相关职能,通过schedule,计算下一次运行task时间. 它用于由第三方DLL实现,以下网站,以下载来自: http://tasksc ...
- DevExpress.XtraReports.UI.XtraReport 动态报表
原文:DevExpress.XtraReports.UI.XtraReport 动态报表 using System;using System.Collections.Generic;using Sys ...
- opencv2对于读书笔记——二值化——thresholded功能
opencv二进制图象值功能threshold功能 其结构 double cv::threshold( //二值化函数 const CvArr* src, //原始图像 CvArr* dst, //输 ...
- 如何利用百度音乐播放器的API接口来获取高音质歌曲
第一步:在网页中打开以下网址: http://box.zhangmen.baidu.com/x?op=12&count=1&title=时间都去哪儿了$$王铮亮$$$$ 其中红色地方可 ...
- Java NIO的多路复用及reactor
(from:http://developer.51cto.com/art/201112/306489.htm) 以下描述,为了说明问题,就提提历史(类似的东西,网上一搜一大把,但是希望你能在这里止步, ...
- C语言学习之路,第一篇章。
看的书是 C primer plus ,这本书好评很多, 学过C#,没有精通,了解Java,所以看这本书会很容易上手,编译器用的是VC++6.0,因为VS2010好像不支持C99标准,有些代码功能 ...
- visual studio 辅助工具
resharper 这是一个收费软件 需要下载对应版本的注册机. 效果如图所示: 这里的using 很多没有用到,他会用灰色标记,你都可以统统去掉. 声明一个类 ,要求 首字母大写,如果你小写了,他 ...
- 兔子--gradle安装和配置
1.下载gradle,下载--all的这个 点击进入下载页 2.下载下来后,解压.配置环境变量. 编辑path , ....;G:\soft\gradle-2.2.1-all\gradle-2.2.1 ...
- C# 程序自动批量生成 google maps 的KML文件
原文:C# 程序自动批量生成 google maps 的KML文件 google maps 的 KML 文件可以用于静态的地图标注,在某些应用中,我们手上往往有成百上千个地址,我们需要把这些地址和描述 ...