Java开发网 |
注册 |
登录 |
帮助 |
搜索 |
排行榜 |
发帖统计
|
您没有登录 |
» Java开发网 » Java SE 综合讨论区
» 实战错误讨论
打印话题 寄给朋友 订阅主题 |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:cxp108] |
九佰
版主 发贴: 983 积分: 126 |
于 2009-01-23 17:10
这么做是有道理的。 请看下面的讲解: JVM中对象的生命周期 在JVM运行空间中,对象的整个生命周期大致可以分为7个阶段:创建阶段(Creation)、应用阶段(Using)、不可视阶段(Invisible)、不可到达阶段(Unreachable)、可收集阶段(Collected)、终结阶段(Finalized)与释放阶段(Free)。上面的这7个阶段,构成了JVM中对象的完整的生命周期。下面分别介绍对象在处于这7个阶段时的不同情形。 2.2.1 创建阶段 在对象创建阶段,系统要通过下面的步骤,完成对象的创建过程: (1)为对象分配存储空间。 (2)开始构造对象。 (3)递归调用其超类的构造方法。 (4)进行对象实例初始化与变量初始化。 (5)执行构造方法体。 上面的5个步骤中的第3步就是指递归地调用该类所扩展的所有父类的构造方法,一个Java类(除Object类外)至少有一个父类(Object),这个规则既是强制的,也是隐式的。你可能已经注意到在创建一个Java类的时候,并没有显式地声明扩展(extends)一个Object父类。实际上,在Java程序设计中,任何一个Java类都直接或间接的是Object类的子类。例如下面的代码: public class A { … } 这个声明等同于下面的声明: public class A extends java.lang.Object { … } 上面讲解了对象处于创建阶段时,系统所做的一些处理工作,其中有些过程与应用的性能密切相关,因此在创建对象时,我们应该遵循一些基本的规则,以提高应用的性能。 下面是在创建对象时的几个关键应用规则: (1)避免在循环体中创建对象,即使该对象占用内存空间不大。 (2)尽量及时使对象符合垃圾回收标准。 (3)不要采用过深的继承层次。 (4)访问本地变量优于访问类中的变量。 关于规则(1)避免在循环体中创建对象,即使该对象占用内存空间不大,需要提示一下,这种情况在我们的实际应用中经常遇到,而且我们很容易犯类似的错误,例如下面的代码: … … for (int i = 0; i < 10000; ++i) { Object obj = new Object(); System.out.println("obj= "+ obj); } … … 上面代码的书写方式相信对你来说不会陌生,也许在以前的应用开发中你也这样做过,尤其是在枚举一个Vector对象中的对象元素的操作中经常会这样书写,但这却违反了上述规则(1),因为这样会浪费较大的内存空间,正确的方法如下所示: … … Object obj = null; for (int i = 0; i < 10000; ++i) { obj = new Object(); System.out.println("obj= "+ obj); } … … 采用上面的第二种编写方式,仅在内存中保存一份对该对象的引用,而不像上面的第一种编写方式中代码会在内存中产生大量的对象应用,浪费大量的内存空间,而且增大了系统做垃圾回收的负荷。因此在循环体中声明创建对象的编写方式应该尽量避免。 另外,不要对一个对象进行多次初始化,这同样会带来较大的内存开销,降低系统性能,如: public class A { private Hashtable table = new Hashtable (); public A() { // 将Hashtable对象table初始化了两次 table = new Hashtable(); } } 正确的方式为: public class B { private Hashtable table = new Hashtable (); public B() { } } 不要小看这个差别,它却使应用软件的性能相差甚远,如下图所示。 http://www.teamlet.org 海纳百川,有容乃大 壁立千仞,无欲则刚 智者不惑,勇者无惧 止戈为武,仁者无敌 |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:JiafanZhou] |
cxp108
发贴: 363 积分: 12 |
于 2009-02-01 10:31
JiafanZhou wrote: 是挺严重的,因为比较隐蔽。 |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:cxp108] |
menzy
版主 发贴: 754 积分: 113 |
于 2009-02-04 15:35
这个错误说明,此人对对象生命周期并不了解 BTW: 如果这个人以前用过C++,发生这种问题的几率会降低 |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:Biubiu] |
cxp108
发贴: 363 积分: 12 |
于 2009-02-04 18:23
Biubiu wrote: 我觉得这是一个很基础的错误,一个资深工程师 不应该犯这种错,而且还和我争了半天说他没错 ,最后是他自己写代码验证才不说话。 |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:cxp108] |
cxp108
发贴: 363 积分: 12 |
于 2009-02-04 18:30
怎么进来的都是版主?? |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:breezehou] |
ditty
负资产小资 CJSDN高级会员 发贴: 1038 积分: 143 |
于 2009-02-11 15:08
其实,说白了就是在循环体内,忘记了初始化对象d而已。 既然是资深,还是需要得到尊敬,lz有些借题发挥的味道。 内忧外患的时代,洗心革面,阿咪豆腐~ |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:cxp108] |
JiafanZhou
版主 发贴: 736 积分: 61 |
于 2009-02-19 23:56
Today, I wrote a very simple unit test class to test the performance of clone() and new instance. Believe it or not, I am surprised to find out that the clone() method is much slower than the new instance. I will also attach the source code "CloneTest.java" for anyone who is interested to see the test result. After a little bit googling, I have a conclusion that actually in the HotSpot JVM Object.clone() is not currently heavily optimized, while new instance is. From now on, I will not use the clone() methods any more I believe. Following the the test result of both clone(), create a new instance, and the System.copyarray() methods. -------------------------------------------------------------------- Time to excute 1000000 clone() takes 262 milliseconds Time to excute 1000000 new Object() takes 29 milliseconds Time to excute 1000000 System.arrayCopy takes 17 milliseconds -------------------------------------------------------------------- Also I found out a very interesting thread about the comparison between clone() and creating a new instance, see the following link: http://forums.java.net/jive/thread.jspa?threadID=743 Now, I would suggest another solution which is shown below:
cxp108 wrote: Do you really have a performance hit here? If so, then using object pool or java NIO is worthy looking at. Otherwise, it could be just some features overkilled. IMO. Jiafan CloneTest.java (2.07k) When I was a kid I used to pray every night for a new bike. Then I realized that The Lord doesn't work that way, so I stole one and asked him to forgive me. |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:cxp108] |
tangming
发贴: 140 积分: 20 |
于 2009-02-24 17:40
为什么要用clone, pool,是因为new一个对象需要比较大的代价,比如new一个Connection,而对于上面的CloneTest对象来说,new一个根本不需要做什么操作,new比clone快也很正常。 |
作者 | Re:一位“资深”同事为了对象重用,而写下的代码.... [Re:cxp108] |
wuanfo
发贴: 5 积分: 0 |
于 2009-04-08 08:44
学习了。 |
已读帖子 新的帖子 被删除的帖子 |
Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1 客服电话 18559299278 客服信箱 714923@qq.com 客服QQ 714923 |