跳至內容

Java和C++的對照

出自Taiwan Tongues 台語維基
這是此頁批准,以及是最近的修訂。

本條目為Java 語言佮 C + + 語言之間的比較

設計目標

C + + 和 Java 語言之間的無仝會當追溯到𪜶各自的傳統,𪜶有著無仝的設計目標。

  • C + +予人設計做主要用佇系統性應用程式設計上的語言,著 C 語言進行矣擴展。是因為 C 語言這為執行效率設計的過程序程式設計語言,C + + 添加著對遮的特性的支援:靜態類型的東西導向程序設計的支援、異常處理、RAII 猶閣有泛型。另外伊閣添一个包含泛型容器佮演算法的 C + + 庫函式。
  • Java上早予人設計用來支援網路計算。伊依賴一个虛擬機來保證安全佮可能會當徙栽性。Java 包含一个會當擴展的庫以提供一个完整的下層平台抽象。Java 是一種靜態面向物件語言,伊使用的語法佮 C + + 類似,但並無與之相容。為著欲使用閣較濟人來使用的語言,伊進行了全新的設計。

無仝款的開發目標致使著 C + + 和 Java 這兩種語言的無仝的規則以及設計的平衡點無仝。 如下列出無仝款:

C + + 是一門強大的語言,設計用佇系統程式設計方面。Java 語言是設計成簡單簡單用易學習,並且有一个強大的跨平台的庫。Java 函式庫對一个函式庫來講相當的大。猶毋過 Java 並袂提供所佇平台的所有特性佮介面。C + + 函式庫簡單勇健,提供容器佮關聯數組的支援。

語言特性

語法

  • Java 語法是懸頂下文無關文法,會當用一个簡單的 LALR 語法的分析器來分析。毋過分析 C + + 就複雜濟矣;比如講 ` Foo < 一 > ( 三 ) ; `,若是 Foo 是一个變數,按呢伊是一个較的運算式,但是若準講 Foo 是一个類範本的名,伊會建立一个物件 .
  • C + + 允准號名空間級別的常數,變數佮函式。所有的按呢的 Java 聲明著愛佇一个類或者是介面當中 .
  • 佇咧 C + + 的聲明中間,一个類名會當用來聲明一个這種物件的值 . Java 內底無法度做甲這點。佇咧 Java 內底毋是值。佇咧 Java 的聲明中間,一个類名聲明的是對這種物件的 _ 參照 _ . 啊若佇咧 C + + 內底佮人等價的做法是用 " \ * " 來聲明一个指標 .
  • 佇咧 C + + 內底," . " 運算子嘛將一个物件做一个左指令引數來存取這个物件的成員。因為東西在 Java 內底毋是講價值,所有的物件攏通過參照來存取,拄仔彼做法佇咧 Java 內底是無法度實現的。佇咧 Java 內底," . " 算子是共一个物件的參照做為左指令引數來存取這个物件的成員。佇咧 C + + 中和這種做法等價的是 "-> " .
  • 佇咧 C + + 內底,定義一个指向常數的指標(唯讀指標)是可能的,也就是講,你袂當修改這个指標指向的物件的內容。函式佮方法嘛攏保證袂曉修改用 " const " 關鍵字的指標指向的物件的內容,是強制常數正確性的。佇咧 Java 內底這無可能做會到的。你會當定義一个參照為 " final "(就親像佇咧 C + + 內底定義一个指標 " 常數 "), 但是這干焦共你擋重新縛定這个參照;你猶是會當修改這 " final " 參照指向的物件的 .
  • C + + 支援 ` goto ` 語句;Java 強制結構化流程控制 ( structured control flow ),依賴 break 標籤佮 continue 標籤的語句來提供類似講 goto 伊的部份功能。一寡評論者指出遮的標籤化的流程控制拍破去結構化程式設計的單登出點的特點 .
  • C + + 提供一寡 Java 欠缺的低級特性。佇咧 C + + 內底,指標會當用來操作特定的記憶體位置,這是咧寫低級作業系統模組的時陣著愛用著的。類似的,真濟 C + + 編譯期支援內底聯彙編,佇咧 Java 內底,這款的代碼干焦會當囥佇外來的庫中,而且咧調用的時陣干焦會當通過 JNI 來取遮的外來庫提供的介面 .

