從C++到JAVA,C++程序員學習JAVA的指南

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

討論新聞組及文件

Technorati 標籤: JAVA ,C++ ,Python

JAVA is not just another programming language. -- 匿名

學習更新的語言,有助於瞭解別人對舊語言有哪些不滿。 -- 匿名

 

前言

先 說明本文的行文習慣,文章寫作流程以本人閱讀《Java Programming Language》爲順序,一般以一個本人認爲值得講的JAVA與C++不同的特性爲一個小節,每小節儘量以JAVA的新特性爲標題,首先對比 C++,JAVA,Python三者在此上的區別,然後展開討論。因爲沒有人能夠在每個領域都成爲專家,本人也是Python知識淺薄,並且新學 JAVA,C++也不過學了2,3年,以此學習方式純粹爲了對比學習,沒有厚此薄彼之意。雖然本人常常幾書在手,時常查閱,但是文中技術的硬傷因爲本人的 水平也就這樣,估計難以避免,也請大家指正。

 

1.原生整數類型的大小確定

C++ -- 類型大小一般規定最小值,整數類型豐富

JAVA -- 完全由標準定死原生整數類型的大小,整數類型豐富

Python -- 整數僅分標準整形和長整形,標準整形長度不確定,長整形

JAVA 的這個特點不算是太大的改動,但是比起C++來說實在是更爲方便。C++繼承了C的傳統,標準中原生類型都僅僅是建議最小的大小,具體多大的權利留給了編 譯器,因爲這種特性,流行着一句"一百家編譯器廠商就有一百種C++”的話。所以在C++中,我們通過typedef來獲取自己一般想要的大小,(到時候 想要改也方便)減少int的使用轉而使用長度更加確定的short,long,去減少整數類型大小不確定帶給我們可移植性的問題。

事實 上,這種特性可能是考慮到不同硬件對不同大小的值執行速度上的差異,比如16位機器一次處理16位整數的效率最高,32位的機器是32位,而64位則是 64位,C++作爲一門沒有完全脫離硬件並且不放棄底層開發市場的語言,無法不考慮這一點,所以纔有int的出現,用此類型來自適應當前機器最適合的類 型,其他類型也沒有強行的規定死,導致了sizeof的使用常常難以避免,特別是在數組等長度的計算時,sizeof的使用簡直就是標準用法,JAVA拋 棄了這種用法,確定了所有原生類型的大小,在一定程度上簡化了程序代碼。

Python的原生整數類型基本上完全使用標準整形,並且與支 持無限長度的長整形可以默認轉換,比JAVA的做法更加激進,事實上使用更加方便,最最重要的是解決了C++,JAVA都存在的數值溢出問題。但是提供給 程序員的選擇少了,方便是方便了,對於內存的精打細算的歪腦筋也沒有辦法打了。。。。

數值溢出問題就更是一個大問題了,多少不正常的歪 門邪道就由此而來啊,在定義數值的時候因爲沒有預計到原來可能的規模,最後不得已需要擴大,在大規模程序中也實在是噩夢一場。(我在工作中就碰到過不止一 次)而程序員數量較多時,對同一個意義的值使用了不同整數類型,相互之間傳遞時的溢出Bug,也是相當難以調試,也會使得明明經過自己單元測試的模塊最後 出現問題,這些,也許就只能放在Python的激進中,通過割捨了節省內存的手段才能解決了。在C++和JAVA中,可能需要更多對程序員的規定才能稍微 緩解此情況。

 

2.去掉了無符號整數的使用

C++ -- 整數類型可選擇有無符號

JAVA -- 完全由標準定死原生整數類型全部爲有符號

Python -- 全部有符號

C++ 中可以由unsigned選擇某個整數類型是否是無符號,默認爲有符號。雖然遵循着整形提升的原則,但是有無符號可以在計算中自動轉換,常常導致問題,這 一點在《C專家編程》1.10中Peter Van Der Linden有過描述,並且推薦大家不要在代碼中使用無符號類型,以免增加不必要的複雜性,但是事實上,在我的工作經歷中,公司對無符號的使用還是較多, 特別是對於那些不存在負數的值,甚至還偏向於使用無符號整數。但是,也不能將無符號整數說的一無是處,在位運算時,特別是位的偏移運算,無符號整數可以讓 我們減少對多情況的考慮,簡化代碼,在《C專家編程中》也是推薦只有在使用位段和二進制掩碼時,纔可以使用無符號數。

對於符號的問題, 本人使用C++中最爲印象深刻的是另外的問題。(也不能全部定性爲有無符號帶來的問題)工作中,很多遺留的代碼喜歡用-1來表示一個無符號數的最大值,事 實上,這樣做僅僅當類型是int時纔是安全的,其他情況下的確能夠獲取到最大的無符號數,但是比較的時候卻會帶來問題,不知道的話也常常會在調試時陷入鬱 悶當中,當時開發的程序常常通過網絡通信(服務器端的程序嘛),更加加大了問題的嚴重性,我甚至還幫同事調試過幾個這樣的問題。

比如下面這個例子:


#include 
using namespace std;

int main()
{
unsigned int d = -1;
cout <<d <<endl;

if(d == -1)
{
cout <<" d == -1" <<endl;
}
else
{
cout <<" d != -1" <<endl;
}

unsigned short s = -1;
cout <<s <<endl;

if(s == -1)
{
cout <<" s == -1" <<endl;
}
else
{
cout <<" s != -1" <<endl;

if(s == (unsigned short)-1)
{
cout <<" s == (unsigned short)-1" <<endl;
}
else
{
cout <<" s != (unsigned short)-1" <<endl;
}
}

return 0;
}

