写博客我也不知道是不是一个好习惯,但是目前还不知道有什么其他更有效率的学习方法。现在的学习方法:看书,写博客。如果看明白一个东西,去写博客的话,这通常是一个浪费时间的行为,但是这个过程同样帮助自己二次记忆。并不知道写博客到底好不好。就先按照这个来吧。开始新的一本书,《Effective Java》

第一条:考虑用静态工厂方法代替构造器
优点

  • 静态工厂有名称(意味着什么应该都懂)
  • 不必在每次调用他们的时候都创建一个对象(可以通过单例模式联想)
  • 可以返回原类型任意子类型的对象(可以返回子类)
  • 创建待泛型的类的实例的时候,可以使代码更整洁

这一点需要举个例子(书中例子小改动)

class First1<K> {
public First1() {} public static <K> First1<K> getNewInstance() {
return new First1<K>();
}
}

如果用构造器

First1<String> first11 = new First1<String>();
First1<Map<String, List<String>>> first12 = new First1<Map<String, List<String>>>();

静态工厂:

    First1<String> first13 = First1.getNewInstance();

缺点:

  • 类不含有public/protected 的构造器就无法被子类化

举个例子

class First2 {
private First2() {}
} class First3 extends First2{
public First3(){}
}

上面代码在First3中会报错。父类无共有构造器,子类根本实例化不了。这时要想到设计原则中的多使用组合少使用继承。这个地方最好就不用继承了,让Frist3成为First2的一个成员变量。

  • 另一个缺点,实例化的方法和其他方法没区别。因此,在doc中不能一眼看出哪个是用来获取对象的。

第二条:遇到多个构造器参数时使用构造器

意思简单世界说,当构建一个对象的时候需要很多参数来创建一个对象。这时,可以重叠构造器,就是这个构造器调用下一个构造器,一个一个调用。如果参数少,这个办法比较好,如果有十个参数,想象一下。这时,可以用到JavaBean,无参构造器一个,然后不断的set各个参数,如果用这种方法,也就意味着,这个类在创建之后可以随意改动。这时,可以用下面的办法:


interface SupBuilder<T> {
    public T build();
  }

public class Second {
private int firP;
private int secP;
private int thiP;
private int fouP;
private int fivP; private Second(Builder buider) {
this.firP = buider.firP;
this.secP = buider.secP;
this.thiP = buider.thiP;
this.fouP = buider.fouP;
this.fivP = buider.fivP;
} public static class Builder implements SupBuilder<Second>{
private int firP;
private int secP;
private int thiP;
private int fouP;
private int fivP; public Builder(int firP, int secP) {
this.firP = firP;
this.secP = secP;
} public Builder thiP(int thiP) {
this.thiP = thiP;
return this;
} public Builder fouP(int fouP) {
this.fouP = fouP;
return this;
} public Builder fivP(int fivP) {
this.fivP = fivP;
return this;
} public Second build() {
return new Second(this);
}
} public static void main(String[] args) {
Second second = new Second.Builder(1, 2).thiP(3).fouP(4).build();
}
}

SupBuilder是附加的,根据项目,感觉需要就加上。这样,创建的时候用到了什么参数非常明显易读,最重要的易读,创建之后对象是不可变的。
怎么选择用静态工厂还是Builder,看创建对象时参数的多少。

第三条:用私有构造器或枚举类型强化Singleton属性

public enum Third {
INSTANTCE
}

这就能保证是一个单例,现在还没有真正领悟到枚举为什么好,用了枚举就不能定义成员了。

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

在项目中经常会有一些Util类中只包含静态方法和静态域的类,这些通常不需要实例化,实例化与不实例化也没有什么区别。但是在没有显示的构造器的情况下会默认的提供一个公有的构造器,就导致外部可以实例化这个类。如果把这个类设计成抽象类来防止实例化(抽象类和接口不能实例化),会给其他人错觉这个类是面向继承设计的。我们只需要在这个类中提供一个私有构造器,为了避免类内部会调用这个构造器,可以抛异常,但最好的做法是在上面添加注释:

// Noninstantialble util class
public class Fourth {
private Fouth(){}
}

注意:这样做了之后就无法被其他类继承了,因为没提供可调用的构造器。

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

最简单的错误做法:

String s = new String("word");  // nerver do this
String s = "word";

如果只是简单的想要一个String对象,别用new。
对于已知不会改变的可变对象也可以重用:

// wrong
private final Date date = new Date(); public int check() {
Calendar calendar = Calendar.getInstance();
calendar.set(2000, Calendar.JANUARY, 1);
Date startDate = calendar.getTime();
calendar.set(2017, Calendar.JANUARY, 1);
Date endDate = calendar.getTime();
if (date.getTime() > startDate.getTime() && date.getTime() < endDate.getTime()) {
return 1;
} return 0;
}

正确的做法:

  private final Date date = new Date();
private static final Date startDate;
private static final Date endDate; static {
Calendar calendar = Calendar.getInstance();
calendar.set(2000, Calendar.JANUARY, 1);
startDate = calendar.getTime();
calendar.set(2017, Calendar.JANUARY, 1);
endDate = calendar.getTime();
} public int check() {
if (date.getTime() > startDate.getTime() && date.getTime() < endDate.getTime()) {
return 1;
} return 0;
}

