華文網

娜姐,帶你深扒關於Java的那些事!

溫馨提示:細讀本文需要6分鐘,速讀僅需2分鐘。

最近jJava聯盟來了很多新的小夥伴,李娜給這些Java小白們,整理了1377G的資料,但是裡面都是直接學習的,對於Java歷史和簡介沒有過多的介紹。

所以娜姐就帶你深扒Java的那些事,希望看完這篇的你,對Java有個完整的認識!

Java簡介

Java是一種電腦程式設計語言,擁有跨平臺、物件導向、泛型程式設計的特性,廣泛應用於企業級Web應用開發和移動應用開發。

1991 年Sun公司的James Gosling等人開始開發名稱為 Oak 的語言。希望用於控制嵌入在有線電視交換盒、PDA等的微處理器

1994年將Oak語言更名為Java

1998年JDK1.2時,更名為Java 2 Platform
分為標準版J2SE,企業版J2EE,微型版J2ME

Java 既安全、可移植,又可跨平臺,

而且人們發現它能夠解決Internet 上的大型應用問題

Internet使Java成為網上最流行的程式設計語言

Java對Internet的影響也意義深遠

B/S的興起 C/S的沒落

任職於太陽微系統的詹姆斯•高斯林等人于1990年代初開發Java語言的雛形,最初被命名為Oak,目標設置在家用電器等小型系統的程式語言,應用在電視機、電話、鬧鐘、烤麵包機等家用電器的控制和通信。由於這些智慧化家電的市場需求沒有預期的高,Sun公司放棄了該項計畫。

隨著1990年代互聯網的發展,Sun公司看見Oak在互聯網上應用的前景,於是改造了Oak,於1995年5月以Java的名稱正式發佈。Java伴隨著互聯網的迅猛發展而發展,逐漸成為重要的網路程式設計語言。

Java程式設計語言的風格十分接近C++語言。繼承了C++語言物件導向技術的核心,Java捨棄了C++語言中容易引起錯誤的指標,改以引用替換,同時移除原C++與原來運算子重載,也移除多重繼承特性,改用介面替換,

增加垃圾回收器功能。在Java SE 1.5版本中引入了泛型程式設計、類型安全的枚舉、不定長參數和自動裝/拆箱特性。太陽微系統對Java語言的解釋是:“Java程式設計語言是個簡單、物件導向、分散式、解釋性、健壯、安全與系統無關、可移植、高性能、多執行緒和動態的語言。”

Java不同於一般的編譯語言或直譯語言。它首先將原始程式碼編譯成位元組碼,然後依賴各種不同平臺上的虛擬機器來解釋執行位元組碼,

從而實現了“一次編寫,到處運行”的跨平臺特性。在早期JVM中,這在一定程度上降低了Java程式的運行效率。但在J2SE1.4.2發佈後,Java的運行速度有了大幅提升。

與傳統型態不同,Sun公司在推出Java時就將其作為開放的技術。全球數以萬計的Java開發公司被要求所設計的Java軟體必須相互相容。“Java語言靠群體的力量而非公司的力量”是 Sun公司的口號之一,並獲得了廣大軟體發展商的認同。

這與微軟公司所宣導的注重精英和封閉式的模式完全不同,此外,微軟公司後來推出了與之競爭的.NET平臺以及模仿Java的C#語言。後來Sun公司被甲骨文公司並購,Java也隨之成為甲骨文公司的產品。

Java語言之父-詹姆斯•高斯林

語言特性

Java之所以被開發,是要達到以下五個目的:

應當使用物件導向程式設計方法學

應當允許同一程式在不同的電腦平臺執行

應當包括內建的對電腦網路的支援

應當被設計成安全地執行遠端代碼

應當易於使用,並借鑒以前那些物件導向語言(如C++)的長處。

Java技術主要分成幾個部分:Java語言、Java運行環境、類庫。一般情況下說Java時並不區分指的是哪個部分。

Java在1.5版本時,做了重大改變,太陽公司並1.5版本重命名為Java 5.0。

物件導向

Java的特點之一就是物件導向, 是程式設計方法的一種。“物件導向程式設計語言”的核心之一就是開發者在設計軟體的時候可以使用自訂的類型和關聯操作。代碼和資料的實際集合體叫做“對 象”。一個物件可以想像成綁定了很多“行為(代碼)”和“狀態(資料)”的物體。對於資料結構的改變需要和代碼進行通信然後操作,反之亦然。物件導向設計 讓大型軟體工程的計畫和設計變得更容易管理,能增強工程的健康度,減少失敗工程的數量。

跨平臺性

Java語言的第二個特性就是跨平臺性,也就是說使用Java語言編寫的程式可以在編譯後不用經過任何更改,就能在任何硬體設備條件下運行。這個特性經常被稱為“一次編譯,到處運行”。


執行Java應用程式必須安裝Java Runtime Environment(JRE),JRE內部有一個Java虛擬機器(Java Virtual Machine,JVM)以及一些標準的類庫(Class Library)。通過JVM才能在電腦系統執行Java應用程式(Java Application),這與.Net Framework的情況一樣,所以電腦上沒有安裝JVM,那麼這些程式將不能夠執行。


實現跨平臺性的方法是大多數編譯器在進行Java語言程式的編碼時候會生成一個用位元組碼寫成的“半成品”,這個“半成品”會在Java虛擬機器(解釋層)的幫助下運行,虛擬機器會把它轉換成當前所處硬體平臺的原始代碼。之後,Java虛擬機器會打開標準庫,進行資料(圖片、執行緒和網路)的訪問工作。主要注意的是,儘管已經存在一個進行代碼翻譯的解釋層,有些時候Java的位元組碼代碼還是會被JIT編譯器進行二次編譯。


