Java語言與C++語言是目前最流行的程式設計語言。兩者的編程思想雖然有一定的共同性,但是在很多方面仍然存在著比較大的差異。如兩者在範圍上仍然存在著很大的差異。下面筆者就分析一下這兩門語言在範圍上的差異,以協助大家進一步認識Java語言的優勢。
差異一:變數範圍的不同。
如,這段程式碼是符合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++語言一樣,都是物件導向的語言。不過兩者在實現機制上有很大的不同。就拿對象的範圍來說,就有很大的差異。這也導致了兩個物件導向的語言在實現細節上的巨大差異。
首先Java程式員需要明白的是,Java對象範圍與變數的範圍是不同的。如上面的分析,變數的範圍只在範圍內部有效。如在二級範圍內定義的變數,超出了二級範圍,那麼就無效了。但是對象則不同,其可以存在於範圍之外。如現在在某個範圍內定義了一個name_full對象。當脫離這個範圍的時候,這個對象的引用是消失了。但是剛才建立的這個對象仍然實實在在的儲存在記憶體中。在Java程式的運行過程中,只要通過傳遞或者複製對象引用的手段,那麼在其他範圍內仍然可以訪問這個對象。也就是說,只要我們有這個需要,那麼在某個範圍內建立的對象其會一直存在並可以在範圍外的其他任何一個地方進行訪問。當然前提是要通過複製或者傳遞等手段把對象引用傳遞到其他的範圍中。這就是Java對象與Java變數在範圍上最大的不同。
其次,Java對象與C++語言的範圍有很大的不同。其實C++語言中的對象跟變數的範圍到是很類似的。在C++語言中一旦使用完對象之後,就必須把這個對象銷毀掉。說的確切一點,就是要在範圍內把使用完的對象所佔的記憶體空間釋放掉。否則的話,如果在作用於外部,由於已經失去了對這個對象的引用,為此這個對象就好像成為了太空中的一個人,無法再對其進行任何的操作,只要任其自生自滅。為此對於C++語言來說,程式員很難在脫離範圍外後,確保在需要調用對象時,仍然可以訪問這個對象。這也正是C++語言開發過程中最讓人頭疼的問題。因為需要手工來銷毀對象。萬一對象所佔用的記憶體空間沒有別及時釋放的話,那麼對於應用程式的安全與效能都會產生很大的影響。
在Java程式中,這個範圍外的對象最終有兩個去向。首先,可以通過複製或者傳遞,在範圍外部仍然可以訪問這個對象。其次,就是銷毀對象。不過我們不用通過代碼來銷毀這個以前建立的對象。因為在Java語言中有一種叫做記憶體回收行程的處理機制,其可以用來動態監視New關鍵字建立的所有對象,並根據一定的規則來判斷哪些對象不會再被引用。如果其判斷某個對象不再被引用話,則會自動釋放這些對象所佔用的記憶體空間,以供其他新的對象所使用。我們程式開發人員只管建立對象即可,而不用去擔心什麼時候去銷毀對象。為此,這就可以消除C++語言面臨的記憶體溢出問題。這個記憶體溢出問題就是因為程式開發人員用完對象後忘記銷毀所造成的。
由於在Java程式開發中,我們開發人員不用關心對象的銷毀問題,為此可以更多的精力放在代碼的最佳化上。而不像C++語言那樣,要把這個對象銷毀問題當作頭件大事來對待。雖然如此,不過Java程式員也不能夠掉以輕心。特別是當我們在離開某個範圍後還需要訪問這個對象的時候,一定要記得通過複製或者傳遞等手段把對象引用傳遞給其他範圍。否則的話,即使這個對象沒有消亡,還實際儲存在記憶體中,但是也會因為缺少了引用而無法訪問他們。為此在跨範圍引用對象的時候,這個引用的複製與傳遞千萬不能夠忘了。
如果不幸忘了的話,那麼在範圍外的代碼就無法再訪問這個對象。不過這個對象在一定時候會被記憶體回收行程回收了。被釋放了的記憶體空間就可以被重複使用,從而防止記憶體溢出的問題發生。
總之,當Java程式員在開發應用程式的時候,這個Java對象與Java變數範圍的差異,以及Java對象與其他語言對象範圍的差異,一定要瞭然於胸。這有助於Java程式員能夠更好的利用這個Java對象。另外筆者不厭其煩的再強調一遍,預設情況下脫離了某個範圍之後,對象就失去了引用無法訪問。如果要在範圍再訪問這個對象的時候,則需要及時把這個引用複製或者傳遞出來。否則的話,範圍外的代碼是無法再操作這個對象。
推薦初學者一個編程技術的學習網站,96堆棧 軟體編程網,http://www.96dz.com,裡面有C++視頻教程、C#視頻教程、Java視頻教程下載,還有C\C++、Java、C# .NET等編程技術文摘,包括目前主流的Linux編程與Web編程等學習資料視頻教程下載。