瘋狂Java講義-面向?qū)ο螅ㄏ拢?/h2>

面向?qū)ο螅ㄏ拢?/h1>

本章思維導(dǎo)圖

4-0面向?qū)ο螅ㄏ拢?png

包裝類(Wrapper Class)

解決8種基本數(shù)據(jù)類型當(dāng)成Object類型變量使用

基本數(shù)據(jù)類型的包裝類

  • byte == Byte
  • short == Short
  • int == Integer
  • long == Long
  • char == Character
  • float == Float
  • double == Double
  • boolean == Boolean

JKD1.5提供了自動(dòng)裝箱(Autoboxing)和自動(dòng)拆箱(AutoUnboxing)

  • 自動(dòng)裝箱是把一個(gè)基本數(shù)據(jù)類型變量直接賦給對(duì)應(yīng)的包裝類變量或者賦給Object變量
  • 自動(dòng)拆箱是直接把包裝類對(duì)象直接賦給一個(gè)對(duì)應(yīng)的基本類型變量

包裝類可實(shí)現(xiàn)基本類型變量和字符串之間的轉(zhuǎn)換

  • 把字符串類型的值轉(zhuǎn)換為基本類型的值
    • parseXxx(String s) 靜態(tài)方法,除Character之外所有包裝類都提供了該方法
    • valueOf(String s) 靜態(tài)方法

包裝類的引用類型變量可以直接和基本數(shù)據(jù)類型作比較

  • 但是Integer包裝類直接把-128~127之間的整數(shù)放入cache數(shù)組中緩存起來(lái)
  • 包裝類提供了一個(gè)靜態(tài)compare(xxx var1, xxx var2)方法,來(lái)比較兩個(gè)基本類型值的大小

包裝類無(wú)符號(hào)運(yùn)算的方法

Integer、Long

static String toUnsignedString(int/long i)

  • 指定int或long型整數(shù)轉(zhuǎn)換為無(wú)符號(hào)整數(shù)對(duì)應(yīng)的字符串

static String toUsignedString(int\long i, int radix)

  • 指定int或long型整數(shù)轉(zhuǎn)換為指定進(jìn)制的無(wú)符號(hào)整數(shù)對(duì)應(yīng)的字符串

static xxx parseUnsignedXxx(String s)

  • 指定字符串解析成無(wú)符號(hào)整數(shù)

static xxx parseUnsignedXxx(String s, int radix)

  • 指定字符串按指定進(jìn)制解析成無(wú)符號(hào)整數(shù)

static int compareUnsigned(xxx x, xxx y)

  • 將x、y兩個(gè)整數(shù)轉(zhuǎn)換為無(wú)符號(hào)整數(shù)后比較大小

Byte、Short

toUnsignedInt(xxx x)

toUnsignedLong(xxx x)

  • 無(wú)符號(hào)類就是把二進(jìn)制代碼的最高位的符號(hào)位當(dāng)成數(shù)值類處理

處理對(duì)象

打印對(duì)象和toString方法

  • 直接打印對(duì)象名是 類名+@+hashCode
  • toString()方法是Object類的一個(gè)實(shí)例方法
    • 是一個(gè)特殊的方法,是一個(gè)“自我描述”的方法
    • 重寫(xiě)類的toString()方法,可對(duì)類介紹
    • 類名[field1=值1, field2=值2, ...]

==和equals方法

  • 對(duì)于兩個(gè)引用類型變量,只有都指向同一個(gè)對(duì)象時(shí),==才會(huì)返回true
    • ==不可用于比較類型上沒(méi)有父子關(guān)系的兩個(gè)對(duì)象
    • "hello"直接量和new String("hello")的區(qū)別
      • 使用形如"hello"的字符串直接量,JVM將會(huì)使用常量池來(lái)管理這些字符串
      • 使用new String("hello")時(shí),JVM會(huì)先使用常量池來(lái)管理"hello"直接量,在調(diào)用String類的構(gòu)造器來(lái)創(chuàng)建一個(gè)新的String對(duì)象,新創(chuàng)建的String對(duì)象被保存在堆內(nèi)存中
      • new String("hello")一共產(chǎn)生了兩個(gè)字符串對(duì)象
      • 常量池(constant pool)專門(mén)用戶管理在編譯時(shí)被確定并被保存在已編譯的.class文件中的一些數(shù)據(jù)。它包括了關(guān)于類、方法、接口中的常量,還包括字符串常量
        • 常量池保住相同的字符串直接量只有一個(gè)
  • equals()方法
    • equals()方法是Object類提供的一個(gè)實(shí)例方法
      • 重寫(xiě)equals()方法來(lái)實(shí)現(xiàn)自定義的相等標(biāo)準(zhǔn)
    • String的equals()方法用來(lái)判斷兩個(gè)字符串是否相等
    • 實(shí)例名.getCall()類名.class
    • 正確重寫(xiě)euqls()方法應(yīng)該滿足的條件
      • 自反性:對(duì)任意x,x.equals(x)一定返回true
      • 對(duì)稱性:對(duì)任意x和y,如果y.equals(x)返回true,則x.equals(y)也返回true
      • 傳遞性:對(duì)任意x、y、z,如果x.equals(y)返回true,y.equals(z)返回true,則x.equals(z)一定返回true
      • 對(duì)任何不是null的x,x.equals(null)一定返回false

類成員

static關(guān)鍵字修飾的成員就是類成員

static可以修飾成員變量、方法、初始化塊、內(nèi)部類(接口、枚舉)

不允許類成員訪問(wèn)實(shí)例成員

單例(Singleton)類

  • 一個(gè)類始終只能創(chuàng)建一個(gè)實(shí)例
  • 把類構(gòu)造器使用private修飾,提供一個(gè)public方法作為該類的訪問(wèn)點(diǎn),用于創(chuàng)建該類的對(duì)象,且該方法必須使用static修飾
  • 該類還必須緩存已經(jīng)創(chuàng)建過(guò)的對(duì)象,用來(lái)判斷該類是否曾經(jīng)創(chuàng)建過(guò)對(duì)象

final修飾符

final關(guān)鍵字可用于修飾類、變量、方法,用于表示不可改變

final成員變量

  • 必須由程序員顯式地指定初始值
  • 類變量
    • 必須在靜態(tài)初始化塊中指定初始值或聲明該類變量時(shí)指定初始值
  • 實(shí)例變量
    • 必須在非靜態(tài)初始化塊、聲明該實(shí)例變量或構(gòu)造器中指定初始值
  • 在顯式初始化之前不能訪問(wèn),但可以通過(guò)方法來(lái)訪問(wèn)(java的一個(gè)缺陷)

final局部變量

final修飾的形參,不允許在方法內(nèi)被賦值