有些編譯器,比如GCJ,可以自動生成原始代碼而不需要解釋層。但是這些編譯器所生成的代碼只能應用於特定平臺。並且GCJ目前只支援部分的Java API。


甲骨文公司對於Java的許可是“全相容的”,這也導致了微軟和升陽關於微軟的程式不支援RMI和JNI介面、並且增加特性為己所用的法律爭端。升陽最終贏得了官司,獲得了大約兩千萬美元的賠償,法院強制要求微軟執行升陽公司關於Java的許可要求。作為回應,微軟不再在Windows系統中捆綁Java,最新的Windows版本,Windows Vista和Internet Explorer 7.0版本也不再提供對於Java應用程式和控制項的支援。但是升陽公司和其他使用Java運行時系統的公司在Windows作業系統下對使用者提供無償的協力廠商外掛程式和程式支援。


Java語言使用解釋層最初是為了輕巧性。所以這些程式的運行效率比C語言和C++要低很多,用戶也對此頗有微詞。很多最近的調查顯示Java的程式運行速度比幾年前要高出許多,有些同樣功能的程式的效率甚至超過了C++和C語言編寫的程式[來源請求]。


Java語言在最開始應用的時候是沒有解釋層的,所有需要編譯的代碼都直接轉換成機器的原始代碼。這樣做的後果就是獲得了最佳的性能,但是程式臃腫異常。從JIT技術開始,Java的程式都經過一次轉換之後才變成機器碼。很多老牌的協力廠商虛擬機器都使用一種叫做“動態編譯”的技術,也就是說虛擬機器即時監測和分析程式的運行行為,同時選擇性地對程式所需要的部分進行編譯和優化。所有這些技術都改善了代碼的運行速度,但是又不會讓程式的體積變得失常。


程式的輕便性事實上是軟體編寫很難達到的一個目標,Java雖然成功地實現了“一次編譯,到處運行”,但是由於平臺和平臺之間的差異,所編寫的程式 在轉換代碼的時候難免會出現微小的、不可察覺的錯誤和意外。有些程式師對此非常頭疼,他們嘲笑Java的程式不是“一次編譯,到處運行”,而是“一次編 譯,到處調試”。以Java AWT為例,早期Java AWT內提供的按鈕、文字區等均是以電腦系統所預設的樣式而顯示。這令Java程式在有些沒有提供圖案的電腦系統產生錯誤(在Microsoft Windows設有視窗管理器,在一些Linux distribution則沒有)。後來SUN公司針對Java AWT一些問題而推出Java Swing。


平臺無關性讓Java在伺服器端軟體領域非常成功。很多伺服器端軟體都使用Java或相關技術建立。

自動垃圾回收(Garbage Collection)

C++語言被使用者詬病的原因之一是大多數C++編譯器不支持垃圾收集機制。通常使用C++程式設計的時候,程式師于程式中初始化物件時,會在主機記憶體堆疊上分配一塊記憶體與位址,當不需要此物件時,進行析構或者刪除的時候再釋放分配的記憶體位址。如果物件是在堆疊上分配的,而程式師又忘記進行刪除,那麼就會造成記憶體洩漏(Memory Leak)。長此以往,程式運行的時候可能會生成很多不清除的垃圾,浪費了不必要的記憶體空間。而且如果同一記憶體位址被刪除兩次的話,程式會變得不穩定,甚 至崩潰。因此有經驗的C++程式師都會在刪除之後將指標重置為NULL,然後在刪除之前先判斷指針是否為NULL。


C++中也可以使用“智慧指標”(Smart Pointer)或者使用C++託管擴展編譯器的方法來實現自動化記憶體釋放,智慧指標可以在標準類庫中 找到,而C++託管擴展被微軟的Visual C++ 7.0及以上版本所支持。智慧指標的優點是不需引入緩慢的垃圾收集機制,而且可以不考慮執行緒安全的問題,但是缺點是如果不善使用智慧指標的話,性能有可能 不如垃圾收集機制,而且不斷地分配和釋放記憶體可能造成記憶體碎片,需要手動對堆進行壓縮。除此之外,由於智慧指標是一個基於範本的功能,所以沒有經驗的程式 員在需要使用多態特性進行自動清理時也可能束手無策。


Java語言則不同,上述的情況被自動垃圾收集功能自動處理。物件的創建和放置都是在記憶體堆疊上面進行的。當一個物件沒有任何引用的時候,Java的自動垃圾收集機制就發揮作用,自動刪除這個物件所佔用的空間,釋放記憶體以避免記憶體洩漏。


注意程式師不需要修改finalize方法,自動垃圾收集也會發生作用。但是記憶體洩漏並不是就此避免了,當程式師疏忽大意地忘記解除一個物件不應該有的引用時,記憶體洩漏仍然不可避免。


不同廠商、不同版本的JVM中的記憶體垃圾回收機制並不完全一樣,通常越新版本的記憶體回收機制越快,IBM、BEA、SUN等等開發JVM的公司都曾宣稱過自己製造出了世界上最快的JVM[來源請求],JVM性能的世界紀錄也在不斷的被打破並提高。
IBM有一篇有關Java記憶體回收機制比不啟動垃圾收集機制的C++記憶體處理快數倍的技術文章[14],而著名的Java技術書籍《Java程式設計思想》(Thinking in Java)也有一段論述Java記憶體及性能達到甚至超過C++的章節[15] 。

基本語法

編寫Java程式前應注意以下幾點:

大小寫敏感:Java是大小寫敏感的,這就意味著識別字Hello與hello是不同的。

類名:對於所有的類來說,類名的首字母應該大寫。如果類名由若干單詞組成,那麼每個單詞的首字母應該大寫,例如MyFirstJavaClass。

