天天看點

瘋狂Java講義-Java基礎類庫Java基礎類庫

Java基礎類庫

本章思維導圖

瘋狂Java講義-Java基礎類庫Java基礎類庫

使用者互動

使用Scanner擷取鍵盤輸入

  • Scanner主要提供了兩個方法來掃描輸入
    • hasNextXxx();

      • 是否還有下一個輸入項,其中

        Xxx

        可以是

        int

        long

        等代表基本資料類型的字元串。
    • nextXxx();

      • 擷取下一個輸入項。

        Xxx

        的含義與前一個方法中的

        Xxx

        相同。

預設情況下,Scanner使用空白(

空格

Tab

回車

)作為多個輸入項之間的分隔符。

如果希望改變Scanner的分隔符,使用方法

useDelimiter(String pattern);

Scanner的讀取操作可能被阻塞,Scanner的

hasNext();

next();

方法都有可能阻塞,

hasNext();

方法是否阻塞與和其相關的

next();

方法是否阻塞無關

為Scanenr設定分隔符使用

useDelimiter(String pattern);

方法即可,該方法的參數應該是一個正規表達式

  • Scanner提供了兩個簡單的方法來逐行讀取
    • boolean hasNextLine();

      • 傳回輸入源中是否還有下一行
    • String nextLine();

      • 傳回輸入源中下一行的字元串
  • Scanner不僅能讀取使用者的鍵盤輸入,還可以讀取檔案輸入。
    • 隻要在建立Scanner對象時傳入一個

      File

      對象作為參數,就可以讓Scanner讀取該檔案的内容。

系統相關

System類

System類代表目前Java程式的運作平台,程式不能建立System類的對象,System類提供了一些類變量和類方法,允許直接通過System類來調用這些類變量和類方法。

  • System類提供了代表标準輸入、标準輸出和錯誤輸出的類變量,并提供了一些靜态方法用于通路環境變量、系統屬性的方法,還提供了加載檔案和動态連結庫的方法。
    • 加載檔案和動态連結庫主要對

      native

      方法有用,對于一些特殊的功能(如通路作業系統底層硬體裝置等)Java程式無法實作,必須借助C語言來完成,此時需要C語言為Java方法提供實作。
        1. Java程式中聲明native修飾的方法,類似于

          abstract

          方法,隻有方法簽名,沒有實作。編譯該Java程式,生産一個

          class

          檔案。
        1. javah

          編譯第1步生産的

          class

          檔案,将生産一個

          .h

          檔案。
        1. 寫一個

          cpp

          檔案實作native方法,這一步需要包含第2步産生的

          .h

          檔案(這個

          .h

          檔案中包含了JDK帶的

          jni.h

          檔案)。
        1. 将第3步的

          .cpp

          檔案編譯成動态連結庫檔案。
        1. 在Java中用System類活動

          loadLibrary..()

          方法或Runtime類的

          loadLibrary()

          方法加載第4步産生的動态連結庫檔案,Java程式中就可以調用這個native方法了。

調用System類的

getenv()

getProperties()

getProperty()

等方法來通路程式所在平台的環境變量和系統屬性。

System類提供了通知系統進行垃圾回收的

gc()

方法,以及通知系統進行資源清理的

runFinalization()

方法。

  • System類還有兩個擷取系統目前時間的方法
    • currentTimeMillis();

    • nanoTime();

    • 它們都傳回一個

      long

      型整數;實際上它們都傳回目前時間與UTC1970年1月1日午夜的時間差,前者以毫秒作為機關,後者以納秒作為機關。
    • 這兩個方法傳回的時間粒度取決于底層的作業系統,可能所在的作業系統根本不支援以毫秒、納秒作為計時機關。
    • 許多作業系統以幾十毫秒為機關測量時間,

      currentTimeMillis()

      方法不可能傳回精确的毫秒數;而

      nanoTime()

      方法很少用,因為大部分作業系統都不支援使用納秒作為計時機關。

System類的

in

out

err

分别代表系統的标準輸入(通常是鍵盤輸入)、标準輸出(通常是顯示器)和錯誤輸出流,并提供了

setIn()

setOut()

setErr()

方法來改變系統的标準輸入、标準輸出和标準錯誤輸出流。

System類還提供了一個

identityHashCode(Object x);

方法,該方法傳回指定對象的精确

hashCode

值,根據該對象的位址計算得到的

hashCode

值。

Runtime類與java9的ProcessHandle

Runtime類代表Java程式運作時的環境,每個Java程式都有一個與之對應的Runtime執行個體,應用程式通過該對象與其運作時環境相連。

應用程式不能建立自己的Runtime執行個體,但可以通過

getRuntime()

方法擷取與之關聯的Runtime對象。

Runtime類也提供了

gc()

方法或

runFinalization()

方法來通知系統進行垃圾回收、清理系統資源,并提供了

load(String filename)

loadLibrary(String libname)

方法來加載檔案和動态連結庫。

  • Runtime類部分方法
    • availableProcessors();

    • freeMemory();

    • totalMemory();

    • maxMemory();

    • exec();

通過exec啟動平台上的指令之後,它就變成了一個程序,Java使用Process來代表程序。

Java9新增了一個

ProcessorHandle

接口,通過該接口可擷取程序的ID、父程序和後代程序;通過該接口的

onExit()

方法可在程序結束時完成某些行為。

ProcessorHandle

還提供了一個

ProcessorHandle.Info

類,用于擷取程序的指令、參數、啟動時間、累計運作時間、使用者等資訊。

常用類

