跳轉到內容

概述

100% developed
來自華夏公益教科書

導航 前言: ( v  d  e )

包含在 Java 中的新功能和升級改變了程式設計環境的面貌,併為面向物件程式設計 (簡稱為 OOP) 給出了新的定義。但與它的前輩不同,Java 需要與標準功能捆綁在一起,並且獨立於主機平臺。

建立 Java 語言的主要目標

  • 它很簡單。
  • 它是面向物件的。
  • 它獨立於主機平臺。
  • 它包含用於網路的語言設施和庫。
  • 它旨在安全地執行來自遠端來源的程式碼。

Java 語言引入了一些在其他語言(如 C 和 C++)中不存在的新功能。

面向物件

[編輯 | 編輯原始碼]
面向物件程式設計可以用UML 圖表示。

面向物件 ("OO") 指的是一種程式設計方法和語言技術。OO 的主要思想是圍繞它操作的“事物”(即物件)來設計軟體,而不是圍繞它執行的操作。

隨著計算機硬體的進步,它帶來了建立更好的軟體技術的必要性,以便能夠建立不斷增加的複雜應用程式。其目的是使大型軟體專案更容易管理,從而提高質量並減少專案失敗的數量。面向物件解決方案是最新的軟體技術。

組合語言
軟體技術始於組合語言,組合語言接近機器指令,易於轉換為可執行程式碼。每臺硬體都有自己的組合語言。組合語言包含低階指令,例如將資料從記憶體移動到硬體暫存器、執行算術運算並將資料移回記憶體。程式設計師必須瞭解計算機的詳細體系結構才能編寫程式。
過程式語言
在組合語言之後,開發了高階語言。在這裡,語言編譯器用於將高階程式轉換為機器指令,使程式設計師擺脫了了解計算機硬體體系結構的負擔。為了促進程式碼的重複使用並最大限度地減少 GOTO 指令的使用,引入了“過程式”技術。這簡化了軟體控制流的建立和維護,但忽略了資料的組織。除錯和維護具有許多全域性變數(即包含可以在應用程式的任何位置修改的資料的變數)的程式變成了噩夢。
面嚮物件語言
在 OO 語言中,資料與資訊隱藏密切相關。特定於物件的 data 只能透過該物件中的過程訪問。因此,物件包含 data 以及控制流,程式成為物件之間的一系列互動。

平臺依賴性

[編輯 | 編輯原始碼]

在 C 或 C++ 程式設計中,您開始編寫原始碼

... 您將其編譯成機器程式碼檔案

... 然後您執行它

在這種情況下,機器程式碼檔案及其執行特定於為其編譯的平臺(Windows、Linux、macOS 等),即 目標平臺


... 因為編譯後的檔案是為在特定平臺和硬體上執行而設計的機器程式碼檔案。它會在另一個平臺上產生不同的結果/輸出。因此,如果希望您的程式在多個平臺上執行,則必須多次編譯您的程式

它帶來了更大的漏洞風險。請注意,當某段程式碼編譯成可執行格式時,可執行檔案無法動態更改。需要從更改後的程式碼重新編譯,才能使更改反映在最終的可執行檔案中。模組化(將程式碼分成模組)在 Java 的前輩中不存在。如果輸出應用程式不是單個可執行檔案,而是模組形式,那麼可以輕鬆更改單個模組並檢視應用程式中的更改。另一方面,在 C/C++ 中,程式碼的細微更改需要重新編譯整個應用程式。

Java 的理念是將原始碼編譯成將要解釋的中間語言。

原始碼 中間檔案 直譯器

中間語言是 位元組碼。直譯器是 Java 虛擬機器 (JVM)。位元組碼檔案是通用的,而 JVM 是特定於平臺的

因此,每個平臺都應該編寫一個 JVM。情況就是這樣。因此,您只需生成一個唯一的位元組碼檔案(一個 .class 檔案)。

該語言的最初實現使用解釋型虛擬機器來實現可移植性,許多實現仍然如此。這些實現產生的程式執行速度比典型的 C++ 編譯器建立的完全編譯的程式慢,因此該語言因產生緩慢的程式而聲名狼藉。從 Java 1.2 開始,Java VM 產生了執行速度快得多的程式,使用了多種技術。

其中第一個是簡單地直接編譯成原生代碼,就像更傳統的編譯器一樣,完全跳過位元組碼。這實現了極高的效能,但代價是可移植性。這實際上不再使用。

另一種技術,即時 (JIT) 編譯器,在程式執行時將 Java 位元組碼編譯成原生代碼,並保留編譯後的程式碼以供反覆使用。更復雜的 VM 甚至使用 動態重新編譯,其中 VM 可以分析正在執行的程式的行為並選擇性地重新編譯和最佳化程式的關鍵部分。這兩種技術都使程式能夠利用原生代碼的速度而不損失可移植性。