可執(zhí)行“宏替換”的final變量

  • 只要滿足3個(gè)條件,final變量就不再是一個(gè)變量,而是相當(dāng)于一個(gè)直接量
    • 使用final修飾
    • 在定義時(shí)制定了初始值
    • 該初始值可以在編譯時(shí)確定下來(lái)

final方法

  • final修飾的方法不可被重寫(xiě)
  • 子類可重寫(xiě)private final修飾的方法
    • 因?yàn)?code>private修飾的方法,子類無(wú)法訪問(wèn),如果子類定義了相同方法名、相同形參列表、相同返回值類型的方法,只是重新定義了一個(gè)新方法

final類

  • final修飾的類不可以有子類

不可變(immutable)類

創(chuàng)建類的實(shí)例后,該實(shí)例的實(shí)例變量不可改變

  • 規(guī)則
    • 使用private和final修飾該類的成員變量
    • 提供帶參數(shù)的構(gòu)造器,用于根據(jù)傳入?yún)?shù)來(lái)初始化類里的成員變量
    • 僅為類的成員變量提供getter方法,不提供setter方法
  • 注意引用類型的成員變量

抽象類

  • 有抽象方法的類只能定義成抽象類
  • 抽象類里可以沒(méi)有抽象方法

規(guī)則

  • 抽象類必須使用abstract來(lái)修飾,抽象方法也必須使用abstract來(lái)修飾,抽象方法不能有方法體
  • 抽象類不能被實(shí)例化
  • 抽象類可以包含成員變量、方法(普通方法、抽象方法)、構(gòu)造器、初始化塊、內(nèi)部類(接口、枚舉)
    • 抽象類的構(gòu)造器不能用于創(chuàng)建實(shí)例,主要是用于被其子類調(diào)用
  • 含有抽象方法的類(直接定義了一個(gè)抽象方法、繼承了一個(gè)抽象父類,但沒(méi)有完全實(shí)現(xiàn)父類包含的抽象方法、實(shí)現(xiàn)了一個(gè)接口,但沒(méi)有完全實(shí)現(xiàn)接口包含的抽象方法)只能被定義成抽象類

abstract修飾類時(shí),表明這個(gè)類只能被繼承

abstract修飾方法時(shí),表明這個(gè)方法必須由子類提供實(shí)現(xiàn)(重寫(xiě))

final和abstract永遠(yuǎn)不能同時(shí)使用

接口

更特殊的抽象類,接口(interface)

[修飾符] interface 接口名 extends 父接口1,... {
    零個(gè)到多個(gè)常量定義...
    零個(gè)到多個(gè)抽象方法定義...
    零個(gè)到多個(gè)內(nèi)部類、接口、枚舉定義...
    零個(gè)到多個(gè)私有方法、默認(rèn)方法、類方法定義.
}
  • 修飾符可以是public或省略
  • 一個(gè)接口可以由多個(gè)直接父接口,但接口只能繼承接口,不能繼承類

接口里不能包含構(gòu)造器和初始化塊定義

接口里可以包含成員變量,方法,內(nèi)部類,都只能是public訪問(wèn)權(quán)限,如果省略也是public

  • 成員變量只能是靜態(tài)常量
  • 方法只能是抽象實(shí)例方法、類方法、默認(rèn)方法、私有方法
  • 內(nèi)部類包括內(nèi)部接口、枚舉

私有方法可以擁有方法體,可以使用static修飾

靜態(tài)常量,系統(tǒng)會(huì)自動(dòng)增加staticfinal修飾符

如果定義的不是默認(rèn)方法、類方法、私有方法,系統(tǒng)會(huì)自動(dòng)為普通方法增加abstract修飾符

  • 普通方法不能有方法體
  • 類方法、默認(rèn)方法、私有方法都必須由方法體
  • 默認(rèn)方法需要用default修飾
  • 私有方法用private修飾

接口的繼承

  • 接口支持多繼承
  • 子接口擴(kuò)展某個(gè)父接口,會(huì)獲得父接口里定義的所有抽象方法、常量

使用接口

  • 接口不能用于創(chuàng)建實(shí)例,但可以用于聲明引用類型變量,這個(gè)引用類型變量必須引用到其實(shí)現(xiàn)類的對(duì)象
  • 接口的用途
    • 定義變量,可用于強(qiáng)制類型轉(zhuǎn)換
    • 調(diào)用接口中定義的常量
    • 被其他類實(shí)現(xiàn)
  • 實(shí)現(xiàn)接口使用implements關(guān)鍵字
    • 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口

      [修飾符] class 類名 implements 接口1,接口2... {
            // 類體部分
      }
      
    • 實(shí)現(xiàn)接口會(huì)獲得接口里定義的常量(成員變量)、方法(抽象方法、默認(rèn)方法)

    • 如果類實(shí)現(xiàn)接口后沒(méi)有重寫(xiě)接口里的抽象方法,那就必須定義成抽象類

      • 如果A類實(shí)現(xiàn)了B接口和C接口,那么A對(duì)象既可以直接賦給B變量,也可以直接賦給C變量
      • 實(shí)現(xiàn)接口時(shí)必須使用public訪問(wèn)控制符,因?yàn)榻涌诶锓椒ǘ际?code>public,而子類重寫(xiě)父類時(shí)訪問(wèn)權(quán)限只能更大或相等

接口和抽象類

相同特征

  • 接口和抽象類都不能被實(shí)例化
  • 接口和抽象類都快可以包含抽象方法

接口體現(xiàn)的是一種規(guī)范,類似于整個(gè)系統(tǒng)的“總綱”,一旦接口改變,將可能導(dǎo)致系統(tǒng)中大部分類需要改寫(xiě)

差別

  • 接口里只能包含抽象方法、默認(rèn)方法、私有方法、類方法,不能為普通方法提供方法實(shí)現(xiàn);抽象類完全可以包含普通方法
  • 接口里只能定義靜態(tài)常量,不能定義普通成員變量;抽象類里則都可以定義
  • 接口里不包含構(gòu)造器;抽象類可以包含構(gòu)造器,但抽象類構(gòu)造器不是用于創(chuàng)建對(duì)象,而是讓其子類調(diào)用這些構(gòu)造器來(lái)完成屬于抽象類的初始化操作
  • 接口里不能包含初始化塊;抽象類可以
  • 一個(gè)類最多只能有一個(gè)直接父類,包括抽象類;但一個(gè)接口可以實(shí)現(xiàn)多個(gè)接口

內(nèi)部類

把一個(gè)類放在另一個(gè)類的內(nèi)部定義,定義在其他類內(nèi)部的類被稱為內(nèi)部類(嵌套類),包含內(nèi)部類的類被稱為外部類(宿主類)