Object類

  • 常用方法
    • boolean equals(Object obj);

      • 判斷指定對象與該對象是否相等。
    • protected void finalize();

      • 當系統中沒有引用變量引用到該對象時,垃圾回收器調用此方法來清理該對象的資源。
    • Class<?> getClass();

      • 傳回該對象的運作時類。
    • int hashCode();

      • 傳回該對象的hashCode值。
    • String toString();

      • 傳回該對象的字元串表示。

Java還提供了一個

protected

修飾的

clone()

方法,該方法用于幫助其他對象實作自我克隆,就是得到一個目前對象的副本,而且二者之間完全隔離。

  • 自定義類實作克隆的步驟
      1. 自定義類實作

        Cloneable

        接口。這是一個标記行性的接口,實作接口的對象可以實作自我克隆,接口裡沒有定義任何方法。
      1. 自定義類實作自己的

        clone()

        方法。
      1. 實作

        clone()

        方法時通過

        super.clone();

        調用

        Object

        實作的

        clone()

        方法來得到該對象的副本,并傳回副本。

Object類提供的Clone機制隻對對象裡各執行個體變量進行簡單複制,如果執行個體變量的類型是引用類型,Object的Clone機制也隻是簡單地複制這個引用變量,這樣原有對象的引用類型的執行個體變量與克隆對象的引用類型的執行個體變量依然指向記憶體中的同一個執行個體。

Object類的

clone()

方法隻是一種淺克隆,隻克隆該對象的所有成員變量值,不會對引用類型的成員變量值所引用的對象進行克隆。

如果需要對對象進行深克隆,則需要進行遞歸克隆,保證所有引用類型的成員變量值所引用的對象都被複制了。

Objects類

Java7新增的一個類,提供了一些工具方法來操作對象,這些工具方法大多是空指針安全的。

Java為工具類的命名習慣是添加一個字母

s

,比如操作數組的工具類是

Arrays

,操作集合的工具類是

Collections

Java9改進的String、StringBuffer和StringBuilder類

Java提供了

String

StringBuffer

StringBuilder

三個類來封裝字元串,并提供了一系列方法來操作字元串對象。

String類是不可變類,即一旦一個String對象被建立以後,包含在這個對象的字元序列是不可改變的,直至這個對象被銷毀。

StringBuffer

對象則代表一個字元序列可變的字元串,當一個StringBuffer被建立以後,通過StringBuffer提供的

append()

insert()

reverse()

setCharAt()

setLength()

等方法改變這個字元串對象的字元序列。一旦通過StringBuffer生産了最終想要的字元串,就可以調用它的

toString()

方法将其轉換為一個String對象。

StringBuilder

類是JDK1.5新增的類,它也代表可變字元串對象。StringBuffer和StringBuilder基本相似,兩個類的構造器和方法也基本相同。不同的是,StringBuffer是線程安全的,而StringBuilder則沒有實作線程安全功能,是以性能略高。

String、StringBuffer、StringBuilder都實作了

CharSequence

接口,是以

CharSequence

可認為是一個字元串的協定接口。

  • String類提供了大量構造器來建立String對象
    • String()

      :建立了一個包含0個的字元串序列的String對象。
    • String(byte[] bytes, Charset charset)

      :使用指定的字元集将指定的

      byte[]

      數組解碼成一個新的String對象。
    • String(byte[] bytes, int offset, int length)

      :使用平台預設的字元集将指定的

      byte[]

      數組從

      offset

      開始、長度為

      length

      的子數組解碼成一個新的String對象。
    • String(byte[] bytes, int offset, int length, String charsetName)

      :使用指定的字元集将指定的

      byte[]

      數組從

      offset

      開始、長度為

      length

      的子數組解碼成一個新的String對象。
    • String(byte[] bytes, String charsetName)

      :使用指定的字元集将指定的

      byte[]

      數組解碼成一個新的String對象。
    • String(char[] value, int offset, int count)

      :将指定的字元數組從

      offset

      開始、長度為

      count

      的字元元素連綴成字元串。
    • String(String original)

      :根據字元串直接量來建立一個String對象。
    • String(StringBuffer buffer)

      :根據

      StringBuffer

      對象來建立對應的String對象。
    • String(StringBuilder builder)

      :根據

      StringBuilder

      對象來建立對應的String對象。
  • String類也提供了大量方法來操作字元串對象
    • char charAt(int index)

      :擷取字元串中指定位置的字元。
    • int compareTo(String anotherString)

      :比較兩個字元串的大小。如果兩個字元串的字元序列相等,則傳回0;不相等時,從兩個字元串第0個字元開始比較,傳回第一個不相等的字元差。另一種情況,較長字元串的前面部分恰巧是較短的字元串,則傳回它們的長度差。
    • String concat(String str)

      :将該String對象和str連接配接在一起。
    • boolean contentEquals(StringBuffer sb)

      :将該對象與StringBuffer對象sb進行比較,當它們包含的字元序列相同時傳回true。
    • static String copy ValueOf(char[] data)

      :将字數組連綴成字元串。
    • static String copyValueOf(char[] data, int offset, int count)

      :将char數組的子數組中的元素連綴成字元串。
    • boolean endsWith(String suffix)

      :傳回該String對象是否以

      suffix

      結尾。
    • boolean equals(Object anObject)

      :将字元串與指定對象比較,如果二者包含的字元序列相等,則傳回true,否則傳回false。
    • boolean equalsIgnoreCase(String str)

      :将字元串與

      str

      忽略大小寫比較。
    • byte[] getBytes()

      :将該String對象轉換成

      byte

      數組。
    • void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

      :該方法将字元串中從

      srcBegin

      開始,到

      srcEnd

      結束的字元複制到

      dst

      字元數組中,其中

      dstBegin

      為目标字元數組的起始複制位置。
    • int indexOf(int ch, int fromIndex)

      :找出

      ch

      字元在該字元串中從

      fromIndex

      開始第一次出現的位置。
    • int indexOf(String str)

      :找出

      str

      子字元串在該字元串中第一次出現的位置。
    • int indexOf(String str, int fromIndex)

      :找出

      str

      子字元串在該字元串中從

      fromIndex

      開始第一次出現的位置。
    • int lastIndexOf(int ch)

      :找出

      ch

      字元在該字元串中最後一次出現的位置。
    • int lastIndexOf(int ch, int fromIndex)

      :找出

      ch

      字元中從

      fronIndex

      在該字元串中最後一次出現的位置。
    • int lastIndexOf(String str)

      :找出

      str

      子字元串在該字元串中最後一次出現的位置。
    • int lastIndexOf(String str, int fromIndex)

      :找出

      str

      子字元串在該字元串中從

      fromIndex

      開始後最後一次出現的位置。
    • int length()

      :傳回目前字元串長度。
    • String replace(char oldChar, char newChar)

      :将字元串中第一個

      oldChar

      替換成

      newChar

    • boolean startsWith(String prefix)

      :該String對象是否以

      prefix

      開始。
    • boolean startsWith(String prefix, int toffset)

      :該String對象從

      toffset

      位置算起,是否以

      prefix

      開始。
    • String substring(int beginIndex)

      :擷取從

      beginIndex

      位置開始到結束的字元串。
    • String substring(int beginIndex, int endIndex)

      :擷取從

      beginIndex

      位置開始到

      endIndex

      位置的子字元串。
    • char[] toCharArray()

      :将該String對象轉換成char數組。
    • String toLowerCase()

      :将字元串轉換成小寫。
    • String toUpeprCase()

      :将字元串轉換成大寫。
    • static String valueOf(X x)

      :一系列用于将基本類型值轉換為String對象的方法。
  • StringBuffer、StringBuilder有兩個屬性:

    length

    capacity

    • 其中

      length

      屬性表示其包含的字元串序列的長度。與String對象不同的是,StringBuffer、StringBuilder的length是可以改變的,可以通過

      length()

      setLength(int len)

      方法來通路和修改其字元序列的長度。
    • capacity

      屬性表示StringBuilder的容量,

      capacity

      通常比

      length

      大,程式通常無需關心

      capacity

      屬性。

