`
kakaluyi
  • 浏览: 438918 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

优化代码的小技巧--读effect java有感

阅读更多

工作一年有余,已经早已不能算菜鸟了,最近工作也比较清闲,也接近年关,想好好补充下早已经被ssh给SM的不像样的知识。看什么好呢,是否需要看看高深点的书比如the pragmatic programmer、人月神话这类‘神作’。为以后架构师打打基础呵呵,但是思考半天还是拿出工作前看得一头雾水的effect java,想体验征服的快感,果然工作年余功力大增,那个是醍醐灌顶啊,一口气打通任督六脉

以下是书总帮忙自己梳理后,自己总结的早已经敲烂的小技巧,系统化一下,大牛就不要打击小弟了,

1 用private 的构造函数可以防止类被实例化,比如都是静态方法的帮助类,如果这些帮助类new foo(),然后调用静态方法是一件相当可笑的事。
2 避免String silly=new String("silly");的这种方法创建过多的无用的String对象,改为String silly="kaka";
小技巧:用Long.valueof("110") 代替new Long("110")来得到110的Long对象,避免创建无用Long对象
3 除了用静态工厂得到单例模式类的对象来避免重复创建对象,还可以你也可以复用那些你知道它们其实不会被更改的mutable
物件,下面是一个类isBabyBoomer()方法计算你是否是80后的年轻人,未来10年内我们要掌管世界,wahahahha!

public class Person {
private final Date birthDate;
// Other fields omitted
public Person(Date birthDate) {
this.birthDate = birthDate;
}
//但用下面的方法你就傻了,每次调用isBabyBoomer方法都要实例化一个Calendar的对象,狂消耗资源。
public boolean isBabyBoomer() {
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1980, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1990, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >= 0 &&
birthDate.compareTo(boomEnd) < 0;
}
}

 

下面的版本避免了这种低效率的动作,代之以一个static 块初始化Calendar对象,而且最体现效率的是,他的生命周期只实例化一次Calendar并且把
80年,90年的出生的值赋值给类静态变量BOOM_START和BOOM_END

class Person {
private final Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
/**
* The starting and ending dates of the baby boom.
*/
private static final Date BOOM_START;
private static final Date BOOM_END;
static {
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1980, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1990, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0 &&
birthDate.compareTo(BOOM_END) < 0;
}
}

 

改善后的Person class 只有在它被初始化的時候才惟一一次创建Calendar,
TimeZone, 和Date 实体,而不再是每次isBabyBoomer()被唤醒就创建它们。如
果该函数被频繁呼叫的話,這便可导致重大的效率提升。在我的机器上,原先版
本进行一百w次呼叫花费36,000 ms,改善版本只花了370 ms,几乎有100 倍快。
4不要被System.gc()和System.runFinalization()诱惑。它们确实可能提高
finalize()的执行可能,但不能保证其一定会执行。

5消除过期的object references

考虑下下面的stack代码碼:
// 你能找到内存泄露吗

 

public class Stack {
private Object[] elements;
private int size = 0;
public Stack(int initialCapacity) {
this.elements = new Object[initialCapacity];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
/**
* Ensure space for at least one more element, roughly
* doubling the capacity each time the array needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size) {
Object[] oldElements = elements;
elements = new Object[2 * elements.length + 1];
System.arraycopy(oldElements, 0, elements, 0, size);
}
}
}

每次pop后有没有发现有什么不对呢呵呵

6ssh敲久了,可能会忘记一些基础的东西,这里就有一点关于重写equal方法的。有个敲了5年java的老鸟也和我说hashcode()无用,如果你重写了object类的equal(),请一定重写hashcode(),如果不这样做
在hashmap,hashset中添加这些对象就不能对这些对象是否重复进行正确的判断,因为似乎这hashmap,hashset里面是用hash码来判断两对象是否重复的。
因为这个违反了object规范:如果两个对象equal,则必须使它们拥有相同的hashcode(),但是反之不成立!
所以重写你类里的equal方法,请一定重写类里的hashcode()!

未完待续。。。。。

2
1
分享到:
评论
1 楼 greatghoul 2009-01-07  
以前都没太这一这些细小问题,谢谢大哥的文章。

相关推荐

Global site tag (gtag.js) - Google Analytics