作用

  • 內(nèi)部類提供了更好的封裝,可以把內(nèi)部類隱藏在外部類之內(nèi),不允許同一個(gè)包中其他類訪問(wèn)該類
  • 內(nèi)部類成員可以直接訪問(wèn)外部類的私有數(shù)據(jù),內(nèi)部類被當(dāng)成外部類成員,同一個(gè)類的成員之間可以互相訪問(wèn)
    • 但外部類不能訪問(wèn)內(nèi)部類的實(shí)現(xiàn)細(xì)節(jié)
  • 匿名內(nèi)部類適合用于創(chuàng)建那些僅需要一次使用的類
  • 內(nèi)部類最多可使用三個(gè)修飾符:private、proteced、static
    • 外部類不可以使用這三個(gè)修飾符
  • 非靜態(tài)內(nèi)部類不能擁有靜態(tài)成員

非靜態(tài)內(nèi)部類

內(nèi)部類都被作為成員內(nèi)部類定義,而不是作為局部?jī)?nèi)部類

  • 成員內(nèi)部類是一種與成員變量、方法、構(gòu)造器和初始化塊相似的類成員
  • 局部?jī)?nèi)部類和匿名內(nèi)部類則不是類成員

成員內(nèi)部類

  • 靜態(tài)內(nèi)部類
    • 使用static修飾的成員內(nèi)部類
  • 非靜態(tài)內(nèi)部類
    • 沒(méi)有使用static修飾的成員內(nèi)部類
  • 內(nèi)部類生成的class文件格式:OuterClass$InnerClass.class
  • 非靜態(tài)內(nèi)部類里可以直接訪問(wèn)外部類的private成員
  • 在非靜態(tài)內(nèi)部類對(duì)象里,保存了一個(gè)它所寄生的外部類對(duì)象的引用
    • 當(dāng)調(diào)用非靜態(tài)內(nèi)部類的實(shí)例方法時(shí),必須有一個(gè)非靜態(tài)內(nèi)部類實(shí)例,非靜態(tài)內(nèi)部類實(shí)例必須寄生在外部類實(shí)例里
  • 非靜態(tài)內(nèi)部類的方法訪問(wèn)某個(gè)變量時(shí):該方法的局部變量->內(nèi)部類成員變量->外部類成員變量
    • 如果外部類成員變量、內(nèi)部類成員變量、內(nèi)部類方法局部變量同名
      • 使用this外部類類名.this區(qū)分
    • 非靜態(tài)內(nèi)部類的成員不能在外部類直接使用
    • 需要在外部類顯示創(chuàng)建內(nèi)部類對(duì)象來(lái)調(diào)用訪問(wèn)實(shí)例成員
  • 不允許在外部類的靜態(tài)成員中直接使用非靜態(tài)內(nèi)部類
  • 不允許在非靜態(tài)內(nèi)部類定義靜態(tài)成員

靜態(tài)內(nèi)部類

使用static來(lái)修飾一個(gè)內(nèi)部類,這個(gè)內(nèi)部類就屬于外部類本身

  • 靜態(tài)內(nèi)部類可以包含靜態(tài)成員,也可以包含非靜態(tài)成員
    • 靜態(tài)內(nèi)部類不能訪問(wèn)外部類實(shí)例變量,只能訪問(wèn)外部類的類成員
    • 內(nèi)部類的實(shí)例方法也不能訪問(wèn)外部類的實(shí)例成員,只能訪問(wèn)外部類的靜態(tài)成員
      • 靜態(tài)內(nèi)部類時(shí)外部類的類相關(guān)的,靜態(tài)內(nèi)部類對(duì)象不是寄生在外部類的實(shí)訓(xùn)中,而是寄生在外部類的類本身中
  • 外部類不能直接訪問(wèn)內(nèi)部類的成員,但可以使用靜態(tài)內(nèi)部類的類名作為調(diào)用者來(lái)訪問(wèn)靜態(tài)內(nèi)部類的類成員,也可以使用靜態(tài)內(nèi)部類對(duì)象作為調(diào)用者來(lái)訪問(wèn)靜態(tài)內(nèi)部類的實(shí)例成員
  • 接口里可以定義內(nèi)部類
    • 接口里定義內(nèi)部類默認(rèn)使用public static修飾
    • 接口內(nèi)部類只能是靜態(tài)內(nèi)部類
    • 接口也可以定義內(nèi)部接口
      • 內(nèi)部接口時(shí)接口的成員,系統(tǒng)默認(rèn)添加public static修飾符
        • 意義不大

使用內(nèi)部類

  • 在外部類內(nèi)部使用內(nèi)部類
  • 在外部類以外使用非靜態(tài)內(nèi)部類
    • 若想在外部類以外的地方使用內(nèi)部類,內(nèi)部類不能使用private訪問(wèn)控制權(quán)限
      • private修飾的內(nèi)部類只能在外部類內(nèi)使用
      • 省略訪問(wèn)控制符,內(nèi)部類只能在和外部類在同一包下的其它類使用
      • 使用protected修飾的內(nèi)部類,可被與外部類同一包下的其他類和外部類的子類使用
      • 在外部類以外的地方定義內(nèi)部類(包括靜態(tài)和非靜態(tài)兩種)變量
        • OuterClass.InnerClass varName
    • 非靜態(tài)內(nèi)部類的對(duì)象必須寄生在外部類的對(duì)象里,因此創(chuàng)建非靜態(tài)內(nèi)部類對(duì)象之前,必須先創(chuàng)建其外部類對(duì)象
  • 在外部類以外的地方創(chuàng)建非靜態(tài)內(nèi)部類實(shí)例
    • OuterInstance.new InnerConstructor()
  • 在外部類以外使用靜態(tài)內(nèi)部類
    • 靜態(tài)內(nèi)部類是外部類類相關(guān)的,創(chuàng)建靜態(tài)內(nèi)部類時(shí)無(wú)須創(chuàng)建外部類對(duì)象
      • new OuterClass.InnerConstructor()
    • 創(chuàng)建靜態(tài)內(nèi)部類的子類
      • public class StaticSubClass extends StaticOut.StaticIn{}
        • 定義一個(gè)靜態(tài)內(nèi)部類時(shí),外部類像一個(gè)包
    • 不管靜態(tài)內(nèi)部類還是非靜態(tài)內(nèi)部類,聲明變量的語(yǔ)法完全一樣,區(qū)別只是在創(chuàng)建內(nèi)部類對(duì)象時(shí)

局部?jī)?nèi)部類

  • 把一個(gè)內(nèi)部類放在方法里定義
  • 局部?jī)?nèi)部類僅在該方法里有效
  • 局部?jī)?nèi)部類不能是使用訪問(wèn)控制符和static修飾符
    • 不管是局部變量還是局部?jī)?nèi)部類,它們的上一級(jí)程序單元都是方法而不是類,都不能使用static修飾
  • 局部?jī)?nèi)部類的class文件命名格式:OuterClass$NInnerClass.class
  • 局部?jī)?nèi)部類在實(shí)際開(kāi)發(fā)中很少使用