Math類

Math類是一個工具類,它的構造器被定義成

private

的,是以無法建立Math類的對象;Math類中的所有方法都是類方法;還提供了的兩個類變量

PI

E

ThreadLocalRandom與Random

Random

類專門用于生成一個僞随機數,它有兩個構造器:一個構造器使用預設的種子(以目前時間作為種子),另一個構造器需要顯式傳入一個

long

型整數的種子。

ThreadLocalRandom

類是Java7新增的一個類,它是

Random

的增強版。在并發通路的環境下,使用

ThreadLocalRandom

來代替

Random

可以減少多線程資源競争,最終保證系統具有更好的線程安全性。

ThreadLocalRandom

類的用法和

Random

類的用法基本相似,它提供了一個靜态的

current()

方法來擷取

ThreadLocalRandom

對象,擷取該對象之後即可調用各種

nextXxx()

方法來擷取僞随機數。

Random使用一個48位的種子,如果這個類的兩個執行個體都是用同一個種子建立的,對它們以同樣的順序調用方法,則它們會産生相同的數字序列。

為避免兩個Random對象産生相同的數字序列,通常推薦使用目前時間作為Random對象的種子:

System.currentTimeMillis();

BigDecimal類

float

double

兩種基本浮點類型的浮點數容易引起精度丢失。

為了精确表示、計算浮點數,Java提供了

BigDecimal

類,該類提供了大量的構造器用于建立BigDecimal對象,包括把所有的基本數值類型變量轉換成一個BigDecimal對象,包括利用數字字元串、數字字元數組來建立BigDecimal對象。

不推薦使用

BigDecimal(double val);

構造器來建立對象,而是

BigDecimal(String val);

BigDecimal.valueOf(double value);

靜态方法來建立BigDecimal對象。

BigDecimal類提供了

add()

subtract()

multiply()

divide()

pow()

等方法對精确浮點數進行正常算術運算。

日期、時間類

Date類

Java提供了

Date

類來處理日期、時間,Date對象既包含日期,也包含時間。

Date類從JDK1.0起就開始存在了,但正因為它曆史悠久,是以它的大部分構造器、方法都已經過時,不在推薦使用了。

Date類提供了6個構造器,其中4個已經

Deprecated

(Java不在推薦使用,使用不再推薦的構造器時編譯會提出警告資訊,并導緻程式性能、安全性能等方面的問題),剩下的兩個構造器:

  • Date()

    :生成一個代表目前日期時間的Date對象。該構造器在底層調用

    System.currentMillis()

    獲得

    long

    整數作為日期參數。
  • Date(long date)

    :根據指定的

    long

    型整數來生成一個Date對象。該構造器的參數表示建立的Date對象和GMT1970年1月1日00:00:00之間的時間差,以毫秒作為計時機關。

Date對象的大部分方法也

Deprecated

了,剩下為數不多的幾個方法:

  • boolean after(Date when)

    :測試該日期是否在指定日期when之後。
  • boolean before(Date when)

    :測試該日期是否在指定日期when之前。
  • long getTime()

    :傳回該時間對應的long型整數,即從GMT1970-01-01 00:00:00到該Date對象之間的時間差,以毫秒作為計時機關。
  • void setTime(long time)

    :設定Date對象的時間。

總體來說,Date是一個設計相當糟糕的類,Java官方推薦盡量少用Date的構造器和方法。

Calendar類

由于

Date

類在設計上存在一些缺陷,是以Java提供了

Calendar

類來更好地處理日期和時間。

Calendar