没修改的做法在compare方法中,没进一次方法就会创建一个Calendar对象,两个Date对象。修改后的只会在实例化类的时候分别创建出来,在方法中不断的重用。上面的做法对于创建实例后经常调用compare方法的程序,性能会有很大的提高。还有一点,如果类被实例化了,但是compare方法从来不会被调用,可以做到延迟加载,在用到compare方法的时候才去实例化,但是不建议这样做,这样会增加代码的复杂性。
现在java提供自动装箱的操作,自动装箱使基本类型和自动装箱类型变的模糊起来。看下面的代码:

    Long sum = 0L;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);

没进行一次+=操作,就会将根据long的数值重新生成一个Long,在进行下一次+=的时候,将Long转成long。会创建很多多余的对象。这里将Long类型的sum定义成long类型,效率就很提高很多。
这里说的不要创建多余对象并不是说尽量不创建对象,这里只是对于可以重用的对象只建一个然后不端重用。对于经常变的对象,不用考虑这点。

第六条:消除过期的对象
第七条:避免使用终结方法(finalizer)

在《深入了解java虚拟机》中有类似的内容。不在重复。

Effective java -- 1的更多相关文章

  1. Effective java笔记(二),所有对象的通用方法

    Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...

  2. 《Effective java》-----读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己!预计在2016年要看12本书,主要涉及java基础.Spring研究.java并 ...

  3. 《Effective Java》学习笔记——积累和激励

    从一个实际案例说起 国庆长假前一个礼拜,老大给我分配了这么一个bug,就是打印出来的报表数量为整数的,有的带小数位,有的不带,毫无规律. 根据短短的两个多月的工作经验以及猜测,最终把范围缩小到以下这段 ...

  4. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  5. effective java 读后感

    think in java  , effective java  这两本书一直都在java的生态圈中经久不衰.本来想着先翻过 think in java 这本大山,但是读到一半就放弃了.过长的篇幅,让 ...

  6. Effective java读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...

  7. effective java —— 终结方法守卫者

    目录: effective java —— 终结方法守卫者 effective java 第2章:创建和销毁对象.第7条 : 避免使用终结方法.最后的“终结方法守卫者 (finalizer guard ...

  8. Effective Java 创建和销毁对象

    <Effective Java>阅读笔记,用适合自己理解的方式提炼该书内容.<Effective Java>是一本很实用的书,阅读方法应该是快速的领会,总结,然后应用.而非,一 ...

  9. Effective Java

    Effective Java 创建和销毁对象---考虑用静态工厂方法代替构造器 构造器是创建一个对象实例最基本也最通用的方法,大部分开发者在使用某个class的时候,首先需要考虑的就是如何构造和初始化 ...

  10. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

随机推荐

  1. Oracle 时间 MM-dd形式转换

    SELECT TO_CHAR( SYSDATE,'MM-dd') AS beginTime,TO_CHAR( TO_DATE(MAX(C.SUBSCRIBE_DATE),'YYYY-MM-dd'),' ...

  2. java 乱码问题解决思路

    "编码一致的条件下,在处理运行正常的情况下,是不会出现乱码的",记住这句金言. 如上所说,如果编码一致是不会出现这种乱码问题,所以解决办法就是仔细再仔细的检查所设置的编码是否是一致 ...

  3. php给图片添加文字水印方法汇总

    在php中要给图片加水印我们需要给php安装GD库了,这里我们不介绍GD库安装,只介绍怎么利用php给图片添加文字水印的4种方法的汇总.有需要的小伙伴可以参考下. 1: 面向过程的编写方法 1 2 3 ...

  4. html 绘图阴影和透明度

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  5. mysql 集合函数与where条件

    这里要查询的是去过的国家数(country)的次数ct大于2的人的名字 select name ,count(country) ct from sz03 where ct >2 group by ...

  6. centos6搭建docker镜像私服

    1.创建私服容器 docker run -d -e SETTINGS_FLAVOR=dev -e STORAGE_PATH=/tmp/registry -v /opt/data/registry:/t ...

  7. 探究 Redis 4 的 stream 类型

    redis 2 10 月初,Redis 搞了个大新闻.别紧张,是个好消息:Redis 引入了名为 stream 的新数据类型和对应的命令,大概会在年底正式发布到 4.x 版本中.像引入新数据类型这样的 ...

  8. 09 nginx Rewrite(重写)详细解析

    一:Rewrite(重写)详细解析 rewrite 重写 重写中用到的指令 if  (条件) {}  设定条件,再进行重写 set #设置变量 return #返回状态码 break #跳出rewri ...

  9. 配置Nginx与tomcat负责均衡集群,

    今天主要说说,nginx如何配置tomcat集群,首先我们先介绍一下各个软件: 一: 1.Nginx介绍: 下载地址:http://nginx.org/en/download.html nginx这个 ...

  10. 网页上10秒倒计时,完了后就自动跳转到另一个网页上html代码

    用html代码的话就这样: <meta http-equiv="Refresh" content="10;URL=http://www.baidu.com" ...