匿名局部?jī)?nèi)部類

  • 創(chuàng)建只需要一次使用的類

  • 創(chuàng)建匿名內(nèi)部類時(shí)會(huì)立即創(chuàng)建一個(gè)該類的實(shí)例,這個(gè)類定義立即消失,匿名內(nèi)部類不能重復(fù)使用

    new 實(shí)現(xiàn)接口() | 父類構(gòu)造器(實(shí)參列表) {
      // 匿名內(nèi)部類的類體部分
    }
    
  • 匿名內(nèi)部類必須繼承一個(gè)父類或?qū)崿F(xiàn)一個(gè)接口,但最多只能繼承一個(gè)父類或?qū)崿F(xiàn)一個(gè)接口

  • 規(guī)則

    • 匿名內(nèi)部類不能是抽象類
    • 匿名內(nèi)部類不能定義構(gòu)造器,但可以定義初始化塊
  • 通過(guò)繼承父類來(lái)創(chuàng)建匿名內(nèi)部類時(shí),匿名內(nèi)部類將擁有和父類相似的構(gòu)造器,相似是指擁有相同形參列表

  • 如果局部變量?jī)?nèi)匿名內(nèi)部類訪問(wèn),該局部變量相當(dāng)于自己使用了final修飾

Lambda表達(dá)式

lambda表達(dá)式入門(mén)

  • 支持將代碼塊作為方法參數(shù),允許使用更簡(jiǎn)潔的代碼來(lái)創(chuàng)建只有一個(gè)抽象方法的接口(這種接口成為函數(shù)式接口)的實(shí)例

  • 代替匿名內(nèi)部類創(chuàng)建對(duì)象,lambda表達(dá)式的代碼塊將會(huì)代替實(shí)現(xiàn)抽象方法的方法體

  • 相當(dāng)于一個(gè)匿名方法

    (形參列表) -> {
      // 代碼塊
    }
    
  • 組成

    • 形參列表
      • 允許省略形參類型;如果形參列表中只有一個(gè)參數(shù),形參列表的圓括號(hào)也可以省略
    • 箭頭->
    • 代碼塊
      • 如果代碼塊只有一條語(yǔ)句,允許省略代碼塊的花括號(hào);若只有一條return語(yǔ)句,return關(guān)鍵字也可以省略;
  • lambda表達(dá)式會(huì)被當(dāng)成一個(gè)“任意類型”的對(duì)象

lambda表達(dá)式與函數(shù)式接口

  • lambda表達(dá)的類型,也被稱為目標(biāo)類型(target type)
  • lambda表達(dá)式的目標(biāo)類型必須是函數(shù)式接口(functional interface)
    • 函數(shù)式接口代表只包含一個(gè)抽象方法的接口
    • 函數(shù)式接口可以包含多個(gè)默認(rèn)方法、類方法,但只能聲明一個(gè)抽象方法
  • lambda表達(dá)式的結(jié)果就是被當(dāng)成對(duì)象,因此程序中完全可以使用lambda表達(dá)式進(jìn)行賦值
  • lambda表達(dá)式的限制
    • lambda表達(dá)式的目標(biāo)類型必須是明確的函數(shù)式接口
    • lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建對(duì)象
  • 常見(jiàn)方式
    • 將lambda表達(dá)式賦值給函數(shù)式接口類型的變量
    • 將lambda表達(dá)式作為函數(shù)式接口類型的參數(shù)傳給某個(gè)方法
    • 使用函數(shù)式接口對(duì)lambda表達(dá)式進(jìn)行強(qiáng)制類型轉(zhuǎn)換

方法引用與構(gòu)造器引用

  • 需要使用兩個(gè)英文冒號(hào)
  • 引用類方法
    • 類名::類方法
    • 函數(shù)式接口中被實(shí)現(xiàn)方法的全部參數(shù)傳給該類方法作為參數(shù)
    • (a, b, ...) -> 類名.類方法(a, b, ...)
  • 引用特定對(duì)象的實(shí)例方法
    • 特定對(duì)象::實(shí)例方法
    • 函數(shù)式接口中被實(shí)現(xiàn)方法的全部參數(shù)傳給該方法作為參數(shù)
    • (a, b, ...) -> 特定對(duì)象.實(shí)例方法(a, b, ...)
  • 引用某類對(duì)象的實(shí)例方法
    • 類名::實(shí)例方法
    • 函數(shù)式接口中被實(shí)現(xiàn)方法的第一個(gè)參數(shù)作為調(diào)用者,后面的參數(shù)全部傳給該方法作為參數(shù)
    • (a, b, ...) -> a.實(shí)例方法(b, ...)
  • 引用構(gòu)造器
    • 類名::new
    • 函數(shù)式接口中被實(shí)現(xiàn)方法的全部參數(shù)傳給該構(gòu)造器作為參數(shù)
    • (a, b, ...) -> new 類名(a, b, ...)
  • Java.util.function包下預(yù)定義了大量函數(shù)式接口
    • XxxFunction :這類接口中通常包含一個(gè)apply()抽象方法, 該方法對(duì)參數(shù)進(jìn)行處理、轉(zhuǎn)換(apply()方法的處理邏輯由lambda表達(dá)式來(lái)實(shí)現(xiàn)),然后返回一個(gè)新的值。該函數(shù)式接口通常用于對(duì)指定數(shù)據(jù)進(jìn)行轉(zhuǎn)換處理
    • XxxConsumer :這類接口通常包含一個(gè)accept()抽象方法,該方法與XxxFunction接口中的apply()方法基本相似,也負(fù)責(zé)對(duì)參數(shù)進(jìn)行處理,只是該方法不會(huì)返回處理結(jié)果
    • XxxPredicate:這類接口中通常包含一個(gè)test()抽象方法,該方法通常用來(lái)對(duì)參數(shù)進(jìn)行某種判斷(test()方法的判斷邏輯由lambda表達(dá)式來(lái)實(shí)現(xiàn)(,然后返回一個(gè)Boolean值。該接口通常用于判斷參數(shù)是否滿足特定條件,經(jīng)常用于進(jìn)行篩濾數(shù)據(jù)
    • XxxSuppliter :這類接口通常包含一個(gè)getAsXxx()抽象方法,該方法不需要傳入?yún)?shù),該方法會(huì)按某種邏輯算法(getAsXxx()方法的邏輯算法由lambda表達(dá)式來(lái)實(shí)現(xiàn))返回一個(gè)數(shù)據(jù)。