語意

  • C + + 允准予函式 / 方法的偏好設定預設值,Java 無提供這個特性。但是方法多載會當達到仝款的效果 .
  • C + + 里上細的編譯單位是一个函式;Java 里上細的編譯單位是一个類。佇咧 C + + 里,函式會當被單獨編譯。佇咧 Java 里,欲編譯佮維護單獨的方法需要共徙去超類或者是子類或者是使用其他的代碼重構的技巧 .
  • C + + 允准基本類型之間的一寡隱式的轉換,也允准程式設計師對使用者自訂類型相關的隱式轉換規則。佇咧 Java 里,只有基本類型之間變闊類型的轉換會當是隱式的;賰的轉換需要顯式的類型轉換語法 .
  • 這造成的一个後果是,雖然講佇 Java 和 C + + 里循環的條件(` if `、` while ` 和 ` for ` 里的登出條件)預期的攏是一个布爾表達式,猶毋過 ` if ( a=五 ) ` 按呢的代碼佇咧 Java 里會致使編譯錯誤,因為無對整型到布爾的隱式變狹轉換。若代碼是 ` if ( a==五 ) ` 的運輸毋著的情形遐爾仔是足方便發現這个錯誤的。這馬的 C + + 編譯器一般來講干焦會針對這款的情況產生一个警告 .
  • 對傳參數予函式的狀況,C + + 支援參照傳遞佮值傳遞。佇咧 Java 里,參數總是值傳遞的。猶毋過佇 Java 里,所有的非基本類型的值攏只是對物件的參照(用 C + + 的術語來講,𪜶是智慧型指針). 物件佇 Java 里毋是做直接被使用的,干焦物件的參照會當直接提去操作;慣勢佇將物件當做值直接使用的 C + + 開發者定定會共這佮參照傳達達 .
  • Java 內建的類型佇咧位元組闊度佮取值範圍頂頭是予虛擬機定義好的;佇咧 C + + 里,內建的類型有定義一个上小取值的範圍,但是其他的部份(位元組闊度)會當予對映做具體平台上支援的原生類型 .
  • 比一个例,Java 字元是十六位元的 Unicode 字元,字串是對這款的字元組成的序列 . C + + 提供狹佮闊兩種字元,但實際的字元寬度是和平台相關的,視所用的字元集來定。這字串會當對這兩種字元的一種組成 .
  • 浮點數佮操作的精度佮較捨入方式佇咧 C + + 里是平台相關的 . Java 提供一个可選的嚴格的浮點數模型,保證跨平台的一致性,毋過可能會致使運行的時效率較䆀 .
  • 佇咧 C + + 里,指針會當做記憶體位址直接操作 . Java 無指針喔—伊干焦和數組參照,這兩个攏無允准直接用來存取記憶體位址。佇咧 C + + 會當構造一个指向指針的指針,而且 Java 的參照干焦會當指向物件 .
  • 佇咧 C + + 里,指針會當指向函式抑是方法(函式指針). 佇咧 Java 里的遮的價數是物件抑是介面的參照 .
  • 雖然有使用棧記憶體分配的物件,C + + 抑是支援區域資源管理,隨用來自動管理記憶體佮其他系統資源的技術,此技術支援確定性物件銷毀 ( deterministic object destruction ) . 猶毋過,區域資源管理佇 C + + 里是無愛予人保證的;伊只是一个設計模式,所以需要依賴程式設計師遵守相關的規則 . Java 通過使用糞埽搜集來支援自動記憶體管理,毋過對其他的系統資源(窗口,通訊埠頭,執行緒), 若糞埽搜集器無法度決定講𪜶敢是無閣被用著,彼通常抑是需要顯式的釋放的 .
  • C + + 的使用者會當自訂運算子加載的特性佇 Java 里是無支援的。唯一佇咧 Java 里會當重載的運算子是 " ` + ` " 和 " ` +=` " 運算子,踮字串里濟載做連接字串 .
  • Java 的標準應用程序介面支援反射佮動態載入任意代碼 .
  • C + + 支援靜態佮動態的庫連接 .
  • Java 支援泛型,其主要目的是提供類型安全的容器 . C + + 支援模板,佇泛型程式設計方面提供了閣較強的支援 .
  • Java 和 C + + 攏對基本的類型(嘛叫 " 內建 " 類型)佮使用者自訂類型(嘛叫 " 複合 " 類型). 佇咧 Java 里,基本類型只有值的語義,複合類型只有參照的語義。佇咧 C + + 里所有的值攏有值語義,會當建立對任何類型的參照,按呢就允准通過參照語義來操作物件 .
  • C + + 支援任意類型的偌重繼承。佇咧 Java 里一个類干焦會當對單一个類繼承來,就是但是一个類會當實現濟个介面(嘛會使講,伊支援類型的偌重繼承,但是對實現干焦會當繼承 ( it supports multiple inheritance of types , but only single inheritance of implementation ))。
  • Java 對類和介面是顯式區分的。佇咧 C + + 里濟重繼承佮純虛函式予得定義出類似於 Java 的介面的類是可能的,猶毋過會有少許區別 .
  • Java 佇語言佮標準庫攏對多執行緒有良好的支援 . ` synchronized ` 這乎 Java 的關鍵字為著支援多執行緒應用提供了簡單了後安全的互斥鎖,但是仝步 ( synchronized ) 區干焦會當用 LIFO 的順序離開 . Java 嘛為閣較高階的多執行緒同步提供健壯所複雜的庫。佇咧 C + + 里無專門為多執行緒定義的記憶體模型;但是第三方庫提供了佮 Java 差不多的功能;猶毋過遮的 C + + 庫之間差異較大,一致性無好 .
  • C + + 方法會當聲明做虛函式,虛函式是咧行期根據物件的類型才確定的 . C + + 方法按算的狀況下毋是無影。佇咧 Java 里,方法按算講的狀況下是虛的,但是會使用 ` final ` 關鍵字使之聲明為非虛的 .
  • C + + 枚舉屬於基本類型,支援佮其他整數類型之間的轉換佮較 . Java 枚舉實際上是類的實例(𪜶對 ` java . lang . Enum < E > ` 擴展來), 象其他的類仝款會當定義構造函式,數據成員佮方法 .