方法名:所有的方法名都應該以小寫字母開頭。如果方法名含有若干單詞,則後面的每個單詞首字母大寫,例如myFirstJavaMethod。

原始檔案名:原始檔案名必須和類名相同。當保存檔的時候,你應該使用類名作為檔案名保存(切記Java是大小寫敏感的),檔案名的尾碼為.java。(如果檔案名和類名不相同則會導致編譯錯誤)。

主方法入口:所有的Java程式由public static void main(String[] args)方法開始執行。

Java關鍵字

關鍵字 下面列出了Java關鍵字。這些關鍵字不能用於常量、變數、和任何識別字的名稱。

關鍵字 描述abstract抽象方法,抽象類別的修飾符assert斷言條件是否滿足continue不執行循環體剩餘部分defaultswitch語句中的預設分支do-while迴圈語句,循環體至少會執行一次double64-bit雙精度浮點數elseif條件不成立時執行的分支enum枚舉類型extends表示一個類是另一個類的子類final表示定義常量finally無論有沒有異常發生都執行代碼float32-bit單精確度浮點數forfor迴圈語句goto用於流程控制if條件陳述式implements表示一個類實現了介面import導入類instanceof測試一個物件是否是某個類的實例int32位元整型數interface介面,一種抽象的類型,僅有方法和常量的定義long64位整型數native表示方法用非java代碼實現new分配新的類實例package一系列相關類組成一個包private表示私有欄位,或者方法等,只能從類內部訪問protected表示保護類型欄位public表示共有屬性或者方法return方法返回值short16位元數字static表示在類級別定義,所有實例共用的strictfp浮點數比較使用嚴格的規則super表示基類switch選擇語句synchronized表示同一時間只能由一個執行緒訪問的代碼塊this調用當前實例或者調用另一個構造函數throw拋出異常throws定義方法可能拋出的異常transient修飾不要序列化的欄位try表示代碼塊要做異常處理void標記方法不返回任何值volatile標記欄位可能會被多個執行緒同時訪問,而不做同步whilewhile迴圈

介面和類別

Java自帶了創建介面的類別,可以這樣使用:

publicinterfaceDeleteable{
voiddelete();
}

這段代碼的意思是任何實現(implement)Deleteable介面的類別都必須實現delete()方法。每個類別對這個方法的實現可以自行定制。由此概念可以引出很多種使用方法,下面是一個類別的例子:

publicclassFredimplementsDeleteable
{
//必須實作Deleteable介面中的delete方法
@Overridepublicvoiddelete(){
//實作的程式碼
}
//這個類別也可以包含其他方法
publicvoiddoOtherStuff(){
}
}

在另外一個類別中,可以使用這樣的代碼:

publicvoiddeleteAll(Deleteable[]list){
for(inti=0;
ilist.length;
i++){
list[i].delete();
}
}

因為佇列中所有的物件都可以使用delete()方法。Deleteable佇列中包含Fred物件的引用,而這個類別和其他Deleteable類別在使用deleteAll()方法時候不需要進行任何改變。


之所以這樣做就是為了在介面的執行和其代碼之間進行區別。舉例來說,一個名叫Collection的介面可以包含任何物件所需要的引入、轉換和存儲資料的方法,其他的類都可以使用這個介面。但是這個介面可以是一個可重定義大小的佇列、一個鏈表或者是其他功能的集合。


這種特性其實是一種折中的辦法。Java的設計者們不想讓Java有多重繼承的特性,因為C++的多重繼承顯示了這種特性的困難。Java的介面功能可以提供同樣的功能,但是又不會很複雜。

應用程式開發介面

在Java語言中,應用程式介面(API)化身成類,並且分組成為包。每個包中包含有相關的介面和類。對於不同的平臺,Java提供了不同版本的包。API的設定由sun公司和其他公司通過JCP(Java社區程式)決定。任何公司和個人都可以參與這個工程,對API進行設計。2004年,IBM和BEA公司準備聯合對官方的Java開源軟體工程進行支持,但是2005年初,sun公司拒絕了這個支持。

關於Java的批評

整體性問題

並不是所有的工程和環境需要企業檔次的複雜性,比如一個簡單的個人網站或者獨自程式設計的程式師所寫的程式。這些程式師會發現Java的複雜管理對於自己要做的程式來說過於強大了。一些人覺得Java在物件導向上面做的沒有Ruby和Smalltalk純粹。但是最新出現的用Java實現的語言Groovy解決了這些問題。

作為一種已經創建的新技術,Java顯然綜合了很多語言的特性,比如C++、C語言、Python等等。一些對於Java的評論認為Java的不變性在動搖。

語言問題

有些程式師不喜歡原始類型(primitive type)和類別(class)的分離,尤其是那些曾經使用過Smalltalk和Ruby的程式師。Java的代碼相對於其他的代碼來說過於冗長,這與它的輕便化聲明相違背。

Java是一種單層繼承的語言。這也導致了程式師在試圖使用多重繼承時候的不便,而很多語言都可以使用這個特性。但是Java可以使用介面類別,把多重繼承可能導致的風險減少到最小。Java不支持運算子重載,這是為了防止運算子重載使得代碼的功能變得不清晰。但是用Java實現的語言Groovy可以進行運算子重載。過去Java對於文本的操作和其他語言,比如Perl和PHP相比差的較多,但Java在1.4版本時候引入了規則運算式。

至Java 1.7為止,Java語言不支援閉包(closure)和混入(mixin)特性。

Java 1.8加入閉包(Lambda Expressions) 。

類庫問題