lambda表達(dá)式與匿名內(nèi)部類的聯(lián)系和區(qū)別

  • lambda表達(dá)式時(shí)匿名內(nèi)部類的一種簡(jiǎn)化,可以部分取代匿名內(nèi)部類的作用
  • 相同點(diǎn)
    • lambda表達(dá)式和匿名內(nèi)部類一樣,都可以直接訪問(wèn)effectively final的局部變量,以及外部類的成員變量(包括實(shí)例變量和類變量)
    • lambda表達(dá)式創(chuàng)建的對(duì)象與匿名內(nèi)部類生成的對(duì)象一樣,都可以直接調(diào)用從接口紅繼承的默認(rèn)方法
  • 區(qū)別
    • 匿名內(nèi)部類可以為任意接口創(chuàng)建實(shí)例,不管接口包含多少個(gè)抽象方法,只要匿名內(nèi)部類實(shí)現(xiàn)所有的抽象方法即可;但lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建實(shí)例
    • 匿名內(nèi)部類可以為抽象類甚至普通類創(chuàng)建實(shí)例;但lambda表達(dá)式只能為函數(shù)式接口創(chuàng)建實(shí)例
    • 匿名內(nèi)部類實(shí)現(xiàn)的抽象方法的方法體允許調(diào)用接口中定義的默認(rèn)方法;但lambda表達(dá)式的代碼塊不允許調(diào)用接口中定義的默認(rèn)方法

使用lambda表達(dá)式調(diào)用Arrays的類方法

  • Arrays類的有些方法需要Comparator、XxxOperatorXxxFunction等接口的實(shí)例,這些接口都是函數(shù)式接口

枚舉類

一個(gè)類的對(duì)象是有限而且固定的,即實(shí)例有限而且固定的類

手動(dòng)實(shí)現(xiàn)枚舉類

  • 在早期代碼中,可能會(huì)使用簡(jiǎn)單的靜態(tài)常量來(lái)表示枚舉
  • 定義類的方式實(shí)現(xiàn)
    • 通過(guò)private將構(gòu)造器隱藏起來(lái)
    • 把類所有可能實(shí)例都使用public static final修飾的類變量來(lái)保存
    • 如果有必要,提供一些靜態(tài)方法,允許其他程序根據(jù)特定參數(shù)來(lái)獲取與之匹配的實(shí)例
  • 通過(guò)定義類實(shí)現(xiàn)枚舉的代碼量比較大,實(shí)現(xiàn)起來(lái)也比較麻煩

枚舉類入門(mén)

  • 關(guān)鍵字enum(與classinterface關(guān)鍵字地位相同),定義枚舉類
  • 一個(gè)源文件中最多只能定義一個(gè)public訪問(wèn)權(quán)限的枚舉類,且該源文件也必須和枚舉類類名相同
  • 與普通類的區(qū)別
    • 枚舉類可以實(shí)現(xiàn)一個(gè)或多個(gè)接口,枚舉類默認(rèn)繼承了java.lang.Enum類,而不是默認(rèn)繼承Object類,因此枚舉類不能顯式繼承其他父類
      • java.lang.Enum類實(shí)現(xiàn)了java.lang.Serializablejava.lang.Comparable兩個(gè)接口
    • 使用enum定義、非抽象的枚舉類默認(rèn)會(huì)使用final修飾,因此枚舉類不能派生子類
    • 枚舉類的構(gòu)造器只能使用private訪問(wèn)控制符
    • 枚舉類的所有實(shí)例必須在枚舉類的第一行顯式列出,否則這個(gè)枚舉類永遠(yuǎn)都不能產(chǎn)生實(shí)例
      • 列出這些實(shí)例時(shí),系統(tǒng)會(huì)自動(dòng)添加public static final修飾,無(wú)需顯式添加
  • 枚舉類默認(rèn)提供了一個(gè)values()方法,該方法可以很方便地遍歷所有的枚舉值
  • 可通過(guò)EnumClass.variable形式來(lái)訪問(wèn)枚舉實(shí)例
  • switch表達(dá)式還可使用枚舉類對(duì)象作為表達(dá)式,case表達(dá)式中的值直接使用枚舉值的名字
  • java.lang.Enum類提供的方法
    • int compareTo(E o)
      • 該方法用于指定枚舉對(duì)象比較順序,同一個(gè)枚舉實(shí)例只能與相同類型的實(shí)例進(jìn)行比較。如果該枚舉對(duì)象位于指定枚舉對(duì)象之后,則返回正整數(shù);如果該枚舉對(duì)象位于指定枚舉對(duì)象之前,則返回負(fù)整數(shù),否則返回零
    • String name()
      • 返回此枚舉實(shí)例的名稱,這個(gè)名稱就是定義枚舉類時(shí)列出的所有枚舉值之一
        • 應(yīng)優(yōu)先考慮使用toString()方法
    • int ordinal()
      • 返回枚舉值在枚舉類中的索引值(在枚舉聲明中的位置,第一個(gè)枚舉值的索引值為零)
    • String toString()
      • 返回枚舉常量的名稱,與name方法相似,但toString()方法更常用
    • public static <T extends Enum<T>> T valueOf(Class<T>enumType, String name)
      • 靜態(tài)方法,返回指定枚舉類中指定名稱的枚舉值。名稱必須與在枚舉類中聲明枚舉值時(shí)所用的標(biāo)識(shí)符完全匹配

枚舉類的成員變量、方法和構(gòu)造器

  • 枚舉類產(chǎn)生對(duì)象的方式不同于普通類,枚舉類的實(shí)例只能是枚舉值,而不是隨意地通過(guò)new來(lái)創(chuàng)建枚舉類對(duì)象
  • 建議將枚舉類的成員變量都使用private final修飾
  • 構(gòu)造器
    • 枚舉類實(shí)例名 (構(gòu)造器形參列表)
      • 必須定義和定義枚舉實(shí)例的形參列表相同的構(gòu)造器

實(shí)現(xiàn)接口的枚舉類

  • 枚舉類也可以實(shí)現(xiàn)一個(gè)或多個(gè)接口

  • 若需要每個(gè)枚舉值在調(diào)用該方法時(shí)呈現(xiàn)出不同的行為方式,則可以讓每個(gè)枚舉值分別來(lái)實(shí)現(xiàn)該方法

    枚舉實(shí)例名 (構(gòu)造器形參列表) {
        // 實(shí)現(xiàn)接口的抽象方法
    }
    
  • 匿名內(nèi)部類

  • 非抽象的枚舉類默認(rèn)使用final修飾;對(duì)于一個(gè)抽象的枚舉類,只要它包含了抽象方法,系統(tǒng)會(huì)默認(rèn)使用abstract修飾

包含抽象方法的枚舉類

  • 不能使用abstract關(guān)鍵字將枚舉類定義成抽象類(系統(tǒng)自動(dòng)會(huì)添加abstract關(guān)鍵字),但因?yàn)槊杜e類需要顯式創(chuàng)建枚舉值,而不是作為父類,所以定義每個(gè)枚舉值時(shí)必須為抽象方法提供實(shí)現(xiàn),否則將出現(xiàn)編譯錯(cuò)誤

對(duì)象與垃圾回收