類本身是一個抽象類,它是所有月曆類的模闆,并提供了一些所有月曆通用的方法;但它本身不能直接執行個體化,程式隻能建立

Calendar

子類的執行個體,Java本身提供了一個

GregorianCalendar

類,一個代表格裡高利月曆的子類,它代表了通常所說的公曆。

Calendar

類是一個抽象類,是以不能使用構造器來建立Calendar對象。但它提供了幾個靜态

getInstance()

方法來擷取

Calendar

對象,這些方法根據

TimeZone

Locale

類來擷取特定的

Calendar

,如果不指定

TimeZone

Locale

,則使用預設的

TimeZone

Locale

來建立

Calendar

Calendar

Date

都是表示日期的工具類,他們直接可以自由轉換。

Calendar類提供了大量通路、修改日期時間的方法:

  • void add(int field, int amount)

    :根據月曆的規則,為給定的月曆字段添加或減去指定的時間量。
  • int get(int field)

    :傳回指定月曆字段的值。
  • int getActualMaximum(int field)

    :傳回指定月曆字段可能擁有的最大值。
  • int getActualMinimum(int field)

    :傳回指定月曆字段可能擁有的最小值。
  • void set(int field, int value)

    :為給定的月曆字段設定為給定值。
  • void set(int year, int month, int date)

    :設定Calendar對象的年、月、日三個字段的值。
  • void set(int year, int month, int date, int hourOfDay, int minute, int second)

    :設定Calendar對象的年、月、日、時、分、秒6個字段的值。

上面的很多方法都需要一個

int

類型的

field

參數,

field

Cakendar

類的類變量,如

Calendar.YEAR

Calendar.MONTH

等分别代表了年、月、日、小時、分鐘、秒等時間字段。

Calendar.MONTH

字段代表月份,月份的起始值不是1,而是0。

Calendar類的注意點:

  1. add

    roll

    的差別
    • add(int field, int amount)

      的功能非常強大,

      add

      主要用于改變

      Calendar

      的特定字段的值。有兩條規則:
      • 當被修改的字段超出它允許的範圍時,會發生進位,即上一級字段也會增大。
      • 如果下一級字段也需要改變,那麼該字段會修正到變化最小的值。
    • roll()

      的規則與

      add()

      的處理規則不同:當被修改的字段超出它允許的範圍時,上一級字段不會增大;下一級字段的處理規則與

      add()

      相似。
  2. 設定

    Calendar

    的容錯性
    • Calendar有兩種解釋月曆字段的模式:

      lenient

      模式和

      non-lenient

      模式。當處于

      lenient

      模式時,每個時間字段可接受超過它允許範圍的值;當處于

      non-lenient

      模式時,如果為某個時間字段設定的值超出了它允許的取值範圍,程式将會抛出異常。
  3. set()

    方法延遲修改
    • set(f, value)

      方法将月曆字段

      f

      更改為

      value

      ,此處它還設定了一個内部成員變量,以訓示月曆字段

      f

      已經被更改。盡管月曆字段

      f

      是立即更改的,但該

      Calendar

      所代表的時間不會立即修改,直到下次調用

      get()

      getTime()

      getTimeInMillis()

      add()

      roll()

      時才會重新計算月曆的時間。

Java8新增的日期、時間包

Java8新增了一個java.time包,該包包含如下常用類:

  • Clock

    :該類用于擷取指定時區的目前日期、時間。該類可取代System類的currentTimeMillis()方法,而且提供了更多方法來擷取目前日期、時間。該類提供了大量靜态方法來擷取

    Clock

    對象。
  • Duration

    :該類代表持續時間。該類可以非常友善地擷取一段時間。
  • Instant

    :代表一個具體的時刻,可以精确到納秒。該類提供了靜态的

    now()

    方法來擷取目前時刻,也提供了靜态的

    now(Clock clock)

    方法來擷取

    clock

    對應的時刻。除此之外,它還提供了一系列

    minusXxx()

    方法在目前時刻基礎上減去一段時間,也提供了

    plusXxx()

    方法在目前時刻基礎上加上一段時間。
  • LocalDate

    :該類代表不帶時區的日期,例如1999-10-30。該類提供了靜态的

    now()

    方法來擷取目前日期,也提供了靜态的

    now(Clock clock)

    方法來擷取目前

    clock

    對應的日期。除此之外,它還提供了一系列

    minusXxx()

    方法在目前年份基礎上減去幾年、幾月、幾周或幾日,也提供了

    plusXxx()

    方法在目前年份基礎上加上幾年、幾月、幾周或幾日。
  • LocalTime

    :該類代表不帶時區的時間,例如10:30:13。該類提供了靜态的

    now()

    方法來擷取目前時間,也提供了靜态的

    now(Clock clock)

    方法來擷取

    clock

    對應的時間。除此之外,它還提供了一系列

    minusXxx()

    方法在目前年份基礎上減去幾小時、幾分、幾秒等,也提供了

    plusXxx()

    方法在目前年份基礎上加上加幾小時、幾分、幾秒等。
  • LocalDateTime

    :該類代表不帶時區的日期、時間,例如1999-10-30T10:30:13。該類提供了靜态的

    now()

    方法來擷取目前日期、時間,也提供了靜态的

    now(Clock clock)

    方法來擷取

    clock

    對應的日期、時間。除此之外,它還提供了一系列

    minusXxx()

    方法在目前年份基礎上減去幾年、幾月、幾日幾小時、幾分、幾秒等,也提供了

    plusXxx()

    方法在目前年份基礎上加上幾年、幾月、幾日幾小時、幾分、幾秒等。
  • MonthDay

    :該類僅代表月日,例如–10-30。該類提供了靜态的

    now()

    方法來擷取目前月日,也提供了靜态的

    now(Clock clock)

    方法來擷取

    clock

    對應的月日。
  • Year

    :該類僅代表年,例如1999。該類提供了靜态的

    now()

    方法來擷取目前年份,也提供了靜态的

    now(Clock clock)

    方法來擷取

    clock

    對應的年份。除此之外,它還提供了

    minusYears()

    方法在目前年份基礎上減去幾年,也提供了

    plusYear()

    方法在目前年份基礎上加上幾年。
  • YearMonth

    :該類僅代表年月,例如1999-10。該類提供了靜态的

    now()

    方法來擷取目前年月,也提供了靜态的

    now(Clock clock)

    方法來擷取

    clock

    對應的年月。除此之外,它還提供了

    minusXxx()

    方法在目前年月基礎上減去幾年、幾月,也提供了

    plusXxx()

    方法在目前年月基礎上加上幾年、幾月。
    • ZonedDateTime

      :該類代表一個時區化的日期、時間。
    • ZoneId

      :該類代表一個時區。
    • DayOfWeek

      :這是一個枚舉類,定義了周日到周六的枚舉值。
    • Month

      :這是一個枚舉類,定義了一月到十二月的枚舉值。

