Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤和異常

Java 多執行緒

Java 同步

Java 網路程式設計

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 雜項

Java API 和框架

Java 類引用

Java 有用資源

Java 8 新特性



JAVA 8 是 JAVA 程式語言 開發的一個主要功能版本。其初始版本於 2014 年 3 月 18 日釋出。隨著 Java 8 的釋出,Java 提供了對函數語言程式設計、新的 JavaScript 引擎、新的日期時間操作 API、新的流 API 等的支援。

以下是 Java 8 支援的新特性列表:

Lambda 表示式

Lambda 表示式 是 Java 中引入的最重要的特性之一。Lambda 表示式促進了 Java 中的函數語言程式設計。Lambda 表示式基於函式式介面的原理。函式式介面是一個只有一個方法要實現的介面。Lambda 表示式提供函式式介面方法的實現。

Lambda 表示式極大地簡化了函數語言程式設計,並使程式碼更易讀,無需任何樣板程式碼。Lambda 表示式可以推斷使用的引數型別,並且可以在沒有 return 關鍵字的情況下返回值。對於簡單的單語句方法,甚至可以省略大括號。

示例 - 使用 Lambda 表示式

以下示例展示了 Lambda 表示式的用法。Lambda 表示式最適合與函式式介面一起使用,函式式介面只有一個抽象方法。我們定義了一個只有一個方法 operate 的介面 Calculator,它可以接受兩個引數並返回一個值。在 main 方法中,我們首先使用匿名函式實現了 Calculator 介面,然後使用 Lambda 表示式。operate() 方法在兩種情況下都被呼叫以列印結果,並且結果都被打印出來。

package com.tutorialspoint;

public class Tester {

   public static void main(String[] args) {
      // Interface implementation using anonymous class
      Calculator sum = new Calculator() {
         @Override
         public int operate(int a, int b) {
            return a + b;
         }
      };
      int result = sum.operate(2,3);
      System.out.println(result);	   

      // Interface implementation using lambda expression
      Calculator sum1 = (a,b) -> a + b;
      result = sum1.operate(2,3);
      System.out.println(result);
   }  

