Java 8 là gì

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:
  • Java 1.0: Bắt đầu một ngôn ngữ lập trình.
  • Java 1.1, 1.2, 1.3, 1.4 về mặt cú pháp và tính năng không có nhiều thay đổi lớn.
  • Java 1.5 [Hay còn gọi là Java 5] đã có những thay đổi lớn, với việc đưa vào một vài khái niệm.
    • Generic
    • Autoboxing/Unboxing
    • Nâng cấp tính năng cho vòng lặp for ["foreach"].
    • Các kiểu liệt kê có tính an toàn [Type-safe enumerations].
    • Varargs
    • Nhập khẩu tĩnh [Static import]
    • Metadata
  • Java 6,7 không có nhiều thay đổi lớn về mặt ngôn ngữ.
  • Java 8 có một sự thay đổi lớn về mặt ngôn ngữ. Với việc đưa vào một vài khái niệm và tính năng:
    • Phương thức mặc định cho interface [Default interface methods]
    • Biểu thức Lambda [Lambda expressions]
    • Method references
    • Annotation có thể lặp [Repeatable annotations]
    • Stream
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.
Xem thêm:
  • So sánh và sắp xếp trong Java
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 fruits = Arrays.asList["Grapefruit", "Apple", "Durian", "Cherry"]; // Sử dụng phương thức tiện ích của Collections // để sắp xếp lại danh sách trên. // Cung cấp một Comparator [Bộ so sách]. Collections.sort[fruits, new Comparator[] { @Override public int compare[String o1, String o2] { return o1.compareTo[o2]; } }]; for [String fruit : fruits] { System.out.println[fruit]; } } }
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 fruits = Arrays.asList["Grapefruit", "Apple", "Durian", "Cherry"]; // Sử dụng phương thức tiện ích của Collections để sắp xếp lại danh sách trên. // Cung cấp một Comparator [bộ so sánh] cho tham số thứ 2 của phương thức. // Vì Comparator là interface có duy nhất 1 phương thức. // ==> Có thể viết ngắn gọn với biểu thức Lambda. // Không cần viết tên interface, // Không cần viết tên phương thức. Collections.sort[fruits, [String o1, String o2] -> { return o1.compareTo[o2]; }]; for [String fruit : fruits] { System.out.println[fruit]; } } }
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 { T convert[F from]; }
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 converter = new Converter[] { @Override public Integer convert[String from] { return Integer.parseInt[from]; } }; // ==> 100 Integer value = converter.convert["0100"]; System.out.println["Value = " + value]; } }
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. Converter converter1 = [String from] -> { return Integer.parseInt[from]; }; // ==> 100 Integer value1 = converter1.convert["0100"]; System.out.println["Value1 = " + value1]; // Hoặc đơn giản hơn: Converter converter2 = [from] -> Integer .parseInt[from]; // ==> 200 Integer value2 = converter2.convert["00200"]; System.out.println["Value2 = " + value2]; // Nếu phương thức chỉ có một tham số, có thể bỏ qua []. Converter converter3 = from -> Integer .parseInt[from]; // ==> 300 Integer value3 = converter3.convert["00300"]; System.out.println["Value3 = " + value3]; } }

5- 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 { // Phương thức chấp nhận một tham số đầu vào // và không trả về gì cả. void accept[T t]; }
Sử dụng method List.forEach[Consumer]:
// java.util.List extends java.util.Collection [extends Iterable] // Interface java.util.Iterable: default void forEach[Consumer

Bài Viết Liên Quan

Chủ Đề