正規表達式

正規表達式是一個強大的字元串處理工具,可以對字元串進行查找、提取、分割、替換等操作。

String

類裡也提供了如下幾個特殊方法:

  • boolean matches(String regex)

    :判斷該字元串是否比對指定的正規表達式。
  • String replaceAll(String regex, String replacement)

    :将該字元串中所有比對

    regex

    的字串替換成

    replacement

  • String repalceFirst(String regex, String replacement)

    :将該字元串中第一個比對

    regex

    的字串替換成

    replacement

  • String[] split(String regex)

    :以

    regex

    作為分隔符,把該字元串分割成多個字串。

上面這些特殊的方法都依賴于Java提供的正規表達式支援,除此之外,Java還提供了

Pattern

Matches

兩個類專門用于提供正規表達式支援。

建立正規表達式

正規表達式所支援的合法字元:

  • x

    :字元x(x可代表任何合法的字元)
  • \0mnn

    :八進制數0mnn所代表的字元
  • \xhh

    :十六進制值0xhh所代表的字元
  • \uhhhh

    :十六進制值0xhhhh所代表的

    Unicode

    字元
  • \t

    :制表符(’\u000A’)
  • \n

    :新行(換行)符(’\u000A’)
  • \r

    :回車符(’\u000D’)
  • \f

    :換頁符(’\u000C’)
  • \a

    :報警(bell)符(’\u0007’)
  • \e

    :Escape符(’\u001B’)
  • \cx

    :

    x

    對應的控制符。x值必須為

    A~Z

    a~z

    之一。

正規表達式中有一些特殊字元,這些特殊字元在正規表達式中有其特殊的用途,如果需要比對這些特殊字元,就必須首先将這些字元轉義,也就是在前面加一個反斜線(

\

)。

  • $

    :比對一行的結尾。
  • ^

    :比對一行的開頭。
  • ()

    :标記子表達式的開始和結束位置。
  • []

    :用于确定中括号表達式的開始和結束位置。
  • {}

    :用于标記前面子表達式的出現頻度。
  • *

    :指定前面子表達式可以出現零次或多次,
  • +

    :指定前面表達式可以出現一次或多次。
  • ?

    :指定前面子表達式可以出現零次或一次。
  • \

    :用于轉義下一個字元,或指定八進制、十六進制字元。
  • |

    :指定兩項之間任選一項。

預定義字元

  • .

    :可以比對任何字元。
  • \d

    :比對

    0~9

    的所有數字。
  • \D

    :比對非數字。
  • \s

    :比對所有的空白字元,包括空格、制表符、回車符、換頁符、換行符等。
  • \S

    :比對所有的非空白字元。
  • \w

    :比對所有的單詞字元,包括0~9所有數字、26個英文字母和下劃線(_)。
  • \W

    :比對所有的非單詞字元。

方括号表達式

  • 表示枚舉:例如

    [fx]

    ,表示f、x其中任意一個字元;

    [jk]

    表示j、x其中任意一個字元。
  • 表示範圍-:例如

    [a-f]

    ,表示

    a~f

    範圍内的任意字元;如

    [a-cx-z]

    ,表示

    a~c

    x~z

    範圍内的任意字元。
  • 表示求否

    ^

    :例如

    [^abc]

    ,表示非a、b、c的任意字元;

    [^a-f]

    ,表示不是

    a~f

    範圍内的任意字元。
  • 表示與運算

    &&

    :例如

    [a-z&&[def]]

    ,求

    a~z

    [def]

    的交集,表示d、e或f;

    [a-z&&[^bc]]

    ,

    a~z

    範圍内的所有字元,除b和c之外,即

    [ad-z]

  • 表示并運算:并運算與前面的枚舉類似。例如

    [a-d[m-p]]

    ,表示

    [a-dm-p]

邊界比對符

  • ^

    :行的開頭
  • $

    :行的結尾
  • \b

    :單詞的邊界
  • \B

    :非單詞的邊界
  • \A

    :輸入的開頭
  • \G

    :前一個比對的結尾
  • \Z

    :輸入的結尾,僅用于最後的結束符。
  • \z

    :輸入的結尾

