1. 程式人生 > >java與C/C++之間的區別

java與C/C++之間的區別

  1. Java中對記憶體的分配是動態的,它採用面向物件的機制,採用運算子new為每個物件分配記憶體空間,而且,實際記憶體還會隨程式執行情況而改變.程式執行中,每個, Java系統自動對記憶體進行掃描,對長期不用的空間作為”垃圾”進行收集,使得系統資源得到更充分地利用.按照這種機制,程式設計師不必關注記憶體管理問題,這使Java程式的編寫變得簡單明瞭,並且避免了了由於記憶體管理方面的差錯而導致系統出問題.而C語言通過malloc()和free()這兩個庫函式來分別實現分配內在和釋放記憶體空間的,C++語言中則通過運算子new和delete來分配和釋放記憶體.在C和C++這仲機制中,程式設計師必須非常仔細地處理記憶體的使用問題.一方面,如果對己釋放的記憶體再作釋放或者對未曾分配的記憶體作釋放,都會造成宕機;而另一方面,如果對長期不用的或不再使用的記憶體不釋放,則會浪費系統資源,甚至因此造成資源枯竭.
  2. Java不在所有類之外定義全域性變數,而是在某個類中定義一種公用靜態的變數來完成全域性變數的功能.
  3. Java不用goto語句,而是用try-catch-finally異常處理語句來代替goto語句處理出錯的功能.
  4. Java不支援標頭檔案,面C和C++語言中都用標頭檔案來定義類的原型,全域性變數,庫函式等,這種採用標頭檔案的結構使得系統的執行維護相當繁雜.
  5. Java不支援巨集定義,而是使用關鍵字final來定義常量,在C++中則採用巨集定義來實現常量定義,這不得於程式的可讀性.
  6. Java對每種資料型別都分配固定長度.比如,在Java中,int型別總是32位的,而在C和C++中,對於不同的平臺,同一個資料型別分配不同的位元組數,同樣是int型別,在PC機中為二位元組即16位,而在VAX-11中,則為32位.這使得C語言造成不可移植性,而Java則具有跨平臺性(平臺無關性).
  7. 型別轉換不同.在C和C++中,可通過指標進行任意的型別轉換,常常帶來不安全性,而在Java中,執行時系統對物件的處理要進行型別相容性檢查,以防止不安全的轉換.
  8. 結構和聯合的處理.在C和C++中,結構和聯合的所有成員均為公有,這就帶來了安全性問題,而在Java中根本就不包含結構和聯合,所有的內容都封裝在類裡面
  9. Java不再使用指標.指標是C和C++中最靈活,也最容易產生錯誤的資料型別.由指標所進行的記憶體地址操作常會造成不可預知的錯誤,同時通過指標對某個記憶體地址進行顯式型別轉換後,可以訪問一個C++中的私有成員,從而破壞安全性.而Java對指標進行完全地控制,程式設計師不能直接進行任何指標操作.

二·Java語言與C++語言在作用域上的差異

差異一:變數作用域的不同

如下,這段程式程式碼是符合C++語言的語法要求的。其可以在C語言下正常執行。但是其在Java語言平臺下編譯的時候,就會被告知有錯誤。其格式、關鍵字上面都沒有錯誤。那麼錯誤到底是這麼呢?這就關係到變數的作用域。

{

float y=3.15

{ float y=3.15

}

}

作用域就決定了其定義的變數名的可見性與生命週期。在C++語言(包括其衍生出來的其他語言)與Java語言中,都是用一定花括號來代表一個作用域的。如上面的程式碼,就表示有兩個作用域。外面一對花括號代表一級作用域;裡面一對花括號代表二級作用域,依次類推。通常情況下,一級作用域中定義的變數,對其下級作用率都是有效的。也就是說,其下級作用域可以直接引用上級作用域中定義的變數。但是在二級作用域中,可以更改一級作用率中設定的變數值,不過這個更改只在二級作用域內部有效。如上面這個程式碼,在二級作用域中可以再定義一個y變數,重新賦值。注意,其實在二級作用域中定義的變數與一級作用域中定義的變數,雖然名字相同,但是他們不是同一個變數。如果此時在一級作用域外,有其他程式碼引用這個y變數的話,則其的值仍然是3.14,而不會是3.15。也就是說,在二級作用域中定義的變數,只在其內部有效。對於上級作用域是沒有絲毫影響的。也就是說,在作用域中定義的變數只在其作用域內有效。出了其作用域外,其內部設定的變數就全部無效了。

