effective java笔记,effective java学习笔记

总共657条建议,随笔记录些

第一条:考虑用静态工厂来代替公开的构造方法

第二条:通过私有的构造函数来强化单例属性

两种单例模式:

模式一:

/**

* 通过构建一个公开静态的对象实例,来保持单例。

* 缺点:想改变单例为多例时,改动较大,若是想一直保持该类为单例的话,没问题,性能上也较高

*/

public static final Singleton2 instance = new Singleton2();

private Singleton2(){}

模式二:

/**

* 通过构建一个公开静态的方法来获得实例。

* 优点:想改变单例为多例时,修改方便

*/

private static final Singleton1 instance = new Singleton1();

private Singleton1(){}

public static Singleton1 getInstance()

{

return instance;

}

第三条:通过私有的构造函数来强化不可实例化

比如说我们需要编写一些全是静态方法或静态属性的类,该类不被实例化。

最好的例子就是工具类。java.util.Collections包。只提供公开,静态的方法来访问。

第四条:避免创建重复的对象

4.1

String s = new String(“haha”); // don’t do this 该语句每次都会new 一个新的对象出来,在循环中将会new出一堆的新对象

String ss = “haha”;这个方式新建的对象把放入JVM的池中,在循环中中再次调用时,不会new 一个新对象。

4.2

Boolean b = Boolean.valueOf(“true”); 这个是利用静态工厂来获得对象,只会新建一个新的对象

Boolean b1 = new Boolean(“true”); 通过构造方法来获得对象的方式则会新建一个对象

在新建一个类的时候,尽量使用对方提供的静态工厂来获得实例,因为在其中还可以做到延迟加载的效果。

4.3

对于一些不变的变量,特别是定义在循环中的变量,如果其值是不变,那么可以考虑设置为static final 。

在static 块中进行赋值。能够大大减少系统的开销。至少可以减少100倍的耗时。在1000000次循环的情况下。

4.4

对于现代的JVM来说,小对象的创建和回收是非常廉价的,建立多使用。不过在循环中例外。

第五条:消除过期的对象引用

例如说在一个栈中,我们pop一个元素后,在数组中指向该对象的引用起始已经是无效了,但是JVM不知道,还在这个数组中保持着对该对象的引用,不会去清理该片内存,如果一直操作这个栈的话就可能会引起内容泄露。

良好的做法就是设置数组pop的这个位置的引用指向null。

即,只要一个类自己管理一片内容的话,就需要考虑内存泄露的问题。

内存泄露还有可能就是缓存

第六条:避免使用终结函数

暂时没看明白

第七条:改写equals尽量遵守的约定

7.1 在进行比较时,不需要进行 null 值比较,可以直接采用instanceof 中为null则直接返回false

7.2 域的比较顺序也会影响性能,最新比较的域应该是最容易发生改变的域。

7.3 改写equals的时候一般要改写hashCode()

7.4 不要让equals方法过于聪明

7.5 不要让equals依赖于不可靠的因素

7.6 不要把其中的Object替换成其他的对象

如:

@Override

public boolean equals(OutOfMenery arg0)

{

return false;

}

一个相对较好的equals方法

@Override

public boolean equals(Object arg0)

{

if (!(arg0 instanceof OutOfMenery)) return false; //这里已经做了null值判断

if (arg0 == this) return true;

OutOfMenery cMenery = (OutOfMenery)arg0;

return cMenery.size == this.size;

}

第八条:重写equals必须重写hashCode

8.1规范

1. 同一个程度中如果对象的值没有变化,那么多次调用hashCode方法必须返回同一个整数

2. 如果两个对象的equals方法相同,那么调用hashCode的方法也必须相同

3. 如果两个对象的equals方法不用,不要求hashCode的方法返回相同的值,不过为了散列跟均匀,建议返回相同的值。

8.2 非常不建立使用下种方式来实现hashCode,因为如此会将一个散列表整成一个链表。导致线性运行的程序成平方运行时间。

@Override

public int hashCode()

{

return 42;

}

8.3 方法实现的小建议

1. 把某个非0常数,比如17.保存在一个较results的变量中

2. 对于对象的每一个域做一下操作 计算散列码 c

2.1 boolean —> c = f?0:1

2.2 byte char short int — > (int)f;

2.3 long 类型 –> (int)(f^f >>> 32);

2.4 float 类型 — > Float.floatToIntBits()转化为int

2.5 double 类型 — > Double.doubleToLongBits() 转化为int

2.6 对象的引用,那么直接调用对象的hashCode()方法,具体在对象中自己实现。如果对象为null 那么就设置为0

2.7 数组,把数组中的每一个值作为单独的域来处理。递归的引用上面的规则。

3. 按照下面的公式来套用2中计算得到的 c

result = result*37 +c ; //选择37是因为37是一个素数

下列就是按照上面的规则进行的计算

@Override

public int hashCode()

{

int result = 17; //设置常量

result = result*37 + area; //转为int 计算

result = result*37 + exchange;

result = result*37 +extention;

return result; //返回自己需要的值

}

4.若是计算的hashCode非常复制,计算代价太大,那么可以将它放到系统缓存中。

private volatile static int hashCode = 0; //这样是作为一个缓存,并做lazy-initialized

@Override

public int hashCode()

{

if ( 0 == hashCode)

{

int result = 17;

result = result*37 + area;

result = result*37 + exchange;

result = result*37 + extention;

hashCode = result;

}

return hashCode;

}

第九条:总是要改写toString()

建议一定要改写该方法。

最好是指定一种格式来来覆盖该方法,可以的话提供一个公开静态的方法来解析toString后的方法。

第十条:谨慎的改写clone()方法

首先需要实现cloneanle接口,标示该类是允许clone的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值