2010-09-21 33 views
8
public static void main(String[] args) { 
    Map<String, Map<Long, List<String>>> map = getHashMap(); 
} 

static <K,V> Map<K,V> getHashMap() 
{ 
    return new HashMap<K, V>(); 
} 

Tôi thấy mã tương tự trong google ổi (như phương pháp nhà máy) để tạo các phiên bản Hashmap mà không đề cập đến các loại generic.I không hiểu cách nhận dạng chung của chương trình trên. Tôi có nghĩa là làm cách nào để function getHashMap hiểu loại bản đồ vì tôi không truyền bất kỳ thông tin kiểu nào cho hàm.Loại chung được suy luận như thế nào ở đây?

Trả lời

6

Chức năng getHashMap không phải suy ra các loại. Đó là tại trang web gọi rằng javac được yêu cầu bởi Java Language Spec để suy ra rằng các loại đồng ý (15.12.2.7 Inferring Type Arguments Based on Actual Arguments).

Tôi tin rằng kế hoạch hiện tại là (vẫn) cho JDK7 để hỗ trợ nhà điều hành kim cương, do đó, loại điều này sẽ làm việc với new quá, mặc dù với một chút rõ ràng là vô nghĩa cú pháp.

Map<String, Map<Long, List<String>>> map = new HashMap<>(); 
                 ^^diamond 
+1

Bạn có thể giải thích một chút không. – Emil

+1

@Emil Về cái gì? –

+1

@Tom: Ý bạn là javac sẽ suy ra loại. Bạn có thể giải thích cách hoạt động của nó trong các bước. – Emil

1

Ở mức bytecode, phương thức sẽ có bộ mô tả chỉ có một phương thức có tên getHashMap, không có đối số và trả về Bản đồ (không có generics).

Sau đó, khi trình biên dịch phân tích dòng Map<String, Map<Long, List<String>>> map = getHashMap();, và nó sẽ nói, ok, tôi cần có một biến với kiểu khai báo là Map<String, Map<Long, List<String>>>, nhưng để thực sự có được cá thể tôi cần gọi phương thức. Tại thời điểm này, công việc của trình biên dịch là kiểm tra xem kiểu trả về của phương thức có khớp với kiểu khai báo của biến mà bạn gán cho kết quả đó không. Vì vậy, nó sẽ kiểm tra nếu String khớp với K và nếu Map<Long, List<String>> khớp với V, chúng sẽ làm như vậy, vì vậy nó xem xét việc gán là an toàn và tạo mã byte cơ bản sử dụng biến Bản đồ (không có generics).

Nếu bạn đã có thể tuyên bố phương pháp của bạn như:

static <K extends Number,V> Map<K,V> getHashMap() 
{ 
    return new HashMap<K, V>(); 
} 

khi phân tích sự phân công, trình biên dịch sẽ thấy rằng String không phù hợp K extends Number, sẽ ném một lỗi biên dịch, và sẽ không tạo ra bytecode cho nhiệm vụ đó.

1
class XX 
    static <T> T foo(){ return null; } 

String s = XX.foo(); 
Integer i = XX.foo(); 

Java infers T là String trong trường hợp thứ nhất, Integer in the 2nd case.

"suy luận" nghĩa là gì? Nó có nghĩa là Java đoán rằng trong hai câu lệnh, lập trình viên muốn nhất là T == String trong trường hợp thứ nhất, T == Integer cho trường hợp thứ 2, là một người tốt, Java có những dự đoán này là thực tế, và lập trình viên không phải tự xác định Ts

String s = XX.<String> foo(); 
    Integer i = XX.<Integer>foo(); 

Nhưng thực sự, Java dictates rằng sự trở lại loại T phải được xác định như thế.

Tôi thấy điều này rất cá, không chắc chắn lý do đằng sau thiết kế là gì. Có lẽ, khi (nếu) Java cho biết thêm loại reifiable (tức là lớp thực sự của T hiện có sẵn tại thời gian chạy), thiết kế ý nghĩa hơn:

class XX 
    static <T> T foo(){ return new T(); } 

String s = XX.foo(); 
Integer i = XX.foo(); 

tôi vẫn không thích thực tế là loại một phương pháp phụ thuộc vào ngữ cảnh.

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