當(dāng)對(duì)象、數(shù)組等引用類型實(shí)體不再被任何引用變量引用時(shí),等待垃圾回收機(jī)制進(jìn)行回收

特征

  • 垃圾回收機(jī)制只負(fù)責(zé)回收堆內(nèi)存的對(duì)象,不會(huì)回收任何物理資源(例如數(shù)據(jù)庫(kù)連接、網(wǎng)絡(luò)IO等資源)
  • 程序無(wú)法精確控制垃圾回收的運(yùn)行,垃圾回收會(huì)在合適的時(shí)候進(jìn)行;當(dāng)對(duì)象永久性地失去引用后,系統(tǒng)就會(huì)在合適的時(shí)候回收它所占的內(nèi)存
  • 在垃圾回收機(jī)制回收任何對(duì)象之前,總會(huì)調(diào)用它的finalize()方法,該方法可能使對(duì)象重新復(fù)活(讓一個(gè)引用變量重新引用該對(duì)象),從而導(dǎo)致垃圾回收機(jī)制取消回收

對(duì)象在內(nèi)存中的狀態(tài)

  • 當(dāng)一個(gè)對(duì)象在堆內(nèi)存中運(yùn)行時(shí),根據(jù)它被引用變量所引用的狀態(tài),可分為三種狀態(tài)
    • 可達(dá)狀態(tài)
      • 當(dāng)一個(gè)對(duì)象被創(chuàng)建后,若有一個(gè)以上的引用變量引用它,則這個(gè)對(duì)象在程序中處于可達(dá)狀態(tài),程序可通過(guò)引用變量來(lái)調(diào)用該對(duì)象的實(shí)例變量和方法
    • 可恢復(fù)狀態(tài)
      • 如果程序中某個(gè)對(duì)象不再有任何引用變量引用它,它就進(jìn)入了可恢復(fù)狀態(tài)
      • 在這種狀態(tài)下,系統(tǒng)的垃圾回收機(jī)制準(zhǔn)備回收該對(duì)象所占用的內(nèi)存,在回收該對(duì)象之前,系統(tǒng)會(huì)調(diào)用所有可恢復(fù)狀態(tài)對(duì)象的finalize()方法進(jìn)行資源清理。
      • 如果系統(tǒng)在調(diào)用finalize()方法時(shí)重新讓一個(gè)以引用變量引用該對(duì)象,則這個(gè)對(duì)象會(huì)再次變?yōu)榭蛇_(dá)狀態(tài);否則該對(duì)象將進(jìn)入不可達(dá)狀態(tài)
    • 不可達(dá)狀態(tài)
      • 當(dāng)對(duì)象與所有引用變量的關(guān)系都被切斷,且系統(tǒng)已經(jīng)調(diào)用所有對(duì)象的finalize()方法后依然沒(méi)有使對(duì)象變成可達(dá)狀態(tài),那么這個(gè)對(duì)象將永久性地失去引用,最后變成不可達(dá)狀態(tài)
      • 只有當(dāng)一個(gè)對(duì)象處于不可達(dá)狀態(tài)時(shí),系統(tǒng)才會(huì)真正回收該對(duì)象所占有的資源
  • 一個(gè)對(duì)象可以被一個(gè)方法的局部變量引用,也可以被其他類的類變量引用,或被其他對(duì)象的實(shí)例變量引用。
  • 當(dāng)某個(gè)對(duì)象被其他類的類變量引用時(shí),只有該類被銷毀后,該對(duì)象才會(huì)進(jìn)入可恢復(fù)狀態(tài);當(dāng)某個(gè)對(duì)象被其他對(duì)象的實(shí)例變量引用時(shí),只有當(dāng)該對(duì)象被銷毀后,該對(duì)象才會(huì)進(jìn)入可恢復(fù)狀態(tài)

強(qiáng)制垃圾回收

  • 程序只能控制一個(gè)對(duì)象何時(shí)不再被任何引用變量引用,絕不能控制它何時(shí)被回收
  • 程序無(wú)法精確控制Java垃圾回收的時(shí)機(jī),但依然可以強(qiáng)制系統(tǒng)進(jìn)行垃圾回收
    • 這種強(qiáng)制只是通知系統(tǒng)進(jìn)行垃圾回收,但系統(tǒng)是否進(jìn)行垃圾回收依然不確定
  • 方式
    • 調(diào)用System類gc()靜態(tài)方法:System.gc()
    • 調(diào)用Runtime對(duì)象gc()實(shí)例方法:Runtime.getRuntime().gc()
  • java -verbose:gc 類名
    • 可以看到每次垃圾回收后的提示信息
  • 這種強(qiáng)制只是建議系統(tǒng)立即進(jìn)行垃圾回收,垃圾回收機(jī)制會(huì)在收到通知后,盡快進(jìn)行垃圾回收

finalize方法

  • 在垃圾回收機(jī)制回收某個(gè)對(duì)象所占用的內(nèi)存之前,通常要求程序調(diào)用適當(dāng)?shù)姆椒▉?lái)清理資源,在沒(méi)有明確指定清理資源的情況下,Java提供了默認(rèn)機(jī)制來(lái)清理該對(duì)象的資源,這個(gè)機(jī)制就是finalize()方法
  • 方法原型
    • protected void finalize() throws Throwable
    • throws Throwable表示可以拋出任何類型的異常
  • 當(dāng)finalize()方法返回后,對(duì)象消失,垃圾回收機(jī)制開(kāi)始執(zhí)行
  • 任何Java類都可以重寫(xiě)Object類的finalize()方法,在該方法中清理該對(duì)象占用的資源
  • 如果程序終止之前始終沒(méi)有進(jìn)行垃圾回收,則不會(huì)調(diào)用失去引用對(duì)象的finalize()方法來(lái)清理資源
  • 垃圾回收機(jī)制何時(shí)調(diào)用對(duì)象的finalize()方法是完全透明的,只有當(dāng)程序認(rèn)為需要更多的額外內(nèi)存時(shí),垃圾回收機(jī)制才會(huì)進(jìn)行垃圾回收
  • 特點(diǎn)
    • 永遠(yuǎn)不要主動(dòng)調(diào)用某個(gè)對(duì)象的finalize()方法,該方法應(yīng)交給垃圾回收機(jī)制調(diào)用
    • finalize()方法何時(shí)被調(diào)用,是否被調(diào)用具有不確定性,不要把finalize()方法當(dāng)成一定會(huì)被執(zhí)行的方法
    • 當(dāng)JVM執(zhí)行可恢復(fù)對(duì)象finalize()方法時(shí),可能使該對(duì)象或系統(tǒng)中其他對(duì)象重新編程可達(dá)狀態(tài)
    • 當(dāng)JVM執(zhí)行finalize()方法時(shí)出現(xiàn)異常時(shí),垃圾回收機(jī)制不會(huì)報(bào)告異常,程序繼續(xù)執(zhí)行
  • 強(qiáng)制垃圾回收機(jī)制調(diào)用可恢復(fù)對(duì)象的finalize()方法
    • Runtime.getRuntime().runFianlization();
    • System.runFinaliaztion();

