2012-07-19 27 views
7

Tôi cố gắng để thực hiện cuộc gọi phương pháp như thế này,Làm thế nào để có được lớp với Generics loại trong Java

public class GenericsTest<T> { 

    public static <T> Map<String, T> createMap(Class<? extends Map<String, T>> clazz) { 
     return null; 
    } 

    public static void main(String[] argv) { 
     Map<String, Integer> result = createMap(TreeMap.class); 
    } 
} 

Nhưng tôi nhận được lỗi này,

<T>createMap(java.lang.Class<? extends java.util.Map<java.lang.String,T>>) in test.GenericsTest<T> cannot be applied to (java.lang.Class<java.util.TreeMap>) 

Làm thế nào để khắc phục vấn đề này?

+0

Bạn không thể do loại xóa. Đặc biệt, chữ ký phương thức không có ý nghĩa bởi vì bạn đang cố gắng lấy 'T' ra mặc dù bạn đang tham gia vào một' Lớp' cho một 'Bản đồ' với tham số giá trị là' T'. Bạn sẽ không bao giờ có thể có được kiểu lồng nhau mà không có một cá thể hiện có của đối tượng. (Bạn có thể truyền vào '(new HashMap ()). GetClass()', nhưng bạn vẫn không thể lấy 'Integer' trở lại phương thức đó). – pickypg

+0

createMap() là từ một thư viện chúng tôi sử dụng. Phải có cách gọi phương thức đó. –

+0

Tôi đặt câu hỏi tính hợp pháp của đối tượng được trả về. Nó được cho là trả về một cá thể của tham số value, 'T', khi được chuyển trong' Lớp' cho một 'Bản đồ', và tên phương thức là' createMap'. Không ai trong số đó có ý nghĩa gì cả. – pickypg

Trả lời

3
Map<String, Integer> instance = new TreeMap<String, Integer>(); 

@SuppressWarnings("unchecked") 
Map<String, Integer> map = 
    createMap((Class<? extends Map<String, Integer>>)instance.getClass()); 

map.put("x", 1); 

System.out.println("THIS IS x: " + map.get("x")); 

này một cách thích hợp sẽ in ra 1. Việc thực hiện phương pháp này là nhiều khả năng

try 
{ 
    return clazz.newInstance(); 
} 
catch (Exception e) 
{ 
    throw new RuntimeException(e); 
} 

Một thực hiện tốt hơn các API của họ sẽ để họ yêu cầu bạn cho các loại hình, T, và cho họ trả lại số Map trong lựa chọn của họ thay vì yêu cầu bạn cung cấp tất cả chi tiết. Nếu không, miễn là họ không được điền vào Map với bất kỳ dữ liệu, bạn có thể nhanh chóng một Map với đối số kiểu generic mình như vậy:

public static <T> Map<String, T> getMap() 
{ 
    return new TreeMap<String, T>(); 
} 

Sau đó bạn có thể truy cập mà không có cảnh báo:

// note the lack of type arguments, which are inferred 
Map<String, Integer> instance = getMap(); 

// alternatively, you could do it more explicitly: 
// Map<String, Integer> instance = ClassName.<Integer>getMap(); 

có thực sự không có lý do để họ yêu cầu bạn cho các loại Class của Map bạn ngoại trừ việc cung cấp cho bạn trở lại một kết hợp chính xác để thực hiện (ví dụ, nếu bạn dính vào một HashMap, sau đó bạn sẽ liên lạc lại một HashMap, và nếu bạn dính vào một TreeMap, sau đó bạn sẽ quay lại TreeMap). Tuy nhiên, tôi nghi ngờ rằng TreeMap sẽ mất bất kỳ Comparator nào mà nó được xây dựng và vì đó là trường bất biến (final) của TreeMap, thì bạn không thể sửa lỗi đó; điều đó có nghĩa là Map không giống nhau trong trường hợp đó, cũng không phải là khả năng bạn muốn.

Nếu chúng được điền vào số Map với dữ liệu, thì điều đó thậm chí còn ít ý nghĩa hơn. Bạn luôn có thể vượt qua trong trường hợp của số Map để điền hoặc trả lại số Map mà bạn có thể chỉ cần bọc (ví dụ: new TreeMap<String, Integer>(instance);) và họ phải biết số nào Map cung cấp tiện ích nhiều nhất cho dữ liệu.

+0

Điều này chạy nhưng với cảnh báo không được chọn. Phải có cách gọi phương thức này mà không cần cảnh báo. Đó là toàn bộ mục đích của việc sử dụng Generics. –

+0

Bạn đúng về mục đích này, nhưng Java có các generics giới hạn vì Loại Erasure, gây ra vấn đề này; có những hạn chế đối với những gì bạn có thể làm mà không phải coax trình biên dịch vào làm việc đó cho bạn. Đó có lẽ là tính năng ít được yêu thích nhất của tôi về Java bởi vì nó sẽ là khó khăn nhất để họ sửa chữa hoặc thay thế. .NET có một hệ thống generics linh hoạt hơn nhiều vì chúng không bị lãng quên trong thời gian chạy. Sau khi biên dịch, truy cập bản đồ đó sẽ trở thành '(Integer) map.get (" x ")' bởi vì kiểu trả về thực sự là 'Object'. – pickypg

Các vấn đề liên quan