论坛登陆 用户名:  密 码:
设为首页  加入收藏
08年北京名校秋季招生
名牌院校免试入学宽进严出,突破考分限制,名校与你零距离,以下院校按报名先后顺序录取,24小时网上报名覆盖全国
  您现在的位置: 中国教育招生在线 >> IT >> JAVA认证 >> IT正文
论全世界所有程序员都会犯的错误
 作者:佚名     2007-3-14 17:01:22        来源:不详  浏览次数:

 

 

 

 

 

 

 

 

当年,国际巨星成龙的“龙种”曝光,众人指责他对不起娇妻林凤娇,逼得他出面召开记者会,向世人自白他犯了“全世界所有男人都会犯的错误”。从来没犯过这种错误的我,也因此常常认为自己不是个男人。

虽然没犯过“全世界所有男人都会犯的错误”,但是我倒是曾经犯了“全世界所有程序员都会犯的错误”。不管使用何种语言,全世界所有程序员都一定犯过这种错误,那就是:太依赖编译器,却不知道编译器做了哪些事。

一般来说,越高阶的程序语言,会提供越多语法上的便利,以方便程序撰写,这就俗称为syntactic sugar,我称其为“语法上的甜头”。虽说是甜头,但是如果你未能了解该语法的实质内涵,很可能会未尝甜头,却吃尽苦头。

不久前,我收到一个电子邮件,读者列出下面的Java程序,向我求救。看过这个程序之后,我确定这又是一个“全世界所有程序员都会犯的错误”。

程序1

class Singleton 
{  
private static Singleton 
obj = new Singleton();  
public static int counter1;  
public static int counter2 = 0;  
private Singleton() {  
    counter1++;  
    counter2++;  
}  
public static Singleton getInstance() 
{  
    return obj;  
}  
}

程序2

public class MyMain {  
public static void main(String[] args) {  
    Singleton obj = Singleton.getInstance();  
    System.out.println("obj.counter1=="+obj.counter1);  
    System.out.println("obj.counter2=="+obj.counter2);  
}  
}

执行结果是:

obj.counter1==1  
obj.counter2==0

你有没有被此结果吓一跳?乍看程序代码,你很可能会认为counter1和counter2的值一定

会相等,但执行结果显然不是如此。其实,程序1被编译后的程序应该等同于下面的程序3

class Singleton 
{  
private static Singleton obj;  
public static int counter1;  
public static int counter2;  
static 
{ 
// 这就是class constructor  
// 在进入此class constructor之前,class已经被JVM  
// 配置好内存,所有的static field都会被先设定为0,  
// 所以此时counter1和counter2都已经是0,
且singleton为null  
obj = new Singleton();
// 问题皆由此行程序产生  
// counter1不会在此被设定为0  
    counter2 = 0;
	// counter2再被设定一次0(其实是多此一举)  
}  
private Singleton() 
{
// 这是instance constructor  
    counter1++;  
    counter2++;  
}  
public static Singleton getInstance() 
{  
    return obj;  
}  
}

这是因为:当class具有static field,且直接在宣告处透过“=...”的方式设定其值时,

编译器会自动将这些叙述依序搬到class constructor内。

同样地,当class具有instance field,且直接在宣告处透过“=...”的方式设定其值时,编译器会自动将这些叙述依序搬到instance constructor内。

此程序在class constructor内,还未将static field初始化时(这时候,counter1和counter2都是0),就呼叫instance constructor,而instance constructor竟然还会去更动static field的值,使得counter1和counter2都变成1。

然后instance constructor执行完,回到class constructor,再把counter2的值设为0(但是counter1维持不变)。最后的结果:counter1等于1,counter2等于0。

欲改正程序1,方法有三:

方法一:将singleton field的宣告调到counter1与counter2 field之后。这是最好的作法。

方法二:将counter2=0的宣告中,“=0”的部分删除。这种作法只有在希望。

方法三:将初始化的动作搬到class constructors内,自行撰写,而不依赖编译器产生。这是最保险的作法。