會輸出:

4294967295
d == -1
65535
s != -1
s == (unsigned short)-1

注意了,在C++中,unsigned short用-1賦值後,在與-1的比較中是不爲真,這種情況的避免一般可以通過兩種方式,一種是在所有的-1使用中全部加上確定的類型,如上面示例中所示,另一種就是全部棄用-1,而是使用0xFFFF…..的形式代替。

統一了符號後,這些問題自然不會存在了。

 

3.類成員變量默認初始化+使用棧上未初始化的變量無法通過編譯

C++ -- 使用未初始化的變量時,此變量值不確定,實際使用內存中的殘留數據,類及棧上的使用一樣

JAVA -- 類成員變量默認初始化+使用棧上未初始化的變量無法通過編譯

Python -- 動態類型語言,變量不需聲明,使用未定義的變量一律拋出運行時異常,NameError

C++的行爲簡直人神共憤。。。。。。。呵呵,當然,事實上,公司和C++使用者們就多出了很多規定了避免此事,比如使用變量時一律先初始化,哪怕 馬上就要用到了,比如分配了內存一律先memset,使用了數組一律先={0},使用指針,一律先=NULL,並且,推遲變量的定義,直到使用時然後才定 義變量,以防忘記初始化。

事實上,個人認爲還是效率上的考慮讓C++如此,(也許因爲繼承了C)假如都能像JAVA這樣不把效率作爲己任,C++要更好的多,C++的設計哲 學裏,可以不初始化的變量,爲啥一定要先初始化?呵呵,在C語言所有變量必須在塊的前面定義時,給每個變量一個無意義的初始值,也的確是有消耗的。

不用多說了,又是一例方便了程序員(但是耽誤了效率)的改進。

 

4.數組本身包含長度信息

C++ -- 原生數組本身無長度信息,但是Vector等容器有

JAVA -- 數組本身包含長度信息

Python -- 數組本身包含長度信息

C++中的原生數組不包含除本身元素外的任何信息,這種方式與C兼容,但是說實話,並不是太好用,使得使用數組的時候有諸多不便,比如傳遞參數時就 需要額外指定一個方式來表示結束方式,要麼傳長度,要麼傳結束指針,要麼如字符串以零結尾,都不算太好,雖然在STL中提供了Vector作爲替換方案, 但是使用中,常常因爲各種因素(與C兼容,節省內存等),還是常常使用原生數組,但是,說實話,習慣了這種思維,其實也不是什麼問題了,當然,對於初學者 來說,JAVA,Python這種萬物皆對象,數組本身就是一個類對象的方式會更容易接受一些,事實上,最簡單的來說,傳遞參數的時候參數數量會少一些, 使用也簡單,難以出錯一些。

 

5.數組訪問範圍檢測

C++ -- 數組訪問範圍不檢測,部分實現可提供可選檢測

JAVA -- 數組訪問範圍檢測,越界時,拋出ArrayIndexOutOfBoundsException異常

Python -- 數組訪問範圍檢測,越界時拋出IndexError: tuple index out of range

數組訪問範圍檢測不會讓C++中常見的越界訪問問題得到徹底解決,僅僅是運行時碰到時會拋出異常,方便了調試和發現問題。因爲此類問題雖然可以通過 良好的習慣儘量避免,但是一旦出現非常難以調試,難到出現莫名其妙的Bug時,公司的資深程序員第一反應就是數組訪問越界導致的問題(其實相對來說比率還 是比較小的),所以我很還是比較支持這種運行時檢測的,但是面試時現在公司的程序員老大說當我用了JAVA後就知道JAVA的數組訪問有多麼慢了,並且認 爲很大的原因就是因爲運行時的範圍檢測,因爲剛接觸JAVA,是對是錯,我暫時也不敢肯定,但是此話應該有參考價值。

 

後記:

此文是當時剛剛通過新公司的面試還沒有進入公司的時候寫的,因爲還沒有完善,一直沒有發佈,當時以爲自己在新公司會使用JAVA,所以趁還沒有進入 公司現鞏固一下(對JAVA的瞭解很少,僅大概看過《Thinking in JAVA》一書),但是事實進入公司以後,還是做C++的工作。。。。。。。所以,此係列,未完善的文章也先發布了,無意外的話,此係列還就此終結 了。。。。。。。。。。。。(假如以後有閒工夫或者工作真的換的時候再開始也未必可知)

 

 

 

參考資料

1.《Thinking In JAVA》,英文版,第4版,Bruce Eckel著,機械工業出版社

2.《JAVA Programming Language》,英文版,第4版,Ken Arnold,James Gosling,David Holmes著,人民郵電出版社

3.《JDK 6 Documentation 》,JAVA在線文檔集合

4.《The Java Language Specification, Third Edition

5.《Java™ Platform, Standard Edition 6 API Specification

6.《C專家編程》,Peter Van Der LinDen著,徐波譯,人民郵電出版社

7. 《Python核心編程》,Wesley J. Chun著,宋吉廣譯,人民郵電出版社

 

 

原創文章作者保留版權 轉載請註明原作者 並給出鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章