可移植性是一個技術上難以實現的目標,Java 在該目標上的成功存在一些爭議。雖然確實有可能為 Java 平臺編寫在許多主機平臺上表現一致的程式,但大量平臺存在小錯誤或不一致性,導致有些人將 Sun 的“一次編寫,隨處執行”的口號戲稱為“一次編寫,隨處除錯”。

標準化

[編輯 | 編輯原始碼]

C++ 是建立在 C 語言之上的,因此在語言周圍出現了多種不同的方法來做相同的事情。例如,在 C++ 中,建立物件可以透過三種不同的方式完成。此外,C++ 並沒有隨其編譯器捆綁提供標準庫。相反,它依賴於其他程式設計師建立的資源;這些程式碼很少能很好地融合在一起。

在 Java 中,提供了標準化的庫,以允許以統一的方式訪問主機機器的功能(例如圖形和網路)。Java 語言還包括對多執行緒程式的支援——這是許多網路應用程式的必需品。

然而,平臺無關的 Java 在伺服器端應用程式方面非常成功,例如 Web 服務、Servlet 或 Enterprise JavaBeans。

Swing 不依賴於底層本機使用者介面。

Java 在客戶端也取得了進展:首先是 抽象視窗工具包 (AWT),然後是 Swing,最新的客戶端庫是 標準小部件工具包 (SWT)。有趣的是,它們試圖如何處理兩種相互對立的消費力量。這些是 

高效、快速的程式碼;移植到最流行的硬體(一次編寫,隨處測試)
使用底層本機子例程建立 GUI 元件。AWT 和 SWT 採用了這種方法。
可移植性到任何移植了 JVM 的硬體(一次編寫,隨處執行)
為了實現後者,Java 工具包不應該依賴於底層本機使用者介面。Swing 採用了這種方法。

有趣的是,這種方法是如何來回切換的。AWT → Swing → SWT。

安全執行

[edit | edit source]
段錯誤是 C 程式設計中最常見的問題之一。

憑藉語言中內建的高階控制來操作硬體,C/C++ 程式設計師可以訪問系統上的幾乎任何資源,無論是硬體還是軟體。這原本是該語言的優勢之一,但這種靈活性卻導致了混亂和複雜的程式設計實踐。

錯誤處理

[edit | edit source]

傳統的錯誤處理方法是讓每個函式返回一個錯誤程式碼,然後讓呼叫者檢查返回的內容。這種方法的問題是,如果返回程式碼充滿了錯誤檢查程式碼,就會影響到正在執行實際工作的原始程式碼,從而降低程式碼的可讀性。

在新的錯誤處理方法中,函式/方法不返回錯誤程式碼。相反,在發生錯誤時,會丟擲一個 異常。異常可以透過 catch 關鍵字在 try 塊的末尾進行處理。這樣,呼叫該函式的程式碼就不需要被錯誤檢查程式碼所破壞,從而使程式碼更易讀。這種新的錯誤處理方法稱為“異常處理”。

異常處理也被新增到 C++ 中。但是,Java 和 C++ 異常處理之間存在兩個區別

  • 在 Java 中,丟擲的異常就像 Java 中的任何其他物件一樣是一個 Java 物件。它只需要實現 Throwable 介面。
  • 在 Java 中,編譯器會檢查是否可以捕獲異常。如果對丟擲的異常沒有 catch 塊,編譯器就會給出錯誤。

Java 前身中可選的異常處理會導致開發人員不關心錯誤處理。因此,經常發生意外錯誤。Java 強制開發人員處理異常。程式設計師必須處理異常,或者宣告使用者必須處理它。必須有人處理它。

網路功能

[edit | edit source]

儘管功能強大,但 Java 的前身缺乏與其他計算機聯網的標準功能,通常依賴於平臺複雜的網路功能。由於幾乎所有網路協議都已標準化,Java 技術的建立者希望將其作為該語言的一項旗艦功能,同時忠於之前在標準化 遠端過程呼叫 方面取得的進展。Java 團隊關注的另一個功能是其在全球資訊網和網際網路中的整合。

Java 平臺是最早提供廣泛支援從遠端來源執行程式碼的系統之一。Java 語言的設計考慮了 網路計算

Applet 可以執行在使用者的瀏覽器中,執行從遠端 HTTP 伺服器下載的程式碼。遠端程式碼在高度受限的“沙箱”中執行,這保護使用者免受行為不端或惡意程式碼的侵害;釋出者可以申請證書,以便使用該證書對 Applet 進行數字簽名,將其標記為“安全”,從而允許它們突破沙箱並訪問本地檔案系統和網路,這很可能是由使用者控制的。

