anonymous的Java學習筆記之(1)——Java語言概述與開發環境

Java語言概述與開發環境

Java語言發展簡史

概述

Java語言是一門非常純粹的面向對象編程語言,它吸收了C++語言的各種優點,又摒棄了C++裏難以理解的多繼承、指針等概念,因此Java語言具有功能強大和簡單易用兩個特徵。Java語言作爲靜態面向對象編程語言的代表,極好地實現了面向對象理論,允許程序員以優雅的思維方式進行復雜的編程開發。

Java語言發展歷程

Java語言發展歷程-13726692df4d484f856c8fb9d2c6b01f

編譯型語言和解釋型語言

Java語言是一種特殊的高級語言,它既具有解釋型語言的特徵,也具有編譯型語言的特徵,因爲Java程序要經過先編譯,後解釋兩個步驟。

計算機高級語言按程序的執行方式可以分爲編譯型和解釋型兩種。

  • 編譯型語言是指使用專門的編譯器,針對特定平臺(操作系統)將某種高級語言源代碼一次性"翻譯"成可被該平臺硬件執行的機器碼(包括機器指令和操作數),幷包裝成該平臺所能識別的可執行性程序的格式,這個轉換過程稱爲編譯(Compile)。編譯生成的可執行性程序可以脫離開發環境,在特定的平臺上獨立運行。
    • 有些程序編譯結束後,還可能需要對其他編譯好的目標代碼進行鏈接,即組裝兩個以上的目標代碼模塊生成最終的可執行性程序,通過這種方式實現低層次的代碼複用。
    • 因爲編譯型語言是一次性地編譯成機器碼,所以可以脫離開發環境獨立運行,而且通常運行效率較高;但因爲編譯型語言的程序被編譯成特定平臺上的機器碼,因此編譯生成的可執行性程序通常無法移植到其他平臺上運行;如果需要移植,則必須將源代碼複製到特定平臺上,針對特定平臺進行修改,至少也需要採用特定平臺上的編譯器重新編譯。
    • 現有的C、C++、Objective-C、Swift、Kotlin等高級語言都屬於編譯型語言。
  • 解釋型語言是指使用專門的解釋器對源程序逐行解釋成特定平臺的機器碼並立即執行的語言。
    • 解釋型語言通常不會進行整體性的編譯和鏈接處理,解釋型語言相當於把編譯型語言中的編譯和解釋過程混合到一起同時完成。
    • 可以認爲:每次執行解釋型語言的程序都需要進行一次編譯,因此解釋型語言的程序運行效率通常較低,而且不能脫離解釋器獨立運行。但解釋型語言有一個優勢:跨平臺比較容易,只需提供特定平臺的解釋器即可,每個特定平臺上的解釋器負責將源程序解釋成特定平臺的機器指令即可。解釋型語言可以方便地實現源程序級的移植,但這是以犧牲程序執行效率爲代價的。
    • 現有的JavaScript、Ruby、Python等語言都屬於解釋型語言。

Java語言的編譯,解釋運行機制

Java語言比較特殊,由Java語言編寫的程序需要經過編譯步驟,但這個編譯步驟並不會生成特定平臺的機器碼,而是生成一種與平臺無關的字節碼(也就是*.class文件)。當然,這種字節碼不是可執行的,必須使用Java解釋器來解釋執行。因此可以認爲:Java語言既是編譯型語言,也是解釋型語言。或者說,Java語言既不是純粹的編譯型語言,也不是純粹的解釋型語言。Java程序的執行過程必須經過先編譯、後解釋兩個步驟,如下圖所示。

image-20200321125950015-acbc088974fb40bc97fc3962d893da46

通過JVM實現跨平臺

  • Java語言裏負責解釋執行字節碼文件的是Java虛擬機,即JVM(JavaVirtualMachine) JVM是可運行Java字節碼文件的虛擬計算機。所有平臺上的JVM向編譯器提供相同的編程接口,而編譯器只需要面向虛擬機,生成虛擬機能理解的代碼,然後由虛擬機來解釋執行。在一些虛擬機的實現中,還會將虛擬機代碼轉換成特定系統的機器碼執行,從而提高執行效率。
  • 當使用Java編譯器編譯Java程序時,生成的是與平臺無關的字節碼,這些字節碼不面向任何具體平臺,只面向JVM。不同平臺上的JVM都是不同的,但它們都提供了相同的接口。JVM是Java程序跨平臺的關鍵部分,只要爲不同平臺實現了相應的虛擬機,編譯後的Java字節碼就可以在該平臺上運行。顯然,相同的宇節碼程序需要在不同的平臺上運行,這幾乎是"不可能的",只有通過中間的轉換器纔可以實現,JVM就是這個轉換器。
  • JVM是一個抽象的計算機,和實際的計算機一樣,它具有指令集並使用不同的存儲區域。它負責執行指令,還要管理數據、內存和寄存器。