使用Swing平臺編寫的帶有GUI(圖形化使用者介面)的程式和其他原始程式非常不同。選用AWT工 具包編寫程式的程式師看到的都是原始介面,而且也無法獲得先進的GUI程式設計支援,如果使用的話,就要提供每個平臺上面所需的API,這將是一項龐大的工 程。Swing則是完全用Java語言所寫的程式,避免了介面元素重複的問題,只使用所有平臺都支持的最基本的繪圖機制。但是很多用戶不知道如何在 Java風格和Windows風格之間進行轉換,結果造成了Java程式的介面在很多程式中非常特殊。蘋果電腦已經提供了優化過的Java運行時程式,包含了Mac OS X的經典Aqua介面風格。

在IBM捐贈給Eclipse基金會的SWT介面框架中,使用者會看到熟悉的本地風格介面。但這又引起了不同喜好的開發人員之間的爭論。

性能問題

由於Java編譯器和虛擬機器的不同對Java代碼的性能影響比語言本身的影響大的多,所以統一討論Java的程式的性能經常是有誤導性的。據IBM的資料,在同樣的硬體上2001年時的IBM JDK版本的性能是1996年的JDK版本的十倍左右。

Java語言的一些特性不可避免的有額外的性能代價,例如陣列範圍檢查、運行時類型檢查等等。Java程式的性能還會因為不同的動態複雜性和垃圾處 理機制使用的多少而各有不同。如果JVM的實現比較優化的話,那麼這些功能甚至可以增加記憶體分配的性能。這和總是使用STL或者託管C++的程式的情況類 似。

儘管如此,仍然有許多人認為Java的性能低。這部分歸因於Sun公司最初的JVM實現使用未優化的解釋機制來運行位元組碼。一些新版本的JVM使用Just-In-Time(JIT) 編譯器,在載入位元組碼的時候將其編譯成針對運行環境的本地代碼來實現一些本地編譯器的優化特性。Just-In-Time機制和本地編譯的性能比較仍舊是 一個有爭議的話題。JIT編譯需要很多時間,對於執行時間不長或者代碼很多的大型程式並不適宜。但是不算JIT編譯階段的話,程式的運行性能在很多JVM下可以和本地編譯的程式一爭短長,甚至在一些計算比較密集的數值計算領域也是這樣。目前,Java已經使用更先進的HotSpot技 術來代替JIT技術,Java的性能有了更進一步的提升。另外,在使用-server選項運行Java程式時,也可以對Java進行更深入的優化,比如在 運行時將調用較多的方法內聯(inline)到程式中來提高運行速度,這就是所謂的“動態優化”,而本地編譯器是無法做到這一點的;這也是一些Java代 碼比對應用C/C++等語言編寫的本地代碼運行的更快的原因之一。微軟的.NET平臺也使用JIT編譯器,所以也有類似問題。

Java的設計目的主要是安全性和可攜性,所以對於一些特性,比如對硬體架構和記憶體位址訪問的直接訪問都被去除了。如果需要間接調用這些底層功能的話,就需要使用JNI(Java 本地介面)來調用本地代碼,而間接訪問意味著頻繁調用這些特性時性能損失會很大,微軟的.NET平臺也有這樣的問題。所以到目前為止,性能敏感的代碼,例 如驅動程式和3D視頻遊戲,還是大多使用本地編譯,甚至直接以不直接支援物件導向的C語言或機器碼編寫。但最近已經有了許多用純Java編寫的3D遊戲, 其效果與用C語言編寫的不相上下,例如“合金戰士”(英文名:Chrome)。這主要是因為新版的Java 3D技術已經能像C++一樣調用硬體加速,也就是使用顯卡來加速,無論是C++還是Java語言寫的3D遊戲都是使用顯卡及GPU來處理,從而使得CPU可以專注於其他方面的工作。

Java平臺

Java平臺即由Java程式設計語言所撰寫的軟體賴以運行的平臺,是Java軟體和電腦系統的仲介,最初被設計用在 Applet 等桌面端程式,不過後來逐漸轉移到服務端的運用。

Java 運行環境

Java 運行環境,即Java Runtime Environment,簡稱為JRE,是在任何平臺上運行Java編寫的程式都需要用到的軟體。終端使用者可以以軟體或者外掛程式方式得到和使用 JRE。Sun 公司還發佈了一個JRE的更複雜的版本,叫做JDK,即Java 2開發包,裡面包含了Java需要的編譯器、參考文檔和調試器等。

JRE的成分

Java的類庫,包含了編譯Java程式所需要的最核心檔。

核心庫檔,其中有

資料結構的庫,包括清單、字典和樹等

XML分析庫

安全方面應用庫

國際化和當地語系化應用庫

綜合庫檔,包含了程式師和其他系統通信的功能檔。

JDBC,即Java資料庫聯通的API

JNDI,即Java命名和目錄介面

RMI和CORBA用於重新分發軟體

使用者介面庫檔,包含:

AWT,即抽象視窗開發包,提供了產生圖形化使用者介面所需要的功能

Swing庫

其他用於回訪媒體檔、錄音、截圖的庫

一個用於執行軟體的Java虛擬機器(JVM)

外掛程式,可以在流覽器裡面使用

JWS,可以讓終端使用者連接到互聯網

許可檔和文檔

桌面的應用

根據Sun公司的統計,安裝Java運行環境的個人電腦已經超過7億。 [1]自從Sun指控微軟添加Windows特效類檔到Java運行環境(JRE),並通過Visual J++運行這些類檔,微軟不再綁定Java運行環境到Windows作業系統。Apple的Mac OS X一般默認綁定Java運行環境, 而且許多Linux發行版本也綁定一些相容的自由套裝軟體GNU Classpath。


一些Java軟體被桌上型電腦廣泛應用,比如NetBeans和Eclipse integrated development environments,檔共用程式如LimeWire和Vuze. Java還被應用於線性代數計算程式設計環境,包括使用者介面和部分系統核心功能.

移動設備