對(duì)象的軟、弱和虛引用

  • 對(duì)于大部分而言,程序里會(huì)有一個(gè)引用變量引用該對(duì)象,這是最常見(jiàn)的引用方式

java.lang.ref包下提供3個(gè)類

  • SoftReference

    • 軟引用
  • PhantomReference

    • 虛引用
  • WeakReference

    • 弱引用
  • 強(qiáng)引用(StrongReference)

    • Java程序中最常見(jiàn)的引用方式
    • 程序創(chuàng)建一個(gè)對(duì)象,并把這個(gè)對(duì)象賦給一個(gè)引用變量,程序通過(guò)該引用變量來(lái)操作實(shí)際的對(duì)象
  • 軟引用(SoftReference)

    • 需要通過(guò)SoftReference類來(lái)實(shí)現(xiàn),當(dāng)一個(gè)對(duì)象只有軟引用時(shí),它有可能被垃圾回收機(jī)制回收
    • 對(duì)于只有軟引用的對(duì)象而言,當(dāng)系統(tǒng)內(nèi)存空間足夠時(shí),它不會(huì)被系統(tǒng)回收,程序也可使用該對(duì)象;當(dāng)系統(tǒng)內(nèi)存空間不足時(shí),系統(tǒng)可能會(huì)回收它
    • 軟引用通常用于對(duì)內(nèi)存敏感的程序中
  • 弱引用(WeakReference)

    • 弱引用通過(guò)WeakReference類實(shí)現(xiàn),弱引用和軟引用很像,但弱引用的引用級(jí)別更低
    • 對(duì)于只有弱引用的對(duì)象而言,當(dāng)系統(tǒng)垃圾回收機(jī)制運(yùn)行時(shí),不管系統(tǒng)內(nèi)存是否足夠,總會(huì)回收該對(duì)象所占用的內(nèi)存
    • 必須等到系統(tǒng)垃圾回收機(jī)制運(yùn)行時(shí)才會(huì)被回收
  • 虛引用(PhantomReference)

    • 虛引用通過(guò)PhantomReference類實(shí)現(xiàn),虛引用完全類似于沒(méi)有引用
    • 虛引用對(duì)對(duì)象本身沒(méi)有太大影響,對(duì)象甚至感覺(jué)不到虛引用的存在
    • 如果一個(gè)對(duì)象只有一個(gè)虛引用時(shí),那么它和沒(méi)有引用的效果大致相同
    • 虛引用主要用于跟蹤對(duì)象被垃圾回收的狀態(tài),虛引用不能單獨(dú)使用,虛引用必須和引用隊(duì)列(ReferenceQueue)聯(lián)合使用
  • 以上三個(gè)引用類型都包含了一個(gè)get()方法,用于獲取被它們所引用的對(duì)象

  • 隊(duì)列引用

    • 引用隊(duì)列由java.lang.ref.ReferenceQueue類表示,它用于保存被回收后對(duì)象的引用
    • 當(dāng)聯(lián)合使用軟引用、弱引用和引用隊(duì)列時(shí),系統(tǒng)在回收被引用的對(duì)象之后,將把被回收對(duì)象對(duì)應(yīng)的引用添加到關(guān)聯(lián)的引用隊(duì)列中
    • 與軟引用和弱引用不同的是,虛引用在對(duì)象被釋放之前,將把它對(duì)應(yīng)的虛引用添加到它關(guān)聯(lián)的引用隊(duì)列中,這使得可以在對(duì)象被回收之前采取行動(dòng)
  • 軟引用和弱引用可以單獨(dú)使用,但虛引用不能單獨(dú)使用,單獨(dú)使用虛引用沒(méi)有太大的意義

  • 虛引用的主要作用就是跟蹤對(duì)象被垃圾回收的狀態(tài),程序可以通過(guò)檢查與虛引用關(guān)聯(lián)的引用隊(duì)列中是否已經(jīng)包含了該虛引用,從而鏈接虛引用所引用的對(duì)象是否即將被回收

  • 系統(tǒng)無(wú)法通過(guò)虛引用來(lái)獲得被引用的對(duì)象;當(dāng)程序強(qiáng)制垃圾回收后,只有虛引用引用的對(duì)象被垃圾回收,當(dāng)被引用的對(duì)象被回收后,對(duì)應(yīng)的虛引用將被添加到關(guān)聯(lián)的引用隊(duì)列

strictfp關(guān)鍵字

  • 含義:FP-strict
    • 精確浮點(diǎn)
  • 使用strictfp關(guān)鍵字來(lái)修飾類、接口或方法時(shí),在修飾的范圍內(nèi)Java的編譯器和運(yùn)行環(huán)境會(huì)完全依照浮點(diǎn)規(guī)范IEEE-754來(lái)執(zhí)行

native關(guān)鍵字

  • 主要用于修飾一個(gè)方法,使用native修飾的方法類似于一個(gè)抽象方法
  • 與抽象方法不同的是,native方法通常采用C語(yǔ)言實(shí)現(xiàn)
  • 如果某個(gè)方法需要利用平臺(tái)相關(guān)特性,或者訪問(wèn)系統(tǒng)硬件等,則可以使用native修飾該方法,再把該方法交給C語(yǔ)言去實(shí)現(xiàn)
  • 一旦Java程序中包含了native方法,這個(gè)程序?qū)⑹タ缙脚_(tái)的功能

JAR包

JAR文件的全稱是Java Archive File,意思是Java檔案文件。通常JAR文件是一種壓縮文件;JAR文件ZIP文件的區(qū)別是在JAR文件中默認(rèn)包含了一個(gè)名為META-INF/MANIFEST.MF的清單文件,這個(gè)清單文件是生成JAR文件時(shí)由系統(tǒng)自動(dòng)創(chuàng)建的。
將開(kāi)發(fā)的應(yīng)用程序提供給別人使用,通常將這些類文件打包成一個(gè)JAR文件;別人在系統(tǒng)的CLASSPATH環(huán)境變量中添加這個(gè)JAR文件,則Java虛擬機(jī)就可以自動(dòng)在內(nèi)存中解壓這個(gè)JAR包,把JAR文件當(dāng)成一個(gè)路徑,在這個(gè)路徑中查找所需要的類或包層次對(duì)應(yīng)的路徑結(jié)構(gòu)。