JVM的作用很容易理解,就像有兩支不同的筆,但需要把同一個筆帽套在兩支不同的筆上,只有爲這兩支筆分別提供一個轉換器,這個轉換器向上的接口相同,用於適應同一個筆帽;向下的接口不同,用於適應兩支不同的筆。在這個類比中,可以近似地理解兩支不同的筆就是不同的操作系統,而同一個筆帽就是Java字節碼程序,轉換器角色則對應JVM。類似地,也可以認爲JVM分爲向上和向下兩個部分,所有平臺上的JVM向上提供給Java字節碼程序的接口完全相同,但向下適應不同平臺的接口則互不相同。

Oracle公司制定的Java虛擬機規範在技術上規定了JVM的統一標準,具體定義了JVM的如下細節:

  • 指令集
  • 寄存器
  • 類文件的格式
  • 垃圾回收堆
  • 存儲區

Oracle公司制定這些規範的目的是爲了提供統一的標準,最終實現Java程序的平臺無關性。

安裝JDK

在開發Java程序之前,必須先完成一些準備工作,也就是在計算機上安裝並配置Java開發環境,開發Java程序需要安裝和配置JDK。

Java JDK在linux系統有兩個版本,一個開源版本OpenJDK,還有一個oracle官方版本JDK。目前企業裏沒有特殊需求的話都是使用的Java8版本的OpenJDK。

Ubuntu18.04安裝Java8的JDK

卸載Ubuntu自帶的OpenJDK 11

sudo apt-get remove openjdk*

更新軟件包列表

sudo apt-get update

安裝openjdk-8-jdk

sudo apt-get install openjdk-8-jdk

查看java版本,驗證是否安裝成功

java -version

終端輸出

openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-8u242-b08-0ubuntu3~18.04-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

查看javac版本,驗證是否安裝成功

javac 1.8.0_242

終端輸出

javac 1.8.0_242

一般而言,如果只是運行Java程序,可以只安裝JRE,無須安裝JDK。

注意:

  • 如果需要開發Java程序,則應該選擇安裝JDK;當然,安裝了JDK之後,就包含了JRE,也可以運行Java程序。但如果只是運行Java程序,則需要在計算機上安裝JRE,僅安裝JVM是不夠的。實際上,Oracle網站上提供的就是JRE的下載,並不提供單獨JVM的下載。
  • Oracle把Java分爲JavaSE、JavaEE和JavaME三個部分,而且爲JavaSE和JavaEE分別提供了JDK和JavaEESDK(SoftwareDevelopmentKit)兩個開發包,如果讀者只需要學習JavaSE的編程知識,則可以下載標準的JDK;如果讀者學完JavaSE之後,還需要繼續學習JavaEE相關內容,也可以選擇下載JavaEESDK,有一個JavaEESDK版本里己經包含了最新版的JDK,安裝JavaEESDK就包含了JDK。
  • JavaSE,JavaEE,JavaME三者的區別:
    • JavaSE:即J2SE,java標準版,主要做一般的java應用,比如,應用軟件/QQ之類的通信軟件等等.
    • JavaEE:即J2EE,主要做企業應用,比如公司網站,企業解決方案等;
    • JavaME:即J2ME,主要面向嵌入式等設備應用的開發,比如手機遊戲等.

編寫,運行Java程序

編寫Hello World

public class HelloWorld {
    //main方法,程序的入口
    public static void main(String[] args) {
        //打印Hello World!並換行
        System.out.println("Hello World!");
        //打印Hello World!不換行
        System.out.print("Hello World!");
        System.out.print("Hello World!");
    }
}

編輯上面的Java文件時,注意程序中粗體宇標識的單詞,Java程序嚴格區分大小寫。

Java程序的組織形式

  • Java程序是一種純粹的面向對象的程序設計語言,因此Java程序必須以類(class)的形式存在,類(class)是Java程序的最小程序單位。Java程序不允許可執行性語句、方法等成分獨立存在,所有的程序部分都必須放在類定義裏。
  • Java解釋器規定:如需某個類能被解釋器直接解釋執行,則這個類裏必須包含main方法,而且main方法必須使用public static void來修飾,且main方法的形參必須是字符串數組類型(String[] args是字符串數組的形式)。也就是說,main方法的寫法幾乎是固定的。Java虛擬機就從這個main方法開始解釋執行,因此,main方法是Java程序的入口。
  • 對於那些不包含main方法的類,也是有用的類。對於一個大型的Java程序而言,往往只需要一個入口,也就是隻有一個類包含main方法,而其他類都是用於被main方法直接或間接調用的。

Java源文件的命名規則