Java ME在移動設備上越來越流行,並開始與Symbian, BREW,和.NET Compact Framework展開競爭。

因為手機製造商的多樣性,需要一種新的統一標準,使程式可以運行於不同手機供應商製造的手機上。第一代這樣的標準是MIDP 1,它假設手機顯示幕很小,沒有音訊操作許可權,而且只允許小於32kb的程式運行。MIDP2有聲音存取權限,程式大小限制提高到了64kb。隨著手機設 計的能力和速度的快速提升,其發展速度遠比標準的制定快的多,一些廠商開始放鬆了對標準的遵守,比如允許更大的程式在手機上運行。


網路服務器和企業級應用

J2EE企業級架構

JavaEE

Java EE,Java平臺企業版(Java Platform Enterprise Edition),是Sun公司為企業級應用推出的標準平臺。Java平臺共分為三個主要版本Java EE、Java SE和Java ME。

Sun公司在1998年發表JDK1.2版本的時候,使用了新名稱Java 2 Platform,即“Java2平臺”,修改後的JDK稱為Java 2 Platform Software Developing Kit,即J2SDK。並分為標準版(Standard Edition,J2SE),企業版(Enterprise Edition,J2EE),微型版(MicroEdition,J2ME)。J2EE便由此誕生。

2005年6月,JavaOne大會召開,SUN公司公開Java SE 6。此時,Java的各種版本已經更名以取消其中的數字“2”:J2EE更名為Java EE, J2SE更名為Java SE,J2ME更名為Java ME。

隨著Java技術的發展,J2EE平臺得到了迅速的發展,成為Java語言中最活躍的體系之一。現如今,J2EE不僅僅是指一種標準平臺,它更多的表達著一種軟體架構和設計思想。

有疑問?請留言!

關注 Java聯盟,看Java要聞!

應當使用物件導向程式設計方法學

應當允許同一程式在不同的電腦平臺執行

應當包括內建的對電腦網路的支援

應當被設計成安全地執行遠端代碼

應當易於使用,並借鑒以前那些物件導向語言(如C++)的長處。

Java技術主要分成幾個部分:Java語言、Java運行環境、類庫。一般情況下說Java時並不區分指的是哪個部分。

Java在1.5版本時,做了重大改變,太陽公司並1.5版本重命名為Java 5.0。

物件導向

Java的特點之一就是物件導向, 是程式設計方法的一種。“物件導向程式設計語言”的核心之一就是開發者在設計軟體的時候可以使用自訂的類型和關聯操作。代碼和資料的實際集合體叫做“對 象”。一個物件可以想像成綁定了很多“行為(代碼)”和“狀態(資料)”的物體。對於資料結構的改變需要和代碼進行通信然後操作,反之亦然。物件導向設計 讓大型軟體工程的計畫和設計變得更容易管理,能增強工程的健康度,減少失敗工程的數量。

跨平臺性

Java語言的第二個特性就是跨平臺性,也就是說使用Java語言編寫的程式可以在編譯後不用經過任何更改,就能在任何硬體設備條件下運行。這個特性經常被稱為“一次編譯,到處運行”。


執行Java應用程式必須安裝Java Runtime Environment(JRE),JRE內部有一個Java虛擬機器(Java Virtual Machine,JVM)以及一些標準的類庫(Class Library)。通過JVM才能在電腦系統執行Java應用程式(Java Application),這與.Net Framework的情況一樣,所以電腦上沒有安裝JVM,那麼這些程式將不能夠執行。


實現跨平臺性的方法是大多數編譯器在進行Java語言程式的編碼時候會生成一個用位元組碼寫成的“半成品”,這個“半成品”會在Java虛擬機器(解釋層)的幫助下運行,虛擬機器會把它轉換成當前所處硬體平臺的原始代碼。之後,Java虛擬機器會打開標準庫,進行資料(圖片、執行緒和網路)的訪問工作。主要注意的是,儘管已經存在一個進行代碼翻譯的解釋層,有些時候Java的位元組碼代碼還是會被JIT編譯器進行二次編譯。


有些編譯器,比如GCJ,可以自動生成原始代碼而不需要解釋層。但是這些編譯器所生成的代碼只能應用於特定平臺。並且GCJ目前只支援部分的Java API。


甲骨文公司對於Java的許可是“全相容的”,這也導致了微軟和升陽關於微軟的程式不支援RMI和JNI介面、並且增加特性為己所用的法律爭端。升陽最終贏得了官司,獲得了大約兩千萬美元的賠償,法院強制要求微軟執行升陽公司關於Java的許可要求。作為回應,微軟不再在Windows系統中捆綁Java,最新的Windows版本,Windows Vista和Internet Explorer 7.0版本也不再提供對於Java應用程式和控制項的支援。但是升陽公司和其他使用Java運行時系統的公司在Windows作業系統下對使用者提供無償的協力廠商外掛程式和程式支援。


Java語言使用解釋層最初是為了輕巧性。所以這些程式的運行效率比C語言和C++要低很多,用戶也對此頗有微詞。很多最近的調查顯示Java的程式運行速度比幾年前要高出許多,有些同樣功能的程式的效率甚至超過了C++和C語言編寫的程式[來源請求]。


Java語言在最開始應用的時候是沒有解釋層的,所有需要編譯的代碼都直接轉換成機器的原始代碼。這樣做的後果就是獲得了最佳的性能,但是程式臃腫異常。從JIT技術開始,Java的程式都經過一次轉換之後才變成機器碼。很多老牌的協力廠商虛擬機器都使用一種叫做“動態編譯”的技術,也就是說虛擬機器即時監測和分析程式的運行行為,同時選擇性地對程式所需要的部分進行編譯和優化。所有這些技術都改善了代碼的運行速度,但是又不會讓程式的體積變得失常。


