Java: Kiểu suy luận (Type Inference)


Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên

Tổng quan

Trong các phương pháp generic, Suy luận Kiểu (Type Inference) giúp gọi một phương thức generic. Ở đây ta không cần chỉ định kiểu giữa các dấu ngoặc nhọn.

Suy luận kiểu cho phép trình biên dịch Java xác định các đối số kiểu làm cho lời gọi có thể áp dụng. Nó phân tích từng lệnh gọi phương thức và khai báo tương ứng để thực thi. Thuật toán suy luận xác định những điều sau:

  • Kiểu đối số.
  • Kiểu kết quả được trả về.
  • Kiểu đặc trưng nhất hoạt động với tất cả các đối số.

Các đối số kiểu cần thiết để gọi phương thức khởi tạo của một lớp generic có thể được thay thế bằng một tập hợp rỗng các tham số kiểu (<>) miễn là trình biên dịch cung cấp các đối số kiểu từ ngữ cảnh.

Ví dụ sau minh họa điều này:

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

Trong Java SE 7, kiểu tham số của hàm tạo có thể được thay thế bằng một tập hợp các tham số kiểu trống như được hiển thị trong ví dụ sau.

Map<String, List<String>> myMap = new HashMap<>();

Lưu ý - Tập trống (empty) các tham số kiểu là rất quan trọng để sử dụng suy luận kiểu tự động trong quá trình khởi tạo lớp generic.

Trong ví dụ sau, trình biên dịch tạo một cảnh báo chuyển đổi không được kiểm tra:

Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning

Trong đoạn mã trên, hàm tạo HashMap() đề cập đến kiểu thô HashMap.

Từ Java SE 7 hỗ trợ suy luận kiểu giới hạn để tạo thể hiện generic. Suy luận kiểu chỉ có thể được sử dụng nếu kiểu tham số hóa của hàm tạo là rõ ràng trong ngữ cảnh. Ví dụ sau minh họa điều này.

List<String> list = new ArrayList<>(); list.add("A");
// The following statement should fail since addAll expects
// Collection<? extends String>
 list.addAll(new ArrayList<>());

Đoạn mã trên không biên dịch.

Lưu ý - Nên sử dụng dấu ngoặc nhọn cho khai báo biến.

Ví dụ trên khi biên dịch được thực thi.

// The following statements compile:
List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);

Các hàm tạo generic của các lớp Generic và Non-Generic

Các hàm tạo có thể khai báo các tham số kiểu chính thức của riêng chúng trong cả hai lớp generic và non-generic. Ví dụ sau minh họa điều này.

class MyClass<X> {
  <T> MyClass(T t) {
// ...
  }
}

Ví dụ sau cho thấy sự khởi tạo của lớp MyClass.

new MyClass<Integer>("")

Lệnh trên hợp lệ trong Java SE 7 và các bản phát hành trước. Trong lệnh trên:

  • Tạo một thể hiện của kiểu tham số hóa MyClass<Integer>.
  • Chỉ định kiểu Integer cho tham số kiểu chính thức, X, của lớp generic MyClass<X>.
  • Hàm tạo cho lớp generic chứa một tham số kiểu chính thức là T.
  • Trình biên dịch hiểu kiểu String cho tham số kiểu chính thức T, của hàm tạo của lớp generic này. Điều này là do tham số thực sự của hàm tạo là một đối tượng String.

Trình biên dịch trong Java SE 7 hiểu các tham số kiểu thực tế của lớp generic được khởi tạo bằng dấu ngoặc nhọn. Trước Java SE 7, các trình biên dịch hiểu các tham số kiểu thực tế của các hàm tạo generic giống như các phương thức generic hiểu.

Ví dụ sau hợp lệ cho Java SE 7.

MyClass<Integer> myObject = new MyClass<>("");

Trong lệnh trên, trình biên dịch hiểu:

  • Kiểu Integer dành cho tham số kiểu chính thức là X, của lớp generic MyClass<X>.
  • Kiểu String dành cho tham số kiểu chính thức T, của hàm tạo của lớp generic.

Những cải tiến trong Java SE 7

  • Dấu gạch dưới trong literal Number: Các ký tự dấu gạch dưới (_) có thể được thêm vào bất kỳ đâu giữa các chữ số trong một chữ số để tách các nhóm chữ số trong các chữ số. Chúng cải thiện khả năng đọc của mã lệnh.
  • Các chuỗi trong câu lệnh switch: Lớp String có thể được sử dụng trong biểu thức của lệnh switch.
  • Literal nhị phân: Trong Java SE 7 các kiểu literal có thể được xác định bằng cách sử dụng hệ thống số nhị phân. Lưu ý, các kiểu literal là kiểu byte, short, int và long. Để chỉ định một ký tự nhị phân, hãy thêm tiền tố 0b hoặc 0B vào số.
  • Cảnh báo và lỗi trình biên dịch tốt hơn với các tham số chính thức không thể kết nối lại : Trình biên dịch Java SE 7 tạo cảnh báo tại vị trí khai báo của phương thức varargs hoặc hàm tạo với tham số chính thức varargs không thể kết nối lại. Java SE 7 loại bỏ những cảnh báo này bằng cách sử dụng tùy chọn trình biên dịch -Xlint:varargs và các chú thích @SafeVarargs và @SuppressWarnings ({"uncheck ed", "varargs"}).
  • Suy luận kiểu cho việc tạo thể hiện generic: Các đối số kiểu bắt buộc có thể được thay thế để gọi hàm khởi tạo của một lớp generic với một tập hợp các tham số kiểu trống miễn là trình biên dịch cung cấp các đối số kiểu từ ngữ cảnh.
  • Bắt nhiều loại ngoại lệ: Một khối bắt đơn xử lý nhiều loại ngoại lệ. Người dùng có thể xác định các kiểu ngoại lệ cụ thể trong mệnh đề ném của một khai báo phương thức vì trình biên dịch thực hiện phân tích chính xác các ngoại lệ phát triển lại.
  • Câu lệnh try-with-resources: Khai báo một hoặc nhiều tài nguyên, là những đối tượng sẽ được đóng lại sau khi chương trình làm việc xong với chúng. Đối tượng triển khai interface java.lang.AutoClosable mới hoặc interface java.io.Closable có thể được sử dụng làm tài nguyên. Câu lệnh đảm bảo rằng mỗi tài nguyên được đóng ở cuối câu lệnh.

Lưu ý - các lớp java.io.InputStream, OutputStream, Reader, Writer, java.sql.Connection, Statement và ResultSet có thể thực thi interface AutoClosable và có thể được sử dụng làm tài nguyên trong câu lệnh try-with-resources.

» Tiếp: Collection và Generic
« Trước: Phương thức generic
Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên
Copied !!!