如何避免犯下“全世界所有程序员都会犯的错误”,我给各位Java程序员的建议是:

-熟读Java Language Specification

-在有疑问时,使用J2SDK所提供的javap来反组译Java Bytecode,直接观察编译后的结果。

下面是我用javap来反组译程序1的示范:

C:>javap -c -classpath . Singleton  
  
Compiled from MyMain.java  
class Singleton extends java.lang.Object
{  
    public static int counter1;  
    public static int counter2;  
    public static Singleton getInstance();  
    static {};  
}  
  
Method Singleton()  
   0 aload_0  
   1 invokespecial 
   #1 <Method java.lang.Object()>  
   4 getstatic 
   #2 <Field int counter1>  
   7 iconst_1  
   8 iadd  
   9 putstatic 
   #2 <Field int counter1>  
12 getstatic
#3 <Field int counter2>  
15 iconst_1  
16 iadd  
17 putstatic
#3 <Field int counter2>  
20 return  
  
Method Singleton getInstance()  
   0 getstatic 
   #4 <Field Singleton obj>  
   3 areturn  
  
Method static {}  
   0 new 
   #5 <Class Singleton>  
   3 dup  
   4 invokespecial 
   #6 <Method Singleton()>  
   7 putstatic 
   #4 <Field Singleton obj>  
10 iconst_0  
11 putstatic 
#3 <Field int counter2>  
14 return

其实Java的syntactic sugar并不算多,C#的syntactic sugar才真的是无所不在,也因此C#的初学者更容易犯了“全世界所有程序员都会犯的错误”。

许多C#的书都会一边介绍C#语法,一边介绍编译之后MSIL(.NET的中间语言,类似Java的Bytecode)的结果,然而Java的书却鲜少这么做。

虽说是“全世界所有程序员都会犯的错误”,但是这不代表你犯了此错误之后,仍可以“抬头挺胸、理直气壮”。只要有心,其实这一类的错误仍是可以避免的。

(T117)


责任编辑:lss
  相关新闻
世界经理人资讯有限公司招聘
实践Eclipse——讲解世界级IDE的技巧应用
javascript:世界上误解最深的语言
Java世界2006风起云涌 IDE谁领风骚?
Java世界2006风起云涌 IDE谁领风骚?
世界经理人资讯有限公司招聘
javascript:世界上误解最深的语言
Java世界2006风起云涌 IDE谁领风骚?
Java世界2006风起云涌 IDE谁领风骚?
实践Eclipse——讲解世界级IDE的技巧应用
  评论
现在有100人对本文发表评论
查看所有评论
 
推  荐
 
100本成功必读热销书
热门招生
  北京文理研修学院   前进大学
  北京明园大学   北京建设大学
  北京邮电大学世纪学院   北方工商管理学院
  联想软件定向委培班   香港数码动画学院
  青年企业管理研修学院   北京华夏管理学院
热门培训
网络化办公专家培训认证 电子科技大学软件学院
软件测试工程师培训认证 北大青鸟十大授权培训
IT硬件工程师培训认证班 北京环球雅思荷兰预科
JAVA开发工程师培训 潜能时代IT服务管理培训
网络信息化工程师培训 清华大学继续教育学院
论坛精选
 
有些细节是男人也该注意的风度!最容易读错的字
某强人手机里保存的30条短信 中国十大高薪职业
最感人的十大韩剧经典台词 嫁给工程师的N个理由
爆强!只有一句话的鬼故事 转贴教你如何做妖精
 女人一定要記住的話 女人最好别嫁给最爱的男人
城市联盟
 大连 上海 天津 广州 西安 深圳  天津  青岛  大连  福州  沈阳  青海  连云港  南京  吉林  厦门  威海  辽宁  呼和浩特
Copyright © 2006   www.edu999.com   All rights reserved. 中国教育招生在线  版权所有
北京市通信管理局[2004]字第552号函    京ICP证040442号