程式的輕便性事實上是軟體編寫很難達到的一個目標,Java雖然成功地實現了“一次編譯,到處運行”,但是由於平臺和平臺之間的差異,所編寫的程式 在轉換代碼的時候難免會出現微小的、不可察覺的錯誤和意外。有些程式師對此非常頭疼,他們嘲笑Java的程式不是“一次編譯,到處運行”,而是“一次編 譯,到處調試”。以Java AWT為例,早期Java AWT內提供的按鈕、文字區等均是以電腦系統所預設的樣式而顯示。這令Java程式在有些沒有提供圖案的電腦系統產生錯誤(在Microsoft Windows設有視窗管理器,在一些Linux distribution則沒有)。後來SUN公司針對Java AWT一些問題而推出Java Swing。


平臺無關性讓Java在伺服器端軟體領域非常成功。很多伺服器端軟體都使用Java或相關技術建立。

自動垃圾回收(Garbage Collection)

C++語言被使用者詬病的原因之一是大多數C++編譯器不支持垃圾收集機制。通常使用C++程式設計的時候,程式師于程式中初始化物件時,會在主機記憶體堆疊上分配一塊記憶體與位址,當不需要此物件時,進行析構或者刪除的時候再釋放分配的記憶體位址。如果物件是在堆疊上分配的,而程式師又忘記進行刪除,那麼就會造成記憶體洩漏(Memory Leak)。長此以往,程式運行的時候可能會生成很多不清除的垃圾,浪費了不必要的記憶體空間。而且如果同一記憶體位址被刪除兩次的話,程式會變得不穩定,甚 至崩潰。因此有經驗的C++程式師都會在刪除之後將指標重置為NULL,然後在刪除之前先判斷指針是否為NULL。


C++中也可以使用“智慧指標”(Smart Pointer)或者使用C++託管擴展編譯器的方法來實現自動化記憶體釋放,智慧指標可以在標準類庫中 找到,而C++託管擴展被微軟的Visual C++ 7.0及以上版本所支持。智慧指標的優點是不需引入緩慢的垃圾收集機制,而且可以不考慮執行緒安全的問題,但是缺點是如果不善使用智慧指標的話,性能有可能 不如垃圾收集機制,而且不斷地分配和釋放記憶體可能造成記憶體碎片,需要手動對堆進行壓縮。除此之外,由於智慧指標是一個基於範本的功能,所以沒有經驗的程式 員在需要使用多態特性進行自動清理時也可能束手無策。


Java語言則不同,上述的情況被自動垃圾收集功能自動處理。物件的創建和放置都是在記憶體堆疊上面進行的。當一個物件沒有任何引用的時候,Java的自動垃圾收集機制就發揮作用,自動刪除這個物件所佔用的空間,釋放記憶體以避免記憶體洩漏。


注意程式師不需要修改finalize方法,自動垃圾收集也會發生作用。但是記憶體洩漏並不是就此避免了,當程式師疏忽大意地忘記解除一個物件不應該有的引用時,記憶體洩漏仍然不可避免。


不同廠商、不同版本的JVM中的記憶體垃圾回收機制並不完全一樣,通常越新版本的記憶體回收機制越快,IBM、BEA、SUN等等開發JVM的公司都曾宣稱過自己製造出了世界上最快的JVM[來源請求],JVM性能的世界紀錄也在不斷的被打破並提高。
IBM有一篇有關Java記憶體回收機制比不啟動垃圾收集機制的C++記憶體處理快數倍的技術文章[14],而著名的Java技術書籍《Java程式設計思想》(Thinking in Java)也有一段論述Java記憶體及性能達到甚至超過C++的章節[15] 。

基本語法

編寫Java程式前應注意以下幾點:

大小寫敏感:Java是大小寫敏感的,這就意味著識別字Hello與hello是不同的。

類名:對於所有的類來說,類名的首字母應該大寫。如果類名由若干單詞組成,那麼每個單詞的首字母應該大寫,例如MyFirstJavaClass。

方法名:所有的方法名都應該以小寫字母開頭。如果方法名含有若干單詞,則後面的每個單詞首字母大寫,例如myFirstJavaMethod。

原始檔案名:原始檔案名必須和類名相同。當保存檔的時候,你應該使用類名作為檔案名保存(切記Java是大小寫敏感的),檔案名的尾碼為.java。(如果檔案名和類名不相同則會導致編譯錯誤)。

主方法入口:所有的Java程式由public static void main(String[] args)方法開始執行。

Java關鍵字

關鍵字 下面列出了Java關鍵字。這些關鍵字不能用於常量、變數、和任何識別字的名稱。

關鍵字 描述abstract抽象方法,抽象類別的修飾符assert斷言條件是否滿足continue不執行循環體剩餘部分defaultswitch語句中的預設分支do-while迴圈語句,循環體至少會執行一次double64-bit雙精度浮點數elseif條件不成立時執行的分支enum枚舉類型extends表示一個類是另一個類的子類final表示定義常量finally無論有沒有異常發生都執行代碼float32-bit單精確度浮點數forfor迴圈語句goto用於流程控制if條件陳述式implements表示一個類實現了介面import導入類instanceof測試一個物件是否是某個類的實例int32位元整型數interface介面,一種抽象的類型,僅有方法和常量的定義long64位整型數native表示方法用非java代碼實現new分配新的類實例package一系列相關類組成一個包private表示私有欄位,或者方法等,只能從類內部訪問protected表示保護類型欄位public表示共有屬性或者方法return方法返回值short16位元數字static表示在類級別定義,所有實例共用的strictfp浮點數比較使用嚴格的規則super表示基類switch選擇語句synchronized表示同一時間只能由一個執行緒訪問的代碼塊this調用當前實例或者調用另一個構造函數throw拋出異常throws定義方法可能拋出的異常transient修飾不要序列化的欄位try表示代碼塊要做異常處理void標記方法不返回任何值volatile標記欄位可能會被多個執行緒同時訪問,而不做同步whilewhile迴圈