Java程序源文件的命名不是隨意的,Java文件的命名必須滿足如下規則。

  • Java程序源文件的擴展名必須是.java,不能是其他文件擴展名。
  • 在通常情況下,Java程序源文件的主文件名可以是任意的。但有一種情況例外:如果Java程序源代碼裏定義了一個public類,則該源文件的主文件名必須與該public類(也就是該類定義使用了public關鍵宇修飾〉的類名相同。
  • 由於Java程序源文件的文件名必須與public類的類名相同,因此,一個Java源文件裏最多隻能定義一個public類。
  • 一個Java源文件可以包含多個類定義,但最多隻能包含一個public類定義;如果Java源文件裏包含public類定義,則該源文件的文件名必須與這個public類的類名相同。
  • 雖然Java源文件裏沒有包含public類定義時,這個源文件的文件名可以是隨意的,但推薦讓Java源文件的主文件名與類名相同,這可以提供更好的可讀性。通常有如下建議:
    • 一個Java源文件只定義一個類,不同的類使用不同的源文件定義。
    • 讓Java源文件的主文件名與該源文件中定義的public類同名。

初學者易犯的錯誤

CLASSPATH 環境變量的問題

  • 如果使用1.5以上版本的JDK,完全可以不用設置這個環境變量。如果不設置這個環境變量,將可以正常編譯和運行Java程序。

大小寫問題

  • Java語言是嚴格區分大小寫的語言。(Linux平臺是區分大小寫的)。
  • 例如classClass是不同的兩個詞,class是正確的,但如果寫成Class,則程序無法編譯通過。實際上,Java程序中的關鍵宇全部是小寫的,無須大寫任何字母。

main方法的問題

  • 如果需要用Java命令直接運行一個Java類,這個Java類必須包含main方法
  • 這個main方法必須使用publicstatic來修飾,必須使用void聲明該方法的返回值
  • 且該方法的參數類型只能是一個字符串數組,而不能是其他形式的參數。對於這個main方法而言,前面的publicstatic修飾符的位置可以互換,但其他部分則是固定的
  • 在Java程序裏執行輸出有兩種簡單的方式:System.out.print(需要輸出的內容)System.out.println(需要輸出的內容),其中前者在輸出結束後不會換行,而後者在輸出結束後會換行。

Java的垃圾回收機制

  • 與C/C++程序不同,Java語言不需要程序員直接控制內存回收,Java程序的內存分配和回收都是由JRE在後臺自動進行的。JRE會負責回收那些不再使用的內存,這種機制被稱爲垃圾回收(Garbage Collection,GC)。通常JRE會提供一個後臺線程來進行檢測和控制,一般都是在CPU空閒或內存不足時自動進行垃圾回收,而程序員無法精確控制垃圾回收的時間和順序等。
  • 垃圾回收能自動釋放內存空間,減輕編程的負擔。這使Java虛擬機具有兩個顯著的優點。
    • 垃圾回收機制可以很好地提高編程效率。在沒有垃圾回收機制時,可能要花許多時間來解決一個難懂的存儲器問題。在用Java語言編程時,依靠垃圾回收機制可大大縮短時間。
    • 垃圾回收機制保護程序的完整性,垃圾回收是Java語言安全性策略的一個重要部分。
  • 通常,垃圾回收具有如下幾個特點。
    • 垃圾回收器的工作目標是回收無用對象的內存空間,這些內存空間都是JVM堆內存裏的內存空間,垃圾回收器只能回收內存資源,對其他物理資源,如數據庫連接、磁盤I/O等資源則無能爲力。
    • 爲了更快地讓垃圾回收器回收那些不再使用的對象,可以將該對象的引用變量設置爲null,通過這種方式暗示垃圾回收器可以回收該對象。
    • 垃圾回收發生的不可預知性。由於不同JVM採用了不同的垃圾回收機制和不同的垃圾回收算法,因此它有可能是定時發生的,有可能是當CPU空閒時發生的,也有可能和原始的垃圾回收一樣,等到內存消耗出現極限時發生,這和垃圾回收實現機制的選擇及具體的設置都有關係。雖然程序員可以通過調用Runtime對象的gc()System.gc()等方法來建議系統進行垃圾回收,但這種調用僅僅是建議,依然不能精確控制垃圾回收機制的執行。
    • 垃圾回收的精確性主要包括兩個方面:
      • 一是垃圾回收機制能夠精確地標記活着的對象
      • 二是垃圾回收器能夠精確地定位對象之間的引用關係。前者是完全回收所有廢棄對象的前提,否則就可能造成內存泄漏;而後者則是實現歸併和複製等算法的必要條件,通過這種引用關係,可以保證所有對象都能被可靠地回收,所有對象都能被重新分配,從而有效地減少內存碎片的產生。
    • 現在的JVM有多種不同的垃圾回收實現,每種回收機制因其算法差異可能表現各異,有的當垃圾回收開始時就停止應用程序的運行,有的當垃圾回收運行時允許應用程序的線程運行,還有的在同一時間允許垃圾回收多線程運行。

當編寫Java程序時,一個基本原則是:對於不再需要的對象,不要引用它們。如果保持對這些對象的引用,垃圾回收機制暫時不會回收該對象,則會導致系統可用內存越來越少;當系統可用內存越來越少時,垃圾回收執行的頻率就越來越高,從而導致系統的性能下降。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章