Trước khi đi vào định nghĩa, nhắc lại 1 số kiến thức chung:
Generics
nghĩa là linh động, linh hoạt, tùy vào điều kiện A để làm việc X, tùy vào điều kiện B để làm việc Y. Đại khái là không cố định.
Generics
trong Java là parameterized types
, có nghĩa là bạn có thể tạo ra 1 class/interface/method mà có kiểu dữ liệu (data type) linh động và có thể truyền từ ngoài vào như parameter vậy. Khi đó, class/interface/method sẽ được gọi là generics class, generics method.
Đôi khi chúng ta viết 1 class hoặc 1 biến mà mục đích là 1 dạng template để phục vụ cho nhiều type khác nhau, chúng ta có xu hướng chọn type là Object
. Ví dụ:
id
có thể là String, Integer hoặc bất kỳ reference type nào
Vấn đề chính là kiểu viết này là bạn phải chấp nhận việc explicit casting
và như thế là bạn mất type safety
.
Bạn sẽ phải cast trước rồi mới gọi method như sau:
Và rất có thể bạn sẽ gặp phải Runtime Exception: ClassCastException.
Thay vì việc sử dụng Object
để làm type chung thì bạn có sử dụng Type Parameter để định nghĩa cho biến đó.
rồi bạn cho biết T
là gì trước khi gọi vào các method subString
hay intValue
. Điều tuyệt vời là bạn sẽ không bao giờ bị ClassCastException. Nếu bạn đã xác định T
là String, mà bạn lại assign Integer cho id
thì sẽ bị lỗi compile luôn.
Chốt lại: Generics giúp bạn “đẩy” lỗi từ Runtime (lúc program chạy) sang lúc compile time (lúc code), tìm bug sớm hơn, lúc chạy ít lỗi hơn.
Code không có generics
List numbers = new ArrayList(); numbers.add(123); numbers.add("abc"); for (int i = 0; i < numbers.size(); i++) { if ((Integer) numbers.get(i) > 10) //cast here System.out.println("greater than 10"); } /*Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer */