2014-04-08 17 views
6

Tôi muốn tạo một HashMap ánh xạ các loại lớp cụ thể cho một đối tượng mới cụ thể duy nhất.Làm thế nào để tạo một HashMap kiểu generic chung theo loại lớp?

Sau đó tôi muốn chuyển loại lớp và nhận tham chiếu đến đối tượng cụ thể đó. đơn giản ví dụ:

Map<Class<?>, ?> values = new HashMap<>(); 

public <T> t get(Class<T> type) { 
    return values.get(type); 
} 


//pet and car do not share any interface or parent class 
class Pet; 
class Car; 

//error: not applicable for arguments 
values.put(Pet.class, new Pet()); 
values.put(Car.class, new Car()); 

sử dụng:

values.get(Pet.class); 

Làm thế nào tôi có thể tạo ra một hashmap và tra cứu hàm tổng quát như vậy cho phù hợp?

+2

Bạn đang tìm kiếm ổi của [ 'ClassToInstanceMap'] (https://code.google.com/p/guava -thư viện/wiki/NewCollectionTypesExplained # ClassToInstanceMap)? –

+0

Tuyệt vời, có lẽ đây là những gì tôi đang cố gắng tái tạo lại;) – membersound

Trả lời

5

Bạn cần lưu trữ một số loại đối tượng, nếu bạn muốn có thể đặt bất kỳ thứ gì khác như Object trên bản đồ, hãy bắt đầu với điều này:

Map<Class<?>, Object> values = new HashMap<>(); 

Điều này phải được thực hiện theo cách này, bởi vì ? không phải là một đối tượng cụ thể, nhưng Object là, đối với loại bản đồ lưu trữ.

Vì vậy, các đoạn sau đây hoạt động, mà không cần cảnh báo:

Map<Class<?>, Object> values = new HashMap<>(); 
values.put(Pet.class, new Pet()); 
values.put(Car.class, new Car()); 

Bây giờ Bí quyết là để có được các đối tượng, chúng tôi làm điều đó như sau:

@SuppressWarnings("unchecked") 
private <T> T get(Class<T> clazz) { 
    return (T)values.get(clazz); 
} 

Bây giờ mục tiêu của bạn là để đảm bảo rằng bản đồ chứa các cặp không cung cấp lỗi khi chạy. Nếu bạn đặt một phiên bản new Car() với Car.class, thì bạn sẽ gặp lỗi.

Vì vậy, các mã ví dụ sau đây:

values = new HashMap<>(); 
    values.put(Pet.class, new Pet()); 
    values.put(Car.class, new Car()); 

    System.out.println("get(Pet.class).getClass() = " + get(Pet.class).getClass()); 
    System.out.println("get(Car.class).getClass() = " + get(Car.class).getClass()); 

sẽ in:

get(Pet.class).getClass() = class testproject8.Pet 
get(Car.class).getClass() = class testproject8.Car 
1

Bạn có thể sử dụng Object như kiểu giá trị:

Map<Class<?>, Object> values = new HashMap<>(); 

Bạn không biết loại các giá trị anyway.

Sau đó, nếu bạn muốn chắc chắn rằng đối tượng chèn qua put là của lớp đóng vai trò như chìa khóa, bạn có thể tạo safePut() theo cách sau:

public <T> T safePut(Class<T> key, T value) { 
    return (T) values.put(key, value); 
} 
2

Tôi nghĩ rằng bạn đang theo đuổi một container không đồng nhất . Không có cách nào dễ dàng để tạo một vùng chứa như vậy trong Java mà không có bất kỳ phôi rõ ràng nào.

Tôi nghĩ rằng cách dễ nhất là đặt bản đồ của bạn trong một lớp học -

public class Container { 
    private Map<Class<?>, Object> values = new HashMap<>(); 

    public <T> T put(Class<T> klass, T obj) { 
     return klass.cast(values.put(klass, obj)); 
    } 

    public <T> T get(Class<T> klass) { 
     return klass.cast(values.get(klass)); 
    } 
} 

Và sử dụng lớp như sau -

Container c = new Container(); 
c.put(Pet.class, new Pet()); 
c.put(Car.class, new Car()); 
Pet p = c.get(Pet.class); 
Các vấn đề liên quan