數量辨別符

  • Greedy

    (貪婪模式):數量辨別符預設采用貪婪模式,除非另有表示。貪婪模式的表達式會一直比對下去,直到無法比對為止。
    • X?

      :X表達式出現零次或一次
    • X*

      :X表達式出現零次或多次
    • X+

      :X表達式出現一次或多次
    • X{n}

      :X表達式出現n次
    • X{n,}

      :X表達式最少出現n次
    • X{n,m}

      :X表達式最少出現n次,最多出現m次
  • Reluctant

    (勉強模式):用問号字尾(

    ?

    )表示,它隻會比對最少的字元。也稱為最小比對模式。
    • X??

      :X表達式出現零次或一次
    • X*?

      :X表達式出現零次或多次
    • X+?

      :X表達式出現一次或多次
    • X{n}?

      :X表達式出現n次
    • X{n,}?

      :X表達式最少出現n次
    • X{n,m}?

      :X表達式最少出現n次,最多出現m次
  • Possessive

    (占有模式):用加号字尾(

    +

    )表示,目前隻有Java支援占有模式,通常比較少用。
    • X?+

      :X表達式出現零次或一次
    • X*+

      :X表達式出現零次或多次
    • X++

      :X表達式出現一次或多次
    • X{n}+

      :X表達式出現n次
    • X{n,}+

      :X表達式最少出現n次
    • X{n,m}+

      :X表達式最少出現n次,最多出現m次

使用正規表達式

一旦在程式中定義了正規表達式,就可以使用

Pattern

Matcher

來使用正規表達式。

Pattern

對象是正規表達式編譯後在記憶體中的表示形式,是以,正規表達式字元串必須先被編譯為Pattern對象,然後再利用Pattern對象建立對應的

Matcher

對象。執行比對所涉及的狀态保留在

Matcher

對象中,多個

Matcher

對象可共享同一個

Pattern

對象。

如果某個正規表達式僅需一次使用,則可直接使用Pattern類的靜态

matches()

方法,此方法自動把指定字元串編譯成匿名

Pattern

對象,并執行比對。

Pattern是不可變類,可供多個并發線程安全使用。

Matcher

類提供了如下幾個常用方法:

  • find()

    :傳回目标字元串中是否包含與

    Pattern

    比對的子串。
  • group()

    :傳回上一次與

    Pattern

    比對的子串。
  • start()

    :傳回上一次與

    Pattern

    比對的子串在目标字元串中的開始位置。
  • end()

    :傳回上一次與

    Pattern

    比對的子串在目标字元串中的結束位置加1。
  • lookingAt()

    :傳回目标字元串前面部分與

    Pattern

    是否比對。
  • matches()

    :傳回整個目标字元串與

    Pattern

    是否比對。
  • reset()

    :将現有的

    Matcher

    對象應用于一個新的字元序列。

通過

Matcher

類的

find()

group()

方法可以從目标字元串中依次取出特定子串(比對正規表達式的子串)。

find()

方法依次查找字元串中與

Pattern

比對的子串,一旦找到對應的子串,下次調用

find()

方法時将接着向下查找。

find()

方法還可以傳入一個

int

類型的參數,帶

int

參數的

find()

方法将從該

int

索引處向下搜尋。

start()

end()

方法主要用于确定子串在目标字元串中的位置。

使用

find()

group()

方法逐項取出目标字元串中與指定正規表達式比對的子串,并使用

start()

end()

方法傳回子串在目标字元串中的位置。

matches()

lookingAt()

方法有點相似,隻是

matches()

方法要求整個字元串和

Pattern

完全比對時才傳回

true

,而

lookingAt()

隻要字元串以

Pattern

開頭就會傳回

true

reset()

方法可将現有的

Matcher

對象應用于新的字元序列。

從某個角度看,

Matcher

matches()

lookingAt()

String

類的

equals()

startWith()

有點相似。差別是

String

類的

equals()

和、

startWith()

都是與字元串進行比較,而

Matcher

matches()

lookingAt()

則是與正規表達式進行比對。

String

類裡也提供了

matches()

方法,該方法傳回該字元串是否比對指定的正規表達式。

還可以利用正規表達式對目标字元串進行分割、查找、替換等操作。

Matcher

類提供了

replaceAll(String replacement)

把字元串中所有與正規表達式比對的子串替換成

replacement

,還提供了一個

replaceFirst(String replacement)

方法,該方法僅替換第一個比對的子串。

String

類也提供了

replaceAll()

replaceFirst()

split()

等方法。

變量處理和方法處理

Java9引入了一個新的

VarHandle

類,并增強了原有的

MethodHandle

類。通過這兩個類,允許Java像動态語言一樣引用變量、飲用方法,并調用它們。

Java9增強的

MethodHandle

  • MethodHandle

    為Java增強了方法引用的功能,方法引用的概念有點類似于C的函數指針。這種方法引用是一種輕量級的引用方式,它不會檢查方法的通路權限,也不管方法所屬的類、執行個體方法或靜态方法,

    MethodHandle

    就是簡單代表特定的方法,并可通過

    MethodHandle

    來調用方法。
  • 為了使用

    MethodHandle

    類,還涉及如以下幾個類:
    • MethodHandles

      :

      MethodHandle

      的工廠類,它提供了一系列靜态方法用于擷取

      MethodHandle

    • MethodHandles.Lookup

      :

      Lookup

      靜态内部類也是

      MethodHandle

      VarHandle

      的工廠類,專門用于擷取

      MethodHandle

      VarHandle

    • MethodType

      :代表一個方法類型。

      MethodType

      根據方法的形參、傳回值類型來确定方法類型。
    • 程式使用

      MethodHandles.Lookup

      對象根據類、方法名、方法類型來擷取

      MethodHandle

      對象。擷取的方法名是一個字元串類型,這意味着通過

      MethodHandle

      可以讓Java動态調用某個方法。

Java9增強的

VarHandle

  • VarHandle

    主要用于動态操作數組的元素或對象的成員變量。

    VarHandle

    MethodHandle

    非常相似,它也需要通過

    MethodHandles

    來擷取執行個體,接下來調用

    VarHandle

    的方法即可動态操作指定數組的元素或指定對象的成員變量。