這個作用域的設定其實Java語言與C++語言是類似的。但是在細節上Java語言又多了一條限制。如上表的程式碼所示,雖然在上面的程式碼中變數y在兩個不同的作用域中定義,照理來說是兩者是互不干涉,可以共存。但是在Java編譯器中,是不允許有這種情況存在的。把上面這個程式碼在Java編譯器中編譯的話,編譯器會通知程式開發人員,說這個變數y已經定義過。然後編譯會以錯誤告終。雖然在C++語言中在不同級別的作用域中定義名字相同的變數是允許的,而在Java語言中則不行,這並不代表在變數的作用域上有所不同。其實從本質上來說,兩者變數的作用域是相同的。只是對於Java語言來說,其又多加了一條限制。在Java語言中,即使作用域不同,其定義的變數名字也不能夠相同。這主要是為了提高Java程式碼的可讀性,防止混淆才定義了這條規則。

差異二:物件作用域的差異

Java語言與C++語言一樣,都是面向物件的語言。不過兩者在實現機制上有很大的不同。就拿物件的作用域來說,就有很大的差異。這也導致了兩個面向物件的語言在實現細節上的巨大差異。

1. 首先Java程式設計師需要明白的是,Java物件作用域與變數的作用域是不同的。如上面的分析,變數的作用域只在作用域內部有效。如在二級作用域內定義的變數,超出了二級作用域,那麼就無效了。但是物件則不同,其可以存在於作用域之外。如現在在某個作用域內定義了一個name_full物件。當脫離這個作用域的時候,這個物件的引用是消失了。但是剛才建立的這個物件仍然實實在在的儲存在記憶體中。在Java程式的執行過程中,只要通過傳遞或者複製物件引用的手段,那麼在其他作用域內仍然可以訪問這個物件。也就是說,只要我們有這個需要,那麼在某個作用域內建立的物件其會一直存在並可以在作用域外的其他任何一個地方進行訪問。當然前提是要通過複製或者傳遞等手段把物件引用傳遞到其他的作用域中。這就是Java物件與Java變數在作用域上最大的不同。

2. 其次,Java物件與C++語言的作用域有很大的不同。其實C++語言中的物件跟變數的作用域到是很類似的。在C++語言中一旦使用完物件之後,就必須把這個物件銷燬掉。說的確切一點,就是要在作用域內把使用完的物件所佔的記憶體空間釋放掉。否則的話,如果在作用於外部,由於已經失去了對這個物件的引用,為此這個物件就好像成為了太空中的一個人,無法再對其進行任何的操作,只要任其自生自滅。為此對於C++語言來說,程式設計師很難在脫離作用域外後,確保在需要呼叫物件時,仍然可以訪問這個物件。這也正是C++語言開發過程中最讓人頭疼的問題。因為需要手工來銷燬物件。萬一物件所佔用的記憶體空間沒有別及時釋放的話,那麼對於應用程式的安全與效能都會產生很大的影響。

java作用域外物件的去向

在Java程式中,這個作用域外的物件最終有兩個去向。首先,可以通過複製或者傳遞,在作用域外部仍然可以訪問這個物件。其次,就是銷燬物件。不過我們不用通過程式碼來銷燬這個以前建立的物件。因為在Java語言中有一種叫做垃圾回收器的處理機制,其可以用來動態監視New關鍵字建立的所有物件,並根據一定的規則來判斷哪些物件不會再被引用。如果其判斷某個物件不再被引用話,則會自動釋放這些物件所佔用的記憶體空間,以供其他新的物件所使用。我們程式開發人員只管建立物件即可,而不用去擔心什麼時候去銷燬物件。為此,這就可以消除C++語言面臨的記憶體溢位問題。這個記憶體溢位問題就是因為程式開發人員用完物件後忘記銷燬所造成的。

由於在Java程式開發中,我們開發人員不用關心物件的銷燬問題,為此可以更多的精力放在程式碼的優化上。而不像C++語言那樣,要把這個物件銷燬問題當作頭件大事來對待。雖然如此,不過Java程式設計師也不能夠掉以輕心。特別是當我們在離開某個作用域後還需要訪問這個物件的時候,一定要記得通過複製或者傳遞等手段把物件引用傳遞給其他作用域。否則的話,即使這個物件沒有消亡,還實際儲存在記憶體中,但是也會因為缺少了引用而無法訪問他們。為此在跨作用域引用物件的時候,這個引用的複製與傳遞千萬不能夠忘了。

如果不幸忘了的話,那麼在作用域外的程式碼就無法再訪問這個物件。不過這個物件在一定時候會被垃圾回收器回收了。被釋放了的記憶體空間就可以被重複使用,從而防止記憶體溢位的問題發生。

總結

當Java程式設計師在開發應用程式的時候,這個Java物件與Java變數作用域的差異,以及Java物件與其他語言物件作用域的差異,一定要了然於胸。這有助於Java程式設計師能夠更好的利用這個Java物件。另外筆者不厭其煩的再強調一遍,預設情況下脫離了某個作用域之後,物件就失去了引用無法訪問。如果要在作用域再訪問這個物件的時候,則需要及時把這個引用複製或者傳遞出來。否則的話,作用域外的程式碼是無法再操作這個物件。