Tất cả những gì chúng ta biết là " Tất cả các thể hiện của một lớp bất kỳ đều có chung đối tượng java.lang.Class của loại lớp đó "
ví dụ)
Student a = new Student();
Student b = new Student();
Đó a.getClass() == b.getClass()
là sự thật.
Bây giờ giả sử
Teacher t = new Teacher();
không có thuốc generic dưới đây là có thể.
Class studentClassRef = t.getClass();
Nhưng điều này là sai bây giờ ..?
ví dụ) public void printStudentClassInfo(Class studentClassRef) {}
có thể được gọi vớiTeacher.class
Điều này có thể tránh được bằng cách sử dụng thuốc generic.
Class<Student> studentClassRef = t.getClass(); //Compilation error.
Bây giờ T là gì ?? T là tham số kiểu (còn gọi là biến kiểu); được phân cách bằng dấu ngoặc nhọn (<>), theo tên lớp.
T chỉ là một ký hiệu, giống như một tên biến (có thể là bất kỳ tên nào) được khai báo trong khi viết tệp lớp. Sau đó, T sẽ được thay thế bằng
tên Class hợp lệ trong quá trình khởi tạo (HashMap<String> map = new HashMap<String>();
)
ví dụ) class name<T1, T2, ..., Tn>
Vì vậy, Class<T>
đại diện cho một đối tượng lớp của loại lớp cụ thể 'T
'.
Giả sử rằng các phương thức lớp của bạn phải làm việc với các tham số loại không xác định như dưới đây
/**
* Generic version of the Car class.
* @param <T> the type of the value
*/
public class Car<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Ở đây T có thể được sử dụng như là String
loại CarName
HOẶC T có thể được sử dụng làm Integer
kiểu như modelNumber ,
HOẶC T có thể được sử dụng như là Object
loại ví dụ xe hợp lệ .
Bây giờ ở đây ở trên là POJO đơn giản có thể được sử dụng khác nhau trong thời gian chạy.
Các bộ sưu tập, ví dụ) List, Set, Hashmap là những ví dụ tốt nhất sẽ hoạt động với các đối tượng khác nhau theo khai báo của T, nhưng một khi chúng ta đã khai báo T là String,
ví dụ) HashMap<String> map = new HashMap<String>();
Sau đó, nó sẽ chỉ chấp nhận các đối tượng thể hiện của String String.
Phương pháp chung
Các phương thức chung là các phương thức giới thiệu các tham số loại riêng của chúng. Điều này tương tự như khai báo một kiểu chung, nhưng phạm vi của tham số loại được giới hạn trong phương thức mà nó được khai báo. Các phương thức chung tĩnh và không tĩnh được cho phép, cũng như các hàm tạo lớp chung.
Cú pháp cho một phương thức chung bao gồm một tham số kiểu, bên trong dấu ngoặc nhọn và xuất hiện trước kiểu trả về của phương thức. Đối với các phương thức chung, phần tham số loại phải xuất hiện trước kiểu trả về của phương thức.
class Util {
// Generic static method
public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
}
Dưới đây <K, V, Z, Y>
là khai báo các kiểu được sử dụng trong các đối số phương thức nên trước kiểu trả vềboolean
ở đây.
Ở phía dưới; khai báo kiểu <T>
không bắt buộc ở cấp phương thức, vì nó đã được khai báo ở cấp lớp.
class MyClass<T> {
private T myMethod(T a){
return a;
}
}
Nhưng bên dưới là sai vì các tham số loại cấp K, V, Z và Y không thể được sử dụng trong ngữ cảnh tĩnh (phương thức tĩnh tại đây).
class Util <K, V, Z, Y>{
// Generic static method
public static boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
PHONG CÁCH GIÁ TRỊ KHÁC
class MyClass<T> {
//Type declaration <T> already done at class level
private T myMethod(T a){
return a;
}
//<T> is overriding the T declared at Class level;
//So There is no ClassCastException though a is not the type of T declared at MyClass<T>.
private <T> T myMethod1(Object a){
return (T) a;
}
//Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).
private T myMethod1(Object a){
return (T) a;
}
// No ClassCastException
// MyClass<String> obj= new MyClass<String>();
// obj.myMethod2(Integer.valueOf("1"));
// Since type T is redefined at this method level.
private <T> T myMethod2(T a){
return a;
}
// No ClassCastException for the below
// MyClass<String> o= new MyClass<String>();
// o.myMethod3(Integer.valueOf("1").getClass())
// Since <T> is undefined within this method;
// And MyClass<T> don't have impact here
private <T> T myMethod3(Class a){
return (T) a;
}
// ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
// Should be o.myMethod3(String.valueOf("1").getClass())
private T myMethod3(Class a){
return (T) a;
}
// Class<T> a :: a is Class object of type T
//<T> is overriding of class level type declaration;
private <T> Class<T> myMethod4(Class<T> a){
return a;
}
}
Và cuối cùng phương thức tĩnh luôn cần <T>
khai báo rõ ràng ; Nó sẽ không xuất phát từ cấp lớp Class<T>
. Điều này là do lớp T bị ràng buộc với thể hiện.
Cũng đọc Hạn chế về Generics
Ký tự đại diện và phân loại
loại đối số cho một phương thức chung