   interface Calculator {
      int operate(int a, int b);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

5
5

方法引用

方法引用 是一種簡短而簡潔的呼叫方法、靜態方法甚至建構函式的方式,無需冗長的語法。方法引用有助於透過名稱指向方法,即使不指定引數也是如此。引數由 Lambda 表示式傳遞。方法引用使用 "::" 符號描述。

可以使用以下語法引用靜態方法:

<<class-name>>::methodName

可以使用以下語法引用例項方法:

<<object-name>>::methodName

可以使用以下語法呼叫建構函式:

<<class-name>>::new

示例 - 使用方法引用

在這個例子中,我們使用了靜態方法 compare 和例項方法 compareTo 來排序兩個整數的 ArrayList。我們使用方法引用來表示靜態方法和例項方法。

package com.tutorialspoint;

import java.util.Arrays;
import java.util.List;

public class Tester {
   public static void main(String args[]) {
      List<Integer> numbers = Arrays.asList(1,2,4,9,8,7,3);
      System.out.println("Sorted using static method reference");
      // Use static method compare
      numbers = numbers.stream().sorted(Integer::compare).toList();
      System.out.println(numbers);

      numbers = Arrays.asList(1,2,4,9,8,7,3);
      System.out.println("Sorted using instance method reference" );
      // Use instance method compareTo
      numbers = numbers.stream().sorted(Integer::compareTo).toList();

      System.out.println(numbers);		
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

Sorted using static method reference
[1, 2, 3, 4, 7, 8, 9]
Sorted using instance method reference
[1, 2, 3, 4, 7, 8, 9]

預設方法

在 Java 8 之前,介面只能包含抽象方法。隨著 Java 8 的釋出,引入了 Lambda 表示式。現在為了向後相容性,添加了 預設方法 功能,以便舊的 介面 可以利用 Lambda 表示式而無需修改其實現。

例如,ListCollection 介面 沒有 'forEach' 方法宣告。因此,新增此方法只會破壞集合框架的實現。Java 8 引入了預設方法,以便 List/Collection 介面可以具有 forEach 方法的預設實現,而實現這些介面的類無需實現相同的方法。

語法

以下是 Java 中介面中預設方法的語法:

public interface vehicle {
   default void message() {
      System.out.println("I am a vehicle!");
   }
}

示例 - 使用預設方法

在這個例子中,我們建立了一個包含預設方法的介面。在實現類中,此訊息未實現,用於列印訊息。

package com.tutorialspoint;

interface vehicle {
   // default method must have an implementation
   default void message() {
      System.out.println("I am a vehicle!");
   }
}

// implementing class need not to implement the default method
// of an interface.
public class Tester implements vehicle {
   public static void main(String args[]) {
      Tester tester = new Tester();
      // implementing class can access the default method as its own method
      tester.message(); 
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

I am a vehicle!

Stream API

Stream API 是 Java 8 中引入的一個新的抽象層,用於以宣告式方式處理資料。流表示一系列元素。流以順序方式提供特定型別的元素集合。流按需獲取/計算元素。它永遠不會儲存元素。

Stream 支援聚合操作,例如 filter、map、limit、reduce、find、match 等,並且可以在內部對提供的源元素進行迭代,這與需要顯式迭代的集合形成對比。

語法

以下是使用流的通用語法

<<collection-instance>>.stream().<<non-terminal-operation()>>.<<non-terminal-operation()>>.<<terminal-operation()>>

示例 - 使用 Stream

在這個例子中,我們建立了一個字串列表,其中一些條目為空。現在使用 Stream API,我們過濾空字串並計算它們的數量。

package com.tutorialspoint;

import java.util.Arrays;
import java.util.List;

public class Tester {
   public static void main(String args[]) {
      List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

      // get stream from list using stream() method
      // then apply filter
      // lastly count the result of filter
      long count = strings.stream().filter(string->string.isEmpty()).count();
      System.out.println("Empty Strings: " + count);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

Empty Strings: 2

Optional 類

Optional 類 功能是在 Java 8 中引入的,用於以程式設計方式處理空指標異常場景,使程式更簡潔、更不易出錯。當使用空物件引用獲取其值或呼叫其方法時,就會發生空指標異常。隨著程式規模的增加,處理所有可能發生空指標異常的情況變得非常繁瑣。

Optional 類例項為物件提供了一個包裝器,其中包含許多實用程式方法,例如在底層值為 null 時獲取備用值,檢查物件引用是否為 null 等。

示例 - 使用 Optional 類

在這個例子中,我們使用 oofNullable() 方法建立了兩個 Optional 類例項,該方法允許將底層物件作為 null 傳遞,然後使用 orElse() 方法檢索值,如果底層物件為 null,則返回預設值。

package com.tutorialspoint;

import java.util.Optional;

public class Tester {
   public static void main(String args[]) {
      // case 1: Optional is having null as underlying value
      Optional<Integer> valueOptional = Optional.ofNullable(null);

      // case 2:  Optional is having not null as underlying value
      Optional<Integer> valueOptional1 = Optional.ofNullable(Integer.valueOf(10));

      // orElse will return -1 being default value
      Integer value = valueOptional.orElse(Integer.valueOf(-1));

      System.out.println(value);

      //  orElse will return the underlying value
      Integer value1 = valueOptional1.orElse(Integer.valueOf(-1));

      System.out.println(value1);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

-1
10

新的日期時間 API

Java 8 引入了一個新的日期時間 API,它是執行緒安全的,支援時區,並具有多個直接處理日期操作的方法。早期的日期時間 API 不是執行緒安全的,在併發問題中,在使用日期時可能會出現問題。新的日期時間 API 使用不可變結構,沒有 setter 方法,因此使 API 更安全。新的 API 在設計時考慮了時區和特定領域的需要。

Java 8 在 java.time 包下引入了一個新的日期時間 API。以下是 java.time 包中引入的一些重要類。

  • Local − 簡化的日期時間 API,沒有時區處理的複雜性。

  • Zoned − 用於處理各種時區的專用日期時間 API。

示例 - 使用日期時間 API

在這個例子中,我們使用 oofNullable() 方法建立了兩個 Optional 類例項,該方法允許將底層物件作為 null 傳遞,然後使用 orElse() 方法檢索值,如果底層物件為 null,則返回預設值。

package com.tutorialspoint;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZonedDateTime;

public class Tester {
   public static void main(String args[]) {
      // Get the current date and time
      LocalDateTime currentTime = LocalDateTime.now();
      System.out.println("Current DateTime: " + currentTime);

      LocalDate date1 = currentTime.toLocalDate();
      System.out.println("date1: " + date1);

      Month month = currentTime.getMonth();
      int day = currentTime.getDayOfMonth();
      int seconds = currentTime.getSecond();

      System.out.println("Month: " + month +", day: " + day +", seconds: " + seconds);

      ZonedDateTime date2 = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]");
      System.out.println("date2: " + date2);
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

Current DateTime: 2024-03-07T10:29:15.650806
date1: 2024-03-07
Month: MARCH, day: 7, seconds: 15
date2: 2007-12-03T09:45:30+05:00[Asia/Karachi]

Nashorn JavaScript 引擎

Nashorn 是一個非常強大且高效的 Javascript 引擎,它作為現有 javascript 引擎 Rhino 的替代品而引入。Nashorn 引擎號稱速度是 Rhino 的 2 到 10 倍,因為它可以直接將 JavaScript 程式碼編譯為位元組碼。Nashorn 引擎允許在 Java 檔案中執行執行 JavaScript 程式碼,我們甚至可以在 JavaScript 程式碼片段中執行 Java 程式碼。使用 Nashorn 引擎,引入了命令列工具 jjs 來在命令列工具中執行 javascript。

直接在命令提示符中執行 JavaScript

開啟控制檯,鍵入 jjs 並按 Enter 鍵。jjs 工具將開啟一個互動式會話。jjs 會話開啟後,我們可以執行 javascript 程式碼。完成後,鍵入quit() 並按 Enter 鍵退出 jjs 互動式會話並返回到命令提示符。

示例

C:\JAVA>jjs
jjs> print("Hello, World!")
Hello, World!
jjs> quit()
>>
C:\JAVA>

示例 - 在 Java 程式碼中使用 Javascript 程式碼

自 Java 6 以來,Java 就有一個 ScriptEngineManager 類,本例中使用它將 javascript 引擎載入為 ScriptEngine 例項。一旦引擎載入到 java 程式碼中,我們就可以呼叫eval() 方法來評估 Java 中的 JavaScript 程式碼。我們甚至可以在 javascript 程式碼片段中使用Java 變數

package com.tutorialspoint;

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

public class Tester {

   public static void main(String args[]) {
      // create the script engine manager   
      ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
      // load the Nashorn javascript engine
      ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");
		
      String message = "This is a message";
      String expression = "10 + 2";
      Integer result = null;
      
      try {
         // call the javascript function, pass a java variable	  
         nashorn.eval("print('" + message + "')");
         // call the javascript function and get the result back in java
         result = (Integer) nashorn.eval(expression);
         
      } catch(ScriptException e) {
         System.out.println("Error executing script: "+ e.getMessage());
      }
      System.out.println(result.toString());
   }
}

讓我們編譯並執行上面的程式,這將產生以下結果:

This is a message
12

Nashorn 引擎在 Java 11 中已棄用,在 Java 15 中已刪除,並由 GraalVM javascript 引擎取代。

廣告