介面和類別

Java自帶了創建介面的類別,可以這樣使用:

publicinterfaceDeleteable{
voiddelete();
}

這段代碼的意思是任何實現(implement)Deleteable介面的類別都必須實現delete()方法。每個類別對這個方法的實現可以自行定制。由此概念可以引出很多種使用方法,下面是一個類別的例子:

publicclassFredimplementsDeleteable
{
//必須實作Deleteable介面中的delete方法
@Overridepublicvoiddelete(){
//實作的程式碼
}
//這個類別也可以包含其他方法
publicvoiddoOtherStuff(){
}
}

在另外一個類別中,可以使用這樣的代碼:

publicvoiddeleteAll(Deleteable[]list){
for(inti=0;
ilist.length;
i++){
list[i].delete();
}
}

因為佇列中所有的物件都可以使用delete()方法。Deleteable佇列中包含Fred物件的引用,而這個類別和其他Deleteable類別在使用deleteAll()方法時候不需要進行任何改變。


之所以這樣做就是為了在介面的執行和其代碼之間進行區別。舉例來說,一個名叫Collection的介面可以包含任何物件所需要的引入、轉換和存儲資料的方法,其他的類都可以使用這個介面。但是這個介面可以是一個可重定義大小的佇列、一個鏈表或者是其他功能的集合。


這種特性其實是一種折中的辦法。Java的設計者們不想讓Java有多重繼承的特性,因為C++的多重繼承顯示了這種特性的困難。Java的介面功能可以提供同樣的功能,但是又不會很複雜。

應用程式開發介面

在Java語言中,應用程式介面(API)化身成類,並且分組成為包。每個包中包含有相關的介面和類。對於不同的平臺,Java提供了不同版本的包。API的設定由sun公司和其他公司通過JCP(Java社區程式)決定。任何公司和個人都可以參與這個工程,對API進行設計。2004年,IBM和BEA公司準備聯合對官方的Java開源軟體工程進行支持,但是2005年初,sun公司拒絕了這個支持。

關於Java的批評

整體性問題

並不是所有的工程和環境需要企業檔次的複雜性,比如一個簡單的個人網站或者獨自程式設計的程式師所寫的程式。這些程式師會發現Java的複雜管理對於自己要做的程式來說過於強大了。一些人覺得Java在物件導向上面做的沒有Ruby和Smalltalk純粹。但是最新出現的用Java實現的語言Groovy解決了這些問題。

作為一種已經創建的新技術,Java顯然綜合了很多語言的特性,比如C++、C語言、Python等等。一些對於Java的評論認為Java的不變性在動搖。

語言問題

有些程式師不喜歡原始類型(primitive type)和類別(class)的分離,尤其是那些曾經使用過Smalltalk和Ruby的程式師。Java的代碼相對於其他的代碼來說過於冗長,這與它的輕便化聲明相違背。

Java是一種單層繼承的語言。這也導致了程式師在試圖使用多重繼承時候的不便,而很多語言都可以使用這個特性。但是Java可以使用介面類別,把多重繼承可能導致的風險減少到最小。Java不支持運算子重載,這是為了防止運算子重載使得代碼的功能變得不清晰。但是用Java實現的語言Groovy可以進行運算子重載。過去Java對於文本的操作和其他語言,比如Perl和PHP相比差的較多,但Java在1.4版本時候引入了規則運算式。

至Java 1.7為止,Java語言不支援閉包(closure)和混入(mixin)特性。

Java 1.8加入閉包(Lambda Expressions) 。

類庫問題

使用Swing平臺編寫的帶有GUI(圖形化使用者介面)的程式和其他原始程式非常不同。選用AWT工 具包編寫程式的程式師看到的都是原始介面,而且也無法獲得先進的GUI程式設計支援,如果使用的話,就要提供每個平臺上面所需的API,這將是一項龐大的工 程。Swing則是完全用Java語言所寫的程式,避免了介面元素重複的問題,只使用所有平臺都支持的最基本的繪圖機制。但是很多用戶不知道如何在 Java風格和Windows風格之間進行轉換,結果造成了Java程式的介面在很多程式中非常特殊。蘋果電腦已經提供了優化過的Java運行時程式,包含了Mac OS X的經典Aqua介面風格。

在IBM捐贈給Eclipse基金會的SWT介面框架中,使用者會看到熟悉的本地風格介面。但這又引起了不同喜好的開發人員之間的爭論。

性能問題

由於Java編譯器和虛擬機器的不同對Java代碼的性能影響比語言本身的影響大的多,所以統一討論Java的程式的性能經常是有誤導性的。據IBM的資料,在同樣的硬體上2001年時的IBM JDK版本的性能是1996年的JDK版本的十倍左右。

Java語言的一些特性不可避免的有額外的性能代價,例如陣列範圍檢查、運行時類型檢查等等。Java程式的性能還會因為不同的動態複雜性和垃圾處 理機制使用的多少而各有不同。如果JVM的實現比較優化的話,那麼這些功能甚至可以增加記憶體分配的性能。這和總是使用STL或者託管C++的程式的情況類 似。