資源管理

  • Java 提供了自動化的糞埽搜集。佇咧 C + + 里記憶體管理通常通過構造函式,析構函式佮智慧型指針。C + + 標準允准糞埽搜集,但並無強制要求;實際使用糞埽搜集誠少予人用著。強制使用自動糞埽搜集致使佇咧 Java 里編寫實時軟體是困難的 .
  • C + + 會當申請任意的記持體塊 . Java 干焦會當通過物件實例化來申請記憶體 .(注意:佇咧 Java 里,程序員會當通過建立一个位元組數組類比申請任意的記持體塊。猶毋過 Java 數組猶原是物件 .)
  • Java 和 C + + 佇資源管理上使用無仝款的習語 . Java 主要依賴干焦會當回收記持體的糞埽搜集的機制,因為這个機制若是用回收使用的非記憶體系統資源可能是足危險的。而且 C + + 主要依賴 RAII ( 資源的取得就是初初化 ) . 這反映著這兩種語言的幾方面的無仝:
  • 佇咧 C + + 里佇棧里申請複合類型的物件是足平常的,一旦登出棧的範圍就會被銷毀。佇咧 Java 里複合類型的物件總是佇堆里申請的記持體,若糞埽搜集器搜集(除非佇虛擬機內底使用了溜旋分析技術來將堆的記持體申請轉成棧的 .
  • C + + 有析構函式,而且 Java 有 finalizer ( finalizer ) . 兩个人攏會佇物件釋放進前被調用,毋過𪜶有顯顯的無仝。一个 C + + 物件的析構函式必須被隱式(棧變數物件的情形)或者是顯式調用來釋放物件。析構函式佇咧物件釋放進前仝步的所在執行。仝步,協調的反初始化以及釋放佇咧 C + + 里滿足 RAII 的要求。佇咧 Java 里,物件的釋放是被糞埽搜集器隱式處理的。一个 Java 物件的 finalizer 佇伊被最後一改存取了後佮佇實際釋放進前的某一个時間點予人異步(非同步)地調用,這个調用有可能一直無產生。足少的物件需要 finalizer;只有遐的咧釋放進前著愛保證一寡清理工課一定愛做的物件來講才是需要的—典型的狀況是:釋放著 JVM 是外部的資源。佇咧 Java 里,企圖安全同步的釋放某一寡系統資源,干焦會當用顯式的 try / finally 結構來進行 .
  • 佇咧 C + + 里是有可能有一个迷途指針的–過去的對一个已經敨放的物件的參照(參照); 試圖使用一个迷途指針的結果是致使程序錯誤。佇咧 Java 里,糞埽搜集器袂銷毀一个當咧被參照的物件 .
  • 佇咧 C + + 里未初初化過的基本類型物件是有可能存在的,Java 強制欲做預設初始化 .
  • 佇咧 C + + 里有可能申請一个物件,但是對伊無任何參照。這款的袂當用物件(不可存取記憶體)是袂當予人銷毀去,致使去記持體泄漏。作為對比,佇咧 Java 里一个物件袂去予回收到甲變攏袂達到(佇使用者的程序來講).(注意 : _ 弱參照 _ ( 弱參照)是去予人支援的,這個特性予 Java 的糞埽搜集器會當識別無仝款程度的達性 .)佇咧 Java 里糞埽搜集阻止了誠濟記持體泄漏的情形,毋過某一寡情況放屎猶原是可能的 .
  • Java 閣較容易泄漏非記持體資源,而且 C + + 的慣用做法閣較袂致使這種泄漏去 .

  • C + + 對真濟平台相關的特性提供了跨平台的存取方式。對 Java 到原生的作業系統佮硬體相關的函式的直接存取需要用著 JNI ( Java 本地介面 ) .

運行的時陣

  • C + + 通常來講會直接予人編譯做機器碼,予作業系統直接執行 . Java 通常會予人編譯做位元組碼,予被 Java 虛擬機器佮直譯器或者是即時編譯器編譯做機器碼然後執行 .
  • 因為表達方式無受限制,低層的 C + + 語言特性(比如講:一般不被檢查的陣列存取,原始標示,類型雙關語 ( type punning ) 袂當佇編譯期間抑是執行期間會當靠地予人檢查。相關的程式設計錯誤會致使低階的緩衝區溢位佮段錯誤(記憶體區段錯誤). 標準模板庫提供進階的抽象(比如講 vector , list 和 map)來幫助避免按呢的錯誤。佇咧 Java 里,低階錯誤袂發生抑是會予 JVM 檢測著閣以異常的形式報告予應用 .
  • Java 語言佇越界存取陣列的時一般來講會對陣列進行邊界檢查 ( bounds checking ) . 這消除了致使程序無穩定的一个可能因素,但是這是以執行速度閣較慢一寡做為代價的。佇咧一寡情形下,編譯器分析 ( compiler analysis ) 會當檢測著無必要的邊界檢查並去掉 . C + + 對原生陣列的越界存取無要求特定的處理,所以需要對原生陣列確認袂越界。猶毋過 C + + 標準庫里的一部份庫象 std : : vector 嘛提供著可選的邊界檢查。總的來講,Java 陣列是 " 總是安全;嚴格的限制;開銷較濟 ",而且 C + + 原生陣列是 " 會當揀的開銷;完全無限制;有藏佇的無安全 . "

模板 vs . 泛型

C + + 和 Java 攏提供泛型程式設計的能力,分別是模板佮泛型 ( Generics in Java ) . 雖然講𪜶予創造用來解決類似的問題,有類似的語法,但是實際上真無相仝 .


雜項

  • Java 和 C + + 佇咧使代碼佇無仝的檔案分開方面使用了無仝的技術 . Java 使用一个包系統,這个系統乎對所有的程序攏愛指定矣檔名佮路徑。佇咧 Java 里,編譯器負責匯入會當執行的類檔案 . C + + 使用標頭檔原始碼的包含系統來佇咧無仝的檔案分享聲明 .
  • 編譯予好的 Java 代碼一般來講比 C + + 檔案小,因為乎 Java 位元組碼 ( Java bytecode ) 一般來講比機器碼愛閣較緊鬥,Java 程序都毋是靜態連結的 .
  • C + + 編譯加一字文字預處理過程,Java 是無的。所以一寡使用者佇咧𪜶的編譯的過程進前增加一个預處理的過程,按呢會當閣較好的支援需要條件編譯的情形 .
  • 兩个語言內底陣列攏是定長的。佇咧 Java 里,陣列是頭等等的物件,啊若佇咧 C + + 里𪜶只是𪜶的基本類型元素的連紲的序列,不三時用一个指向頭一个元素的指標佮一个會當選的長度來參照。佇咧 Java 里,陣列是去予邊界檢查的,而且知影𪜶的長度,啊若佇咧 C + + 里你會當將任意的序列當做一个陣列 . C + + 和 Java 攏提供著相關的容器類(分別為std : : vectorjava . util . ArrayList), 會當改變大細 .
  • Java 的除法佮模除運算子是定義成零截斷的 . C + + 無定義這兩个運算子是零截斷的抑是 " 負無錢斷去 " 的。佇咧 Java 里-二分之三總是得著影一,但是一个 C + + 編譯器可能會轉去擗一抑是鋪二,視平台而定 . C 九十九定義矣佮 Java 仝款的除法的方式。兩種語言攏保證對所有的 a 和 b ( b !=零 )(當 a 和 b 攏是規型的時陣)` ( a / b ) * b + ( a % b )==a ` . C + + 版本會閣較緊,因為伊允准直接使用處理器的截斷方式 .
  • 整個的長度佇咧 Java 里是定義好的 ( int 為三十二-bit , long 為六十四-bit ),啊若佇咧 C + + 里整型佮指標的長度是佮編譯器閣應用二進位介面相關的。就按呢詳細編寫的 C + + 代碼會當利用六十四位元處理器的能力而且會當佇三十二位元處理器上工課。但是需要足斟酌用會當徙栽的方式來編寫。作為對比,Java 的固定規型大細使得程式設計師無法度做甲按呢,無法度利用處理器的字長會致使 Java 佇咧六十四位元處理器上表現較䆀 .

效能

想執行一个編譯好的 Java 程序,電腦愛執行 JVM;啊若編譯予好的 C + + 程序無需要加額的應用。較早期的 Java 版本佇效能上比靜態編譯的語言如 C + + 差足濟,這是因為用 C + + 是直接編譯做一寡機器指令,啊若當 Java 編譯做位元組碼以後用 JVM 解說執行的時閣牽涉袂少額外的機器指令。 比如講:

C + + 佇大部份的情形下攏比 Java 要緊, 有幾若个數值方面的基準測試的研究爭辯講 Java 佇某一寡情形下可能會比 C + + 的效能好得濟。但是有人講數值方面的基準測試對著語言的評估是無合適合的,因為編譯器攏會當做相關的最佳化,甚至可能將被測試的代碼徹底刪除。若牽連著一个真正現實應用的程序,Java 會因為足濟原因致使效能變差:

  • 所有的物件攏佇堆里去予人申請。對於使用小物件的函式來講會致使誠大的效能損失,因為佇棧里申請記憶體強欲無效能損失。
  • 方法按算講是虛的。這對小物件來講會因為虛表增加幾若倍的記持體來使用。伊嘛會引起效能損失,因為乎 JIT 編譯器不得不對查虛表的過程做其他的最佳化。
  • 就使用標準的容器猶原會當有誠濟的類型轉換,這會引起效能的損失,因為需要規个繼承樹仔。
  • 虛擬機器閣較進一步增加記憶體的使用,就按呢降低記憶體的局部性,增加緊取命中失敗率,但是致使規个程序變慢。
  • 欠缺低階細節的操作方式予開發者無法度共程序進一步最佳化,因為編譯器袂支援。

有人相爭講,和 Java 相比並 C + + 嘛有足濟彼个劣勢:

  • 指標予最佳化變甲困難,因為𪜶可能指向任意的資料。當然這馬這點嘛並毋是完全正確,因為一寡現代的編譯器引入了 " 嚴格別名 " 的規則並且支援 C 九十九的關鍵字 _ restrict _,對嚴格限制矣指標的使用,使用干焦會當用佇指向已經知影的變數
  • Java 的糞埽搜集佮使用 _ malloc _ / _ new _ 來申請記憶體相比有閣較好的緊取連貫性,因為伊的申請一般來講是順序的。毋過,始終有爭論認為二者仝款會致使記持體的「四秀仔」(即濟次分配佮回收了後記憶體空間會變甲無連紲), 而且並無佗一个比對方有閣較明顯的快取優勢。
  • 執行的時編譯可能會當閣較好的最佳化代碼,因為會當利用執行的時陣的資訊,譬如講知影代碼是佇啥物款的處理器上執行。毋過當今的情形嘛無完全按呢,因為目前上先進的 C + + 編譯器嘛會針對無仝系統生成無仝的目的碼,以期充分利用該系統的計算能力另外,有爭議的是,花咧閣較複雜的 C + + 代碼上的 debug 時間傷過濟,用 Java 開發完全會當共遮的時間用來最佳化 Java 代碼。當然對著一个予定的程序來講兩種語言會當最佳化到啥物程度嘛是一方面。最後咧,對處理器負擔誠重的狀況,譬如講影片彩現,C + + 會當直接存取硬體,平平一个硬體規格下跤 C + + 總是會比 Java 的表現好足濟。

所有權控制

C + + 毋是任何一个公司抑是組織的商標,無去予任何個人有。 Java 原是 Sun 的商標,這陣由甲骨文公司有擁有。

C + + 語言由 _ ISO / IEC 一爿四千八百八十二 _ 定義,是一个 ISO 標準,由 _ ISO / IEC JTC 一 / SC 二十二 / WG 二十一 _ 委員會發佈講。 Java 語言由 _ Java Language Specification _ 定義,這是一本 Sun 公司(已經予甲骨文收去)出版的冊。

其他

兩个人的物件存取格式嘛無仝款。

參考文獻

外部連結

  • Java and C + + Memory Management—一本詳盡的物件導向記持體管理方面出版物,佇記持體模型上著 Java 和 C + + 做了較 .
  • How Java Differs from C—excerpt from Java in a Nutshell by David Flanagan
  • Java vs . C + + resource management comparison-一份有例的綜合論文
  • Java vs C performance . . . again . . .-探入討論 Java 和 C + + 效能方面的差別