動態類載入

[edit | edit source]

在 C 和 C++ 等傳統語言中,所有程式碼都必須在執行之前編譯並連結到一個可執行程式。在 Java 中,類按需編譯。如果在執行階段不需要某個類,則該類甚至不會被編譯成位元組碼。

此功能在網路程式設計中特別有用,因為我們事先不知道將執行哪些程式碼。正在執行的程式可以從檔案系統或遠端伺服器載入類。

此外,此功能理論上使 Java 程式可以在執行過程中更改自己的程式碼,以實現一些自我學習行為。然而,更現實的想象是,Java 程式會在執行之前生成 Java 程式碼,然後執行該程式碼。透過一些反饋機制,生成的程式碼可以隨著時間的推移而改進。

自動記憶體垃圾收集

[edit | edit source]

在 C 和 C++ 等傳統語言中,程式設計師必須確保釋放所有分配的記憶體。在程式設計師必須手動分配系統記憶體資源的情況下,記憶體洩漏成為了一種常見的麻煩。

記憶體資源或緩衝區具有特定的操作模式,以實現最佳效能。緩衝區一旦充滿資料,就需要在不再使用其內容後進行清理。如果程式設計師忘記在程式碼中清理它,記憶體很容易過載。用 C/C++ 語言程式設計變得很繁瑣且不安全,因為存在這些缺陷,用這些語言構建的程式容易出現記憶體洩漏和系統崩潰——有時甚至會損害硬體本身。釋放記憶體對於伺服器來說尤其重要,因為它必須連續執行幾天。如果在使用後沒有釋放一塊記憶體,而伺服器只是不斷分配記憶體,那麼這種記憶體洩漏可能會導致伺服器宕機。

在 Java 中,釋放記憶體的工作從程式設計師手中解放出來;Java 虛擬機器跟蹤所有使用的記憶體。當記憶體不再使用時,它會自動釋放。JVM 在後臺執行一個單獨的任務,釋放未被引用的、未使用的記憶體。該任務稱為“垃圾回收”。

垃圾回收器始終在執行。這種自動記憶體垃圾收集功能使用 Java 編寫健壯的伺服器端程式變得容易。程式設計師唯一需要關注的是物件建立的速度。如果應用程式建立物件的速率快於垃圾回收器釋放物件的速率,則會導致記憶體問題。根據 JVM 的配置方式,應用程式要麼會因丟擲 NotEnoughMemoryException 而耗盡記憶體,要麼會暫停以讓垃圾回收器執行其工作。

Applet

[edit | edit source]

Java 的建立者提出了applet的概念。Java 程式可以在客戶端瀏覽器程式中執行。Java 於 1995 年釋出;當時網際網路正變得越來越普及,人們也越來越熟悉它。Java 的承諾在於客戶端瀏覽器方面,程式碼將被下載並在客戶端瀏覽器程式中作為 Java applet 執行。

另請參見 Java 程式設計/小程式

禁止的壞習慣

[編輯 | 編輯原始碼]

多年來,C/C++ 程式設計中的一些特性被程式設計師濫用。雖然語言允許這樣做,但它被稱為壞習慣。因此,Java 的建立者將其從語言中排除。

  • 運算子過載
  • 多重繼承
  • 友元類(訪問另一個物件的私有成員)
  • 顯式型別轉換的限制(與記憶體管理相關)

在大多數人的觀點中,Java 技術在所有這些目標上都相當不錯。然而,該語言並非沒有缺點。Java 往往比類似語言(如 C++)更高階,這意味著 Java 語言缺乏硬體特定資料型別、指向任意記憶體地址的低階指標或運算子過載等程式設計方法。雖然這些特性經常被程式設計師濫用或誤用,但它們也是強大的工具。然而,Java 技術包括 Java 本地介面 (JNI),這是一種從 Java 語言程式碼呼叫原生代碼的方式。使用 JNI,仍然可以使用其中的一些功能。

一些程式設計師也抱怨 Java 缺乏多重繼承,這是 C++ 等其他面嚮物件語言的一項強大功能。Java 語言將型別和實現的繼承分開,允許透過介面繼承多個型別定義,但只允許透過類層次結構單繼承型別實現。這在避免多重繼承的許多危險的同時,提供了大多數多重繼承的好處。此外,透過使用具體類、抽象類以及介面,Java 語言程式設計師可以選擇對其定義的物件型別進行完全、部分或零實現,從而確保應用程式設計中的最大靈活性。

有些人認為,對於某些專案,面向物件會使工作變得更困難而不是更容易。這種特定的抱怨並不獨特,它也適用於其他面嚮物件語言。


華夏公益教科書