Java 8 là gì
Ngày đăng:
29/01/2022
Trả lời:
0
Lượt xem:
164
Show
1- Giới thiệu
Từ khi Java ra đời và sự nâng cấp về mặt cú pháp và các tính năng, có vài dấu mốc thực sự quan trọng:
Trong tài liệu này tôi sẽ giới thiệu với các bạn về các tính năng và cú pháp của Java 8.
2- Phương thức mặc định cho Interface
Java 8 cho phép bạn thêm một method không trừu tượng vào interface bằng cách sử dụng từ khóa default. Các method này được hiểu như các phương thức mở rộng. Đây là ví dụ đầu tiên của bạn:
Formula.java
package org.o7planning.tutorial.j8.itf;
public interface Formula {
// Khai báo một phương thức trừu tượng.
double calculate(int a);
// Khai báo một phương thức không trừu tượng.
// Sử dụng từ khóa default.
// (Hàm tính căn bậc 2 của một số).
default double sqrt(int a) {
return Math.sqrt(a);
}
}
Và lớp FormulaImpl thực hiện interface Formula.
FormulaImpl.java
package org.o7planning.tutorial.j8.itf;
// Một lớp thi hành interface Formula.
public class FormulaImpl implements Formula {
// Chỉ cần thực hiện phương thức trừu tượng của Formula.
@Override
public double calculate(int a) {
return a * a - a;
}
}
FormulaTest.java
package org.o7planning.tutorial.j8.itf;
public class FormulaTest {
public static void main(String[] args) {
Formula formula = new FormulaImpl();
// ==> 5
double value1 = formula.sqrt(25);
System.out.println("Value1 = " + value1);
// ==> 600
double value2 = formula.calculate(25);
System.out.println("Value2 = " + value2);
}
}
3- Functional Interface (Interface tính năng)
Java 8 coi các Interface có duy nhất một method trừu tượng là các Functional Interface. Bạn có thể sử dụng annotation @FunctionalInterface để đánh dấu một interface của bạn là Functional Interface, điều này không bắt buộc, tuy nhiên trình biên dịch của Java sẽ thông báo lỗi cho bạn nếu vô tình thêm một method trìu tượng khác nữa vào interface có đánh dấu bởi annotation này.
Dưới đây là một số ví dụ thực hành với @FunctionalInterface:
Ví dụ dưới đây là một FunctionalInterface hợp lệ vì có duy nhất một method trừu tượng.
Foo.java
package org.o7planning.tutorial.j8.funcitf;
@FunctionalInterface
public interface Foo {
void something();
default void defaultMethod() {
System.out.println("..");
}
}
Không hợp lệ:
Hợp lệ:
Không hợp lệ:
Hợp lệ:
4- Biểu thức Lambda
Trước hết chúng ta xem lại cách Java phiên bản trước 8 sắp xếp một tập hợp có sẵn.
SortBefore8Example.java
package org.o7planning.tutorial.j8.lambda;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortBefore8Example {
public static void main(String[] args) {
// Một danh sách các loại quả.
List
Kết quả khi chạy ví dụ trên:
Apple
Cherry
Durian
Grapefruit
Java 8 coi các interface chỉ có duy nhất một method là các interface tính năng (Functional Interface). Và đó ý tưởng để khi thi hành interface này bạn chỉ cần viết method triển khai method trừu tượng duy nhất đó. Comparator là một interface có duy nhất một method, và nó là một Functional Interface. Bạn có thể viết lại ví dụ trên với cú pháp Lambda của Java 8:
SortJava8Example.java
package org.o7planning.tutorial.j8.lambda;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SortJava8Example {
public static void main(String[] args) {
// Một danh sách các loại quả.
List
Trong một khối lệnh nếu chỉ có một lệnh duy nhất, bạn có thể bỏ đi { }, khi đó đoạn code trên bạn có thể viết ngắn hơn:
Collections.sort(fruits, (String o1, String o2) -> o1.compareTo(o2) );
Thậm chí trình biên dịch (Compiler) của Java đủ thông minh để nhận thức được kiểu phần tử trong tập hợp của bạn cần sắp xếp là kiểu gì, trong ví dụ này là kiểu String, và vì vậy bộ so sánh (Comparator) chắc chắn là so sánh các kiểu dữ liệu String. Bạn có thể viết ngắn gọn hơn nữa.
Collections.sort(fruits, (o1, o2) -> o1.compareTo(o2));
Ví dụ khác với biểu thức Lambda.
Converter.java
package org.o7planning.tutorial.j8.lambda;
@FunctionalInterface
public interface Converter
Sử dụng interface Converter theo cách của Java trước phiên bản 8 (Không sử dụng biểu thức Lambda).
ConverterBefore8Example.java
package org.o7planning.tutorial.j8.lambda;
public class ConverterBefore8Example {
public static void main(String[] args) {
// Khởi tạo một đối tượng Converter.
Converter
Sử dụng biểu thức Lambda của Java 8:
ConveterJava8Example.java
package org.o7planning.tutorial.j8.lambda;
public class ConveterJava8Example {
public static void main(String[] args) {
// Converter là một FunctionalInterface
// Sử dụng cú pháp của Java 8 (Lambda)
// Trong trường hợp: Tạo đối tượng trực tiếp từ FunctionalInterface.
Converter5- Functional Interface API
Java 8 xây dựng sẵn một số lượng khá lớn các Functional Interface, chúng nằm trong package java.util.function, tại đây tôi sẽ hướng dẫn bạn sử dụng một số Interface đó, để hiểu hơn về biểu thức Lambda và sự tiện dụng của chúng.
5.1- java.util.function.Consumer
Consumer là một Functional interface xây dựng sẵn của Java 8, nó có một method trìu tượng duy nhất chấp nhận một tham số đầu vào, và method này không trả về gì cả.
Consumer.java
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Consumer
Sử dụng method List.forEach(Consumer):
// java.util.List extends java.util.Collection (extends Iterable)
// Interface java.util.Iterable:
default void forEach(Consumer action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
ConsumerExample.java
package org.o7planning.tutorial.j8.api;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class ConsumerExample {
// Sử dụng phương thức List.forEach(Consumer) với cú pháp của Java < 8.
// In ra danh sách các phân tử của List.
public static void beforeJ8() {
List5.2- java.util.function.Predicate
Predicate là một Functional interface xây dựng sẵn của Java 8, nó có một method trừu tượng duy nhất chấp nhận một tham số đầu vào, và method trả về giá trị boolean (true/false). Method này dùng để đánh giá tham số đầu vào phù hợp với một logic gì đó hay không.
Predicate.java
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Predicate
Ví dụ sau đây sẽ lọc một danh sách các tự nhiên và in ra danh sách các số lẻ, sử dụng Predicate theo cách Java8, và trước Java8.
PredicateExample.java
package org.o7planning.tutorial.j8.api;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class PredicateExample {
// Sử dụng phương thức Stream.filter(Predicate5.3- java.util.function.Function
Function là một Functional interface xây dựng sẵn của Java 8, nó có một method trừu tượng duy nhất chấp nhận một tham số đầu vào, và method trả về một đối tượng khác.
Function.java
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Function
Ví dụ: Cho một danh sách các String, in ra các String trong tập hợp dưới dạng chữ hoa.
FunctionExample.java
package org.o7planning.tutorial.j8.api;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
public class FunctionExample {
// Sử dụng phương thức Stream.map(Function) với cú pháp của Java < 8.
// In ra danh sách các phần tử của List.
public static void beforeJ8() {
List
Một số Functional interface tương tự:
@FunctionalInterface
public interface IntFunction
5.4- java.util.function.Supplier
Supplier là một Functional interface xây dựng sẵn của Java 8, nó có một method trừu tượng duy nhất không tham số, và trả về một đối tượng.
Supplier.java
package java.util.function;
@FunctionalInterface
public interface SupplierSupplierExample.java
package org.o7planning.tutorial.j8.api;
import java.util.function.Supplier;
public class SupplierExample {
// Một phương thức với tham số là Supplier
Một số Functional Interface tương tự:
6- Method reference
Đó là một tính năng có liên quan đến biểu thức Lambda. Nó cho phép bạn tham chiếu tới một method hoặc một constructor mà không cần thực thi chúng. Method references và Lambda là tương tự nhau, vì cả hai yêu cầu một loại mục tiêu là một Functional Interface tương thích.
Java 8 cho phép bạn truyền một tham chiếu của một method hoặc một constructor thông qua việc sử dụng từ khóa ::
Trước khi đi vào vấn đề hãy xem một ví dụ đơn giản.
MyFunction là một Functional Interface. Nó định nghĩa ra một method có 2 tham số int a và b, và trả về giá trị int.
MyFunction.java
package org.o7planning.tutorial.j8.mref;
@FunctionalInterface
public interface MyFunction {
// Phương thức này có 2 tham số a, b và trả về kiểu int.
public int doSomething(int a, int b);
}
MyMathUtils là class có 2 method tĩnh để tính tổng và tính hiệu 2 số int.
MyMathUtils.java
package org.o7planning.tutorial.j8.mref;
public class MyMathUtils {
// Phương thức này có 2 tham số a, b và trả về kiểu int.
// Phương thức này khác tên,
// nhưng có cấu trúc giống với MyFunction.doSomething(int,int).
public static int sum(int a, int b) {
return a + b;
}
public static int minus(int a, int b) {
return a - b;
}
}
MethodReferenceExample.java
package org.o7planning.tutorial.j8.mref;
public class MethodReferenceExample {
// Tham số thứ 3 của phương thức này là MyFunction (Functional Interface).
// Khi sử dụng phương thức này:
// Bạn có thể truyền tham chiếu của một phương thức cho tham số thứ 3.
// (Các phương thức phải cùng kiểu với MyFunction).
public static int action(int a, int b, MyFunction func) {
return func.doSomething(a, b);
}
public static void main(String[] args) {
int a = 100;
int b = 30;
// Truyền vào tham chiếu của phương thức MyMathUtils.sum.
int c = action(a, b, MyMathUtils::sum);// ==> 130.
System.out.println("c = " + c);
// Truyền vào tham chiếu của phương thức MyMathUtils.minus.
int d = action(a, b, MyMathUtils::minus);// ==> 70
System.out.println("d = " + d);
// Truyền vào tham chiếu của phương thức Math.subtractExact.
int e = action(a, b, Math::subtractExact);// ==> 70
System.out.println("e = " + e);
// Truyền vào tham chiếu của phương thức Math.min.
// Pass the reference of Math.min method.
int f = action(a, b, Math::min);// ==> 30
System.out.println("f = " + f);
}
}
Thông qua ví dụ ở trên bạn có thể thấy cách thức sử dụng từ khóa :: để truyền vào tham chiếu của một method. Nếu bạn gọi một method, mà trong method đó có một tham số là Functional Interface, bạn có thể truyền vào một tham chiếu method có cấu trúc giống với cấu trúc method định nghĩa trong Functional interface.
7- Contructor reference
Bạn có thể sử dụng MyClass::new để tham chiếu tới một constructor. Điều này rất giống với tham chiếu tới một method tĩnh. Khác biệt giữa 2 cái đó là tên method của tham chiếu constructor là new. Hãy xem ví dụ sau:
|