編程技術(shù) - 全世界所有程序員都會(huì)犯的錯(cuò)誤
更新時(shí)間: 2007-05-28 13:07:37來(lái)源: 粵嵌教育瀏覽量:759
當(dāng)年,國(guó)際成龍的「龍種」曝光,眾人指責(zé)他對(duì)不起嬌妻林鳳嬌,逼得他出面召開(kāi)記者會(huì),向世人自白他犯了「全世界所有男人都會(huì)犯的錯(cuò)誤」。從來(lái)沒(méi)犯過(guò)這種錯(cuò)誤的我,也因此常常認(rèn)為自己不是個(gè)男人。
雖然沒(méi)犯過(guò)「全世界所有男人都會(huì)犯的錯(cuò)誤」,但是我倒是曾經(jīng)犯了「全世界所有程序員都會(huì)犯的錯(cuò)誤」。不管使用何種語(yǔ)言,全世界所有程序員都一定犯過(guò)這種錯(cuò)誤,那就是:太依賴(lài)編譯器,卻不知道編譯器做了哪些事。
一般來(lái)說(shuō),越高階的程序語(yǔ)言,會(huì)提供越多語(yǔ)法上的便利,以方便程序撰寫(xiě),這就俗稱(chēng)為syntactic sugar,我稱(chēng)其為「語(yǔ)法上的甜頭」。雖說(shuō)是甜頭,但是如果你未能了解該語(yǔ)法的實(shí)質(zhì)內(nèi)涵,很可能會(huì)未嘗甜頭,卻吃盡苦頭。
不久前,我收到一個(gè)電子郵件,讀者列出下面的Java程序,向我求救。看過(guò)這個(gè)程序之后,我確定這又是一個(gè)「全世界所有程序員都會(huì)犯的錯(cuò)誤」。
// 程序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);
}
}
執(zhí)行結(jié)果是:
obj.counter1==1
obj.counter2==0
你有沒(méi)有被此結(jié)果嚇一跳?乍看程序代碼,你很可能會(huì)認(rèn)為counter1和counter2的值一定會(huì)相等,但執(zhí)行結(jié)果顯然不是如此。其實(shí),程序1被編譯后的程序應(yīng)該等同于下面的程序3:
// 程序3
class Singleton {
private static Singleton obj;
public static int counter1;
public static int counter2;
static { // 這就是class constructor
// 在進(jìn)入此class constructor之前,class已經(jīng)被JVM
// 配置好內(nèi)存,所有的static field都會(huì)被先設(shè)定為0,
// 所以此時(shí)counter1和counter2都已經(jīng)是0,且singleton為null
obj = new Singleton(); // 問(wèn)題皆由此行程序產(chǎn)生
// counter1不會(huì)在此被設(shè)定為0
counter2 = 0; // counter2再被設(shè)定一次0(其實(shí)是多此一舉)
}
private Singleton() { // 這是instance constructor
counter1++;
counter2++;
}
public static Singleton getInstance() {
return obj;
}
}
這是因?yàn)椋寒?dāng)class具有static field,且直接在宣告處透過(guò)「=...」的方式設(shè)定其值時(shí),編譯器會(huì)自動(dòng)將這些敘述依序搬到class constructor內(nèi)。同樣地,當(dāng)class具有instance field,且直接在宣告處透過(guò)「=...」的方式設(shè)定其值時(shí),編譯器會(huì)自動(dòng)將這些敘述依序搬到instance constructor內(nèi)。
此程序在class constructor內(nèi),還未將static field初始化時(shí)(這時(shí)候,counter1和counter2都是0),就呼叫instance constructor,而instance constructor竟然還會(huì)去更動(dòng)static field的值,使得counter1和counter2都變成1。然后instance constructor執(zhí)行完,回到class constructor,再把counter2的值設(shè)為0(但是
counter1維持不變)。的結(jié)果:counter1等于1,counter2等于0。
欲改正程序1,方法有三:
-方法一:將singleton field的宣告調(diào)到counter1與counter2 field之后。
這是的作法。
-方法二:將counter2=0的宣告中,「=0」的部分刪除。這種作法只有在希望
-方法三:將初始化的動(dòng)作搬到class constructors內(nèi),自行撰寫(xiě),而不依賴(lài)
編譯器產(chǎn)生。這是保險(xiǎn)的作法。
如何避免犯下「全世界所有程序員都會(huì)犯的錯(cuò)誤」,我給各位Java程序員
的建議是:
-熟讀Java Language Specification
-在有疑問(wèn)時(shí),使用J2SDK所提供的javap來(lái)反組譯Java Bytecode,直接觀察
編譯后的結(jié)果。
下面是我用javap來(lái)反組譯程序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
4 getstatic #2
7 iconst_1
8 iadd
9 putstatic #2
12 getstatic #3
15 iconst_1
16 iadd
17 putstatic #3
20 return
Method Singleton getInstance()
0 getstatic #4
3 areturn
Method static {}
0 new #5
3 dup
4 invokespecial #6
7 putstatic #4
10 iconst_0
11 putstatic #3
14 return
其實(shí)Java的syntactic sugar并不算多,C#的syntactic sugar才真的是無(wú)所不在,
也因此C#的初學(xué)者更容易犯了「全世界所有程序員都會(huì)犯的錯(cuò)誤」。許多C#的書(shū)都會(huì)一邊介紹C#語(yǔ)法,一邊介紹編譯之后MSIL(.NET的中間語(yǔ)言,類(lèi)似Java的Bytecode)的結(jié)果,然而Java的書(shū)卻鮮少這么做。
雖說(shuō)是「全世界所有程序員都會(huì)犯的錯(cuò)誤」,但是這不代表你犯了此錯(cuò)誤之后,仍可以同愛(ài)借錢(qián)的曹啟泰一般地「抬頭挺胸、理直氣壯」。只要有心,其實(shí)這一類(lèi)的錯(cuò)誤仍是可以避免的。
粵嵌動(dòng)態(tài)
推薦閱讀
- ·Linux字符設(shè)備驅(qū)動(dòng)框架解析:file_operations的核心作用與實(shí)現(xiàn)
- ·廣東朝歌數(shù)碼科技股份有限公司專(zhuān)場(chǎng)招聘會(huì)
- ·深化產(chǎn)教融合,共筑技能人才培養(yǎng)新生態(tài) —— 廣州華立學(xué)院到訪粵嵌從化校區(qū)為深化產(chǎn)教
- ·校企合作新突破 | 粵嵌科技與三亞學(xué)院共探產(chǎn)教融合新路徑
- ·粵嵌科技入選國(guó)家級(jí)職業(yè)數(shù)字展館聯(lián)合建設(shè)單位,賦能計(jì)算機(jī)程序設(shè)計(jì)員高技能人才培養(yǎng)
- ·嵌入式實(shí)時(shí)操作系統(tǒng)的性能優(yōu)化與實(shí)現(xiàn)路徑
- ·校企攜手賦能教育!粵嵌科技助力海南科技職業(yè)大學(xué)探索 AGI 時(shí)代教學(xué)新范式
- ·嵌入式系統(tǒng)中的低功耗設(shè)計(jì)策略與實(shí)現(xiàn)路徑
- ·深圳市軒宇軟件開(kāi)發(fā)有限公司專(zhuān)場(chǎng)招聘會(huì)
- ·嵌入式系統(tǒng)中的代碼空間優(yōu)化:策略與實(shí)踐