使用JAR文件的好處:

  • 安全。能夠?qū)AR文件進(jìn)行數(shù)字簽名,只讓能夠識(shí)別數(shù)字簽名的用戶使用里面的東西。
  • 加快下載速度。在網(wǎng)上使用Applet時(shí),如果存在多個(gè)文件而不打包,為了能夠把每個(gè)文件都下載到客戶端,需要為每個(gè)文件單獨(dú)建立一個(gè)HTTP連接。
  • 壓縮。使文件變小,JAR的壓縮機(jī)制和ZIP完全相同
  • 包封裝。能夠讓JAR包里的文件依賴于同一版本的類文件。
  • 可移植性。JAR包作為嵌在Java平臺(tái)內(nèi)部的標(biāo)準(zhǔn),能夠在各種平臺(tái)上直接使用。

JAR命令

JAR使隨JDK自動(dòng)安裝的,在JDK安裝目錄下的bin目錄中,Windows下文件名未jar.exe,Linux下文件名為jar

  1. 創(chuàng)建JAR文件:jar cf jarName.jar -C dist\.
    該命令沒(méi)有顯示壓縮過(guò)程,執(zhí)行結(jié)果使將當(dāng)前路徑下的dist路徑下的全部?jī)?nèi)容生成一個(gè)jarName.jar文件。
  2. 創(chuàng)建JAR文件,并顯示壓縮過(guò)程:jar cvf jarName.jar -C dist\.
    該命令的結(jié)果與第一個(gè)命令相同,但是由于v參數(shù)的作用,顯示出了打包過(guò)程。
  3. 不使用清單文件:jar cvfM jarName.jar -C dist\.
    該命令的結(jié)果與第二個(gè)命令相似,其中M選項(xiàng)表明不生成清單文件。因此生成的JAR包中沒(méi)有META-INF/MANIFEST.MF文件。
  4. 自定義清單文件內(nèi)容:jar cvfm jarName.jar MANIFEST.MF -C dist\.
    運(yùn)行結(jié)果與第二個(gè)命令相似,其中m選項(xiàng)指定讀取用于清單文件信息。因此在生成的JAR包中青島文件META-INF/MANIFEST.MF的內(nèi)容有所不同,它會(huì)在原有清單文件基礎(chǔ)上增加MANIFEST.MF文件的內(nèi)容。
    當(dāng)開(kāi)發(fā)者向MANIFEST.MF清單文件中增加自己的內(nèi)容時(shí),清單文件的內(nèi)容由如下格式的多個(gè)key-value對(duì)組成。
    key:<空格>value
    清單文件的內(nèi)容格式要求如下:
    • 每行只能定義一個(gè)key-value對(duì),每行的key-value對(duì)之前不能有空格
    • 每組key-value對(duì)之間以;(英文冒號(hào)后緊跟一個(gè)英文空格)分隔
    • 文件開(kāi)頭不能有空行
    • 文件必須以一個(gè)空行結(jié)束
      可以將上面文件保存在任意位置,以任意文件名存放。
  5. 查看JAR包內(nèi)容:jar tf jarName.jar
    當(dāng)JAR包中的文件路徑和文件非常多時(shí),直接執(zhí)行該命令將無(wú)法查看到包的全部?jī)?nèi)容,此時(shí)可利用重定向?qū)@示結(jié)果保存到文件中。
    jar tf jarName.jar > a.txt
    執(zhí)行上面命令看不到任何輸出,但命令執(zhí)行結(jié)束后,將在當(dāng)前路徑下生成一個(gè)a.txt文件,該文件保存了包里的文件的詳細(xì)信息。
  6. 查看JAR包詳細(xì)內(nèi)容:jar tvf jarName.jar
    該命令與第五個(gè)命令基本相似,但它更詳細(xì)。
  7. 解壓縮:jar xf jarName.jar
    將jar文件解壓到當(dāng)前目錄下,不顯示任何信息。
  8. 帶提示信息解壓縮:jar xvf jarName.jar
    解壓縮效果與第七個(gè)命令相似,但系統(tǒng)會(huì)顯示解壓過(guò)程的詳細(xì)信息。
  9. 更新JAR文件:jar uf jarName.jar Hello.class
    更新JAR文件中的Hello.class文件;如果JAR包中已有Hello.class文件,則使用新的文件替換原來(lái)的文件;如果包中沒(méi)有Hello.class文件,則把文件添加到JAR文件中。
  10. 更新時(shí)顯示詳細(xì)信息:jar uvf jarName.jar Hello.class
    這個(gè)命令與第九個(gè)命令相似,也用于更新JAR包的文件,但它會(huì)顯示詳細(xì)信息。
  11. 創(chuàng)建多版本的JAR包:jar cvf jarName.jar -C dist1\. --release 9 -C dist\.
    多版本JAR包時(shí)JDK9新增的功能,它允許同一個(gè)JAR包中包含針對(duì)多個(gè)Java版本的class文件。JDK9為JAR命令增加了一個(gè)--release選項(xiàng),用于創(chuàng)建多版本JAR包,該選項(xiàng)的參數(shù)值必須大于或等于9。
    在使用多版本JAR包之前,可以使用javac--release選項(xiàng)針對(duì)指定Java進(jìn)行編譯。比如命令:javac --release 7 Test.java,這個(gè)命令代表使用Java7的語(yǔ)法來(lái)編譯Test.java文件。

創(chuàng)建可執(zhí)行的JAR包

當(dāng)一個(gè)應(yīng)用程序開(kāi)發(fā)成功后,大致有如下三種發(fā)布方式

  • 使用平臺(tái)相關(guān)的編譯器將整個(gè)應(yīng)用編譯成平臺(tái)相關(guān)的可執(zhí)行性文件

  • 為應(yīng)用編輯一個(gè)批處理文件,以Windows系統(tǒng)為例,批處理文件只需要定義如下命令:java package.MainClass,當(dāng)用戶運(yùn)行這個(gè)批處理文件時(shí),系統(tǒng)將運(yùn)行程序的主類。如果不想保留運(yùn)行Java程序的命令行窗口,也可以在批處理文件中定義如下命令:start javaw package.MainClass

  • 將一個(gè)應(yīng)用程序制作成可執(zhí)行的JAR包,通過(guò)JAR包來(lái)發(fā)布應(yīng)用程序。
    在Windows下安裝JRE時(shí),安裝文件會(huì)將*.jar文件映射成由javaw.exe打開(kāi)。
    JAR命令有一個(gè)-e選項(xiàng),該選項(xiàng)指定JAR包中作為程序在入口的主類的類名,例如下命令:jar cvfe jarName.jar test.Test test,這個(gè)命令把test目錄下所有文件都?jí)嚎s到JAR包中,并指定使用test.Test類作為程序的入口。
    運(yùn)行上面的JAR包有兩種方式:

    • 使用java命令,語(yǔ)法是:java -jar jarName.jar
    • 使用javaw命令,語(yǔ)法是:javaw jarName.jar

    當(dāng)創(chuàng)建JAR包時(shí),所有類都必須放在與包結(jié)構(gòu)對(duì)應(yīng)的目錄結(jié)構(gòu)中,必須在JAR包下包含*.class文件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容