Java9改進的國際化與格式化

國際化是指應用程式運作時,可根據用戶端請求來自的國家/地區、語言的不同而顯示不同的界面。

Java國際化的思路:

  • Java程式的國際化思路是将程式中的标簽、提示等資訊放在資源檔案中,程式需要支援哪些國家、語言環境,就對應提供的資源檔案。
  • 資源檔案是

    key-value

    對,每個資源檔案中的

    key

    是不變的,但

    value

    則随不同的國家、語言而改變。
  • Java程式的國際化主要是通過如下三個類完成:
    • java.util.ResourceBundle

      :用于加載國家、語言資源包。
    • java.util.Locale

      :用于封裝特定的國家/區域、語言環境。
    • java.text.MessageFormat

      :用于格式化帶占位符的字元串。
  • 資源檔案的命名可以有如下三種形式:
    • baseName_language_country.properties

    • baseName_language.properties

    • baseName.properties

  • 其中

    baseName

    是資源檔案的基本名,使用者可随意指定;而

    language

    country

    都不可随意變化,必須是Java所支援的語言和國家。

Java支援的國家和語言:

  • 可調用

    Locale

    類的

    getAvailableLocales()

    方法,該方法傳回一個

    Locale

    數組,該數組包含了Java所支援的國家和語言。

完成程式國際化:

  • 為了讓字元串常量可以改變,可以将需要輸出的各種字元串(不同的國家/語言環境對應不同的字元串)定義在資源包中。
  • Java9支援使用

    UTF-8

    字元集來儲存屬性檔案,這樣在屬性檔案中就可以直接包含非西歐字元。
  • Java9程式國際化的關鍵類是

    ResourceBundle

    ,它有一個靜态方法:

    getBUndle(String baseName, Locale locale)

    ,該方法将根據

    Locale

    加載資源檔案,而

    Locale

    封裝了一個國家、語言。

使用

MessageFormat

處理包含占位符的字元串:

  • 如果需要輸出的消息中必須包含動态的内容,可以使用帶占位符的消息。
  • 例如:

    msg=你好!{0}!今天是{1}

    。當程式使用

    ResourceBundle

    getString()

    方法來取出

    msg

    對應的字元串時,程式還需要為

    {0}

    {1}

    兩個占位符指派。
  • 此時需要使用

    MessageFormat

    類,該類包含一個有用的靜态方法:
    • format(String pattern, Object... values)

      :傳回後面的多個參數值填充前面的

      pattern

      字元串,其中

      patter

      不是正規表達式,而是一個帶占位符的字元串。

使用類檔案代替資源檔案:

除使用屬性檔案作為資源檔案外,

Java

也允許使用類檔案代替資源檔案,即将所有的

key-value

對存入

class

檔案。

使用類檔案來代替資源檔案必須滿足以下條件:

  • 該類的類名必須是

    baseName_language_country

    ,這與屬性檔案的命名相似。
  • 該類必須繼承

    ListResourceBundle

    ,并重寫

    getContents()

    方法,該方法傳回

    Object

    數組,該數組的每一項都是

    key-value

    對。

如果系統同時存在資源檔案、類檔案,系統将以類檔案為主,而不會調用資源檔案。

對于簡體中文的

Locale

ResourceBundle

搜尋資源檔案的順序是:

  • baseName_zh_CN.class

  • baseName_zh_CN.properties

  • baseName_zh.class

  • baseName_zh.properties

  • baseName.class

  • baseName.properties

Java9新增的日志API

Java9強化了原有的日志API,這套日志API隻是定義了記錄消息的最小API,開發者可将這些日志消息路由到各種主流的日志架構(如

SLF4J

Log4J

等),否則預設使用Java傳統的

java.util.logging

日志

API

這套日志API的用法非常簡單,隻要兩步即可:

  • 調用

    System

    類的

    getLogger(String name)

    方法擷取

    System.Logger

    對象
  • 調用

    System.Logger

    對象的

    log()

    方法輸出日志。該方法的第一個參數用于指定日志級别。
    • 日志級别:
      • Java9日志級别
        • ALL

          :最低級别,系統将會輸出所有日志資訊。
        • TRACE

          :輸出系統的各種跟蹤資訊。
        • DEBUG

          :輸出系統的各種調試資訊。
        • INFO

          :輸出系統内需要提示使用者的提示資訊。
        • WARNING

          :隻輸出系統内警告使用者的警告資訊。
        • ERROR

          :隻輸出系統發生錯誤的錯誤資訊。
        • OFF

          :關閉日志輸出。
      • 傳統日志級别
        • ALL

          :最低級别,系統将會輸出所有日志資訊。
        • FINER

          :輸出系統的各種跟蹤資訊。
        • FINE

          :輸出系統的各種調試資訊。
        • INFO

          :輸出系統内需要提示使用者的提示資訊。
        • WARNING

          :隻輸出系統内警告使用者的警告資訊。
        • SERVRE

          :隻輸出系統發生錯誤的錯誤資訊。
        • OFF

          :關閉日志輸出。

Java9的日志API也支援國際化,

System

類除使用簡單的

getLogger(String name)

方法擷取

System.Logger

對象之外,還可使用

getLogger(String name, ResourceBundle bundle)

方法來擷取該對象,該方法需要傳入一個國際化語言資源包,這樣該

Logger

對象即可根據

key

來輸出國際化的日志資訊。

使用

NumberFormat

格式化數字

MessageFormat

是抽象類

Format

的子類,

Format

抽象類還有兩個子類:

NumberFormat

DateFormat

,它們分别用以實作數值、日期的格式化。

NumberFormat

DateFormat