儘管如此,仍然有許多人認為Java的性能低。這部分歸因於Sun公司最初的JVM實現使用未優化的解釋機制來運行位元組碼。一些新版本的JVM使用Just-In-Time(JIT) 編譯器,在載入位元組碼的時候將其編譯成針對運行環境的本地代碼來實現一些本地編譯器的優化特性。Just-In-Time機制和本地編譯的性能比較仍舊是 一個有爭議的話題。JIT編譯需要很多時間,對於執行時間不長或者代碼很多的大型程式並不適宜。但是不算JIT編譯階段的話,程式的運行性能在很多JVM下可以和本地編譯的程式一爭短長,甚至在一些計算比較密集的數值計算領域也是這樣。目前,Java已經使用更先進的HotSpot技 術來代替JIT技術,Java的性能有了更進一步的提升。另外,在使用-server選項運行Java程式時,也可以對Java進行更深入的優化,比如在 運行時將調用較多的方法內聯(inline)到程式中來提高運行速度,這就是所謂的“動態優化”,而本地編譯器是無法做到這一點的;這也是一些Java代 碼比對應用C/C++等語言編寫的本地代碼運行的更快的原因之一。微軟的.NET平臺也使用JIT編譯器,所以也有類似問題。

Java的設計目的主要是安全性和可攜性,所以對於一些特性,比如對硬體架構和記憶體位址訪問的直接訪問都被去除了。如果需要間接調用這些底層功能的話,就需要使用JNI(Java 本地介面)來調用本地代碼,而間接訪問意味著頻繁調用這些特性時性能損失會很大,微軟的.NET平臺也有這樣的問題。所以到目前為止,性能敏感的代碼,例 如驅動程式和3D視頻遊戲,還是大多使用本地編譯,甚至直接以不直接支援物件導向的C語言或機器碼編寫。但最近已經有了許多用純Java編寫的3D遊戲, 其效果與用C語言編寫的不相上下,例如“合金戰士”(英文名:Chrome)。這主要是因為新版的Java 3D技術已經能像C++一樣調用硬體加速,也就是使用顯卡來加速,無論是C++還是Java語言寫的3D遊戲都是使用顯卡及GPU來處理,從而使得CPU可以專注於其他方面的工作。

Java平臺

Java平臺即由Java程式設計語言所撰寫的軟體賴以運行的平臺,是Java軟體和電腦系統的仲介,最初被設計用在 Applet 等桌面端程式,不過後來逐漸轉移到服務端的運用。

Java 運行環境

Java 運行環境,即Java Runtime Environment,簡稱為JRE,是在任何平臺上運行Java編寫的程式都需要用到的軟體。終端使用者可以以軟體或者外掛程式方式得到和使用 JRE。Sun 公司還發佈了一個JRE的更複雜的版本,叫做JDK,即Java 2開發包,裡面包含了Java需要的編譯器、參考文檔和調試器等。

JRE的成分

Java的類庫,包含了編譯Java程式所需要的最核心檔。

核心庫檔,其中有

資料結構的庫,包括清單、字典和樹等

XML分析庫

安全方面應用庫

國際化和當地語系化應用庫

綜合庫檔,包含了程式師和其他系統通信的功能檔。

JDBC,即Java資料庫聯通的API

JNDI,即Java命名和目錄介面

RMI和CORBA用於重新分發軟體

使用者介面庫檔,包含:

AWT,即抽象視窗開發包,提供了產生圖形化使用者介面所需要的功能

Swing庫

其他用於回訪媒體檔、錄音、截圖的庫

一個用於執行軟體的Java虛擬機器(JVM)

外掛程式,可以在流覽器裡面使用

JWS,可以讓終端使用者連接到互聯網

許可檔和文檔

桌面的應用

根據Sun公司的統計,安裝Java運行環境的個人電腦已經超過7億。 [1]自從Sun指控微軟添加Windows特效類檔到Java運行環境(JRE),並通過Visual J++運行這些類檔,微軟不再綁定Java運行環境到Windows作業系統。Apple的Mac OS X一般默認綁定Java運行環境, 而且許多Linux發行版本也綁定一些相容的自由套裝軟體GNU Classpath。


一些Java軟體被桌上型電腦廣泛應用,比如NetBeans和Eclipse integrated development environments,檔共用程式如LimeWire和Vuze. Java還被應用於線性代數計算程式設計環境,包括使用者介面和部分系統核心功能.

移動設備

Java ME在移動設備上越來越流行,並開始與Symbian, BREW,和.NET Compact Framework展開競爭。

因為手機製造商的多樣性,需要一種新的統一標準,使程式可以運行於不同手機供應商製造的手機上。第一代這樣的標準是MIDP 1,它假設手機顯示幕很小,沒有音訊操作許可權,而且只允許小於32kb的程式運行。MIDP2有聲音存取權限,程式大小限制提高到了64kb。隨著手機設 計的能力和速度的快速提升,其發展速度遠比標準的制定快的多,一些廠商開始放鬆了對標準的遵守,比如允許更大的程式在手機上運行。


網路服務器和企業級應用

J2EE企業級架構

JavaEE

Java EE,Java平臺企業版(Java Platform Enterprise Edition),是Sun公司為企業級應用推出的標準平臺。Java平臺共分為三個主要版本Java EE、Java SE和Java ME。

Sun公司在1998年發表JDK1.2版本的時候,使用了新名稱Java 2 Platform,即“Java2平臺”,修改後的JDK稱為Java 2 Platform Software Developing Kit,即J2SDK。並分為標準版(Standard Edition,J2SE),企業版(Enterprise Edition,J2EE),微型版(MicroEdition,J2ME)。J2EE便由此誕生。

2005年6月,JavaOne大會召開,SUN公司公開Java SE 6。此時,Java的各種版本已經更名以取消其中的數字“2”:J2EE更名為Java EE, J2SE更名為Java SE,J2ME更名為Java ME。

隨著Java技術的發展,J2EE平臺得到了迅速的發展,成為Java語言中最活躍的體系之一。現如今,J2EE不僅僅是指一種標準平臺,它更多的表達著一種軟體架構和設計思想。

有疑問?請留言!

關注 Java聯盟,看Java要聞!