2011-09-08 20 views
5

Xin chào tôi có một phương thức sẽ trả về các kết quả khác nhau tùy thuộc vào loại.Kiểm tra bản sao chung?

Tôi có thể làm như thế này để kiểm tra loại chung.

public <T> T search(final String query){ 
T returnValue = null; 
if (returnValue instanceof String){ } 
if (returnValue instanceof Integer){ } 
if (returnValue instanceof MyObject){ } 

Nhưng tại sao tôi không thể làm như thế này?

public <T> T search(final String query){ 
T returnValue = null; 
if (T instanceof String){ } 
if (T instanceof Integer){ } 
if (T instanceof MyObject){ } 

Mã gọi.

String id = myObjcet.<String> search("select ..."); 

Trả lời

4

Java thực hiện generics "bằng cách xóa". Điều đó có nghĩa là tại thời điểm chạy có (gần như) không có kiến ​​thức về generics cả. Thay vào đó, trình biên dịch kiểm tra các generics, nhưng dưới trang bìa nó chuyển đổi mọi thứ thành Object (hoặc đến ranh giới generics gần nhất).

Nếu bạn dịch ngược phương pháp mà sử dụng javap, bạn sẽ thấy rằng nó đọc:

public Object search(... 

Mỗi tài liệu tham khảo để T được lấy ra.

Đây là một hạn chế nghiêm trọng của Generics trong Java, được phản ánh thường cũng trong các lớp JRE với cấu trúc như sau:

SomeClass<String> x = new SomeClass<String>(String.class); 

Trong trường hợp lặp lại thứ ba của String (String.class) là cần thiết bởi vì các nhà xây dựng cần phải biết nó đang hoạt động trên lớp nào.

Mô hình này, mặc dù là khủng khiếp, có thể giải quyết vấn đề của bạn.

Thông tin về generics thực sự có trong các tệp .class, dưới dạng siêu dữ liệu, chúng có thể được kiểm tra bằng cách sử dụng sự phản chiếu và ở một mức độ nào đó cũng được giải quyết. Tuy nhiên, điều này là không thể trong một trường hợp như của bạn, nhưng nó là ví dụ được sử dụng bởi ORMs trên danh sách getters. ví dụ, sử dụng Hibernate, một getter như thế này:

public List<Group> getGroups() { 

Có thể được kiểm tra bởi Hibernate để biết rằng danh sách được coi là tổ chức các cá thể của nhóm, điều chỉnh truy vấn tương ứng.

(Tuy nhiên, ngay cả khi generics không được thực hiện theo cách này, T không phải là một thể hiện, nó là một lớp, viết String instanceof String là bằng nhau sai.Nó nên nếu (T.equals (String.class)))

+0

Cảm ơn rất nhiều vì lời giải thích tuyệt vời này, tôi sẽ chấp nhận bạn trả lời ngay khi SO cho phép tôi. – Farmor

1

T bị xóa khi chạy. Nó chỉ có ở thời gian biên dịch. returnValue là biến - nó hiện diện trong thời gian chạy.

1
public <T> T search(Class<T> clazz, String query){ 
T returnValue = null; 
if (clazz==String.class){ } 
if (clazz==Integer.class){ } 
if (MyObject.clazz.isAssignableFrom(clazz){ } 


String id = myObjcet.search(String.class, "select ..."); 
Các vấn đề liên quan