可以将數值、日期轉換成字元串,也可以将字元串轉換成數值、日期。

NumberFormat

DateFormat

都包含了

format()

parse()

方法,其中

format()

用于将數值、日期格式化成字元串,

parse()

用于将字元串解析成數值、日期。

NumberFormat

也是一個抽象基類,是以無法通過它的構造器來建立

NumberFormat

對象,它提供了如下幾個類方法來得到

NumberFormat

對象:

  • getCurrencyInstance()

    :傳回預設

    Locale

    的貨币格式器。也可以在調用該方法時傳入指定的

    Locale

    ,則擷取指定

    Locale

    的貨币格式器。
  • getIntegerInstance()

    :傳回預設

    Locale

    的整數格式器。也可以在調用該方法時傳入指定的

    Locale

    ,則擷取指定

    Locale

    的整數格式器。
  • getNumberInstance()

    :傳回預設

    Locale

    的通用數值格式器。也可以在調用該方法時傳入指定的

    Locale

    ,則擷取指定的

    Locale

    的通用數值格式器。
  • getPercentInstance()

    :傳回預設的

    Locale

    的百分數格式器。也可以在調用該方法時傳入指定的

    Locale

    ,則擷取指定的

    Locale

    的百分數格式器。

一旦獲得了

NumberFormat

對象後,就可以調用它的

format()

方法來格式化數值,包括整數和浮點數。

使用

DateFormat

格式化日期、時間

  • NumberFormat

    相似的是,

    DateFormat

    也是一個抽象類,它也提供了如下幾個類方法用于擷取

    DateFormat

    對象:
    • getDateInstance()

      :傳回一個日期格式器,它格式化後的字元串隻有日期,沒有時間。該方法可以傳入多個參數,用于指定日期樣式和

      Locale

      等參數;如果不指定這些參數,則使用預設參數。
    • getTimeInstance()

      :傳回一個時間格式器,它格式化後的字元串隻有時間,沒有日期。該方法可以傳入多個參數,用于指定時間樣式和

      Locale

      等參數;如果不指定這些參數,則使用預設參數。
    • getDateTimeInstance()

      :傳回一個日期、時間格式器,它格式化後的字元串既有日期,也有時間。該方法可以傳入多個參數,用于指定日期樣式、時間樣式和

      Locale

      等參數;如果不指定這些參數,則使用預設參數。

上面三個方法可以指定日期樣式、時間樣式參數,它們是

DateFormat

的4個靜态常量:

FULL

LONG

MEDIUM

SHORT

,通過這4個樣式參數可以控制生成的格式化字元串。

DateFormat

parse()

方法可以把一個字元串解析成

Date

對象,但它要求被解析的字元串必須符合日期字元串的要求,否則可能抛出

ParseException

異常。

使用

SimpleDateFormat

格式化日期

DateFormat

parse()

方法可以把字元串解析成

Date

對象,但

parse()

方法不夠靈活,它要求被解析的字元串必須滿足特定的格式;為了更好地格式化日期、解析日期字元串,Java提供了

SimpleDateFormat

類。

  • SimpleDateFormat

    DateFormat

    的子類。
  • SimpleDateFormat

    可以非常靈活地格式化

    Date

    ,也可以用于解析各種格式的日期字元串。建立

    SimpleDateFormat

    對象時需要傳入一個

    pattern

    字元串,這個

    pattern

    不是正規表達式,而是一個日期模闆字元串。

Java8新增的日期、時間格式器

java.time.format

包下提供了一個

DateTimeFormatter

格式器類,該類相當于

DateFormat

SimpleDateFormat

的合體。

DateTimeFormatter

不僅可以将日期、時間對象格式化成字元串,也可以将特定格式的字元串解析成日期、時間對象。

為了使用

DateTimeFormatter

進行格式化或解析,必須先擷取

DateTimeFormatter

對象,擷取對象有如下三種常見的方式:

  • 直接使用靜态常量建立

    DateTimeFormatter

    格式器。

    DateTimeFormatter

    類中包含了大量形如

    ISO_LOCAL_DATE

    ISO_LOCAL_TIME

    ISO_LOCAL_DATE_TIME

    等靜态常量,這些靜态常量本身就是

    DateTimeFormatter

    執行個體。
  • 使用代表不同風格的枚舉值來建立

    DateTimeFormatter

    格式器。在

    FormatStyle

    枚舉類中定義了

    FULL

    LONG

    MEDIUM

    SHORT

    四個枚舉值,它們代表日期、時間不同的風格。
  • 根據模式字元串來建立

    DateTimeFormatter

    格式器。類似于

    SimpleDateFormat

    ,可以采用模式字元串來建立

    DateTimeFormatter

使用DateTimeFormatter完成格式化

使用

DateTimeFormatter

将日期、時間(

LocalDate

LocalDateTime

LocalTime

等執行個體)格式化為字元串,可通過如下兩種方式:

  • 調用

    DateTimeFormatter

    format(TemporalAccessor temporal)

    方法執行格式化,其中

    LocalDate

    LocalDateTime

    LocalTime

    類都是

    TemporalAccessor

    接口的實作類。
  • 調用

    LocalDate

    LocalDateTime

    LocalTime

    等日期、時間對象的

    format(DateTimeFormatter formatter)

    方法執行格式化。

DateTimeFormatter

則提供了一個

toFormat()

方法,該方法可擷取

DateTimeFormatter

對應的

Format

對象。

使用DateTimeFormatter解析字元串

使

DateTimeFormatter

将指定格式的字元串解析成日期、時間對象(

LocalDate

LocalDateTime

LocalTime

等執行個體),可通過日期、時間對象提供的

parse(CharSequence text, DateTimeFormatter formatter)

方法進行解析。