2013-03-12 41 views
19

Tôi có các lớp học lập trình nâng cao tại trường đại học của mình và tôi gặp một chút rắc rối khi hiểu mã này hoạt động như thế nào.Tính đa hình nâng cao trong Java

public final class GenericClass<T> { 
    private void overloadedMethod(Collection<?> o) { 
     System.out.println("Collection<?>"); 
    } 

    private void overloadedMethod(List<Number> o) { 
     System.out.println("List<Number>"); 
    } 

    private void overloadedMethod(ArrayList<Integer> o) { 
     System.out.println("ArrayList<Integer>"); 
    } 

    public void method(List<T> l) { 
     overloadedMethod(l); 
    } 

    public static void main(String[] args) { 
     GenericClass<Integer> test = new GenericClass<Integer>(); 
     test.method(new ArrayList<Integer>()); 
    } 
} 

Tại sao mã này in "Bộ sưu tập <? >"?

Trả lời

14

Tuyên bố method(List<T> l) không chỉ định bất kỳ giới hạn nào về loại T. Không có gì đảm bảo rằng T là Số hoặc một phân lớp của Số. Do đó, trình biên dịch chỉ có thể quyết định rằng phương thức này gọi là overloadedMethod(Collection<?> o).

Hãy nhớ rằng: sau khi biên dịch, thông tin về generics không còn có sẵn trong các tệp lớp.

+0

cảm ơn, câu trả lời của bạn giải thích thậm chí tại sao sau khi thay đổi 'overloadedMethod (Danh sách o) 'với' overloadedMethod (Danh sách o) 'chương trình in ra' Danh sách 'thay vì' Collection ' –

+0

sự điều quan trọng nhất là câu cuối cùng của bạn. Điều đó giải thích mọi thứ! –

+0

Câu trả lời khá hay, nhưng -1 để thu hút sự chú ý của bạn vào thực tế là khai báo 'GenericClass ' thay cho kết quả trong cùng một lời gọi tới 'overloadedMethod (Collection )'. Vì vậy, có cái gì khác đang xảy ra ở đây. –

-1

Bất cứ khi nào bạn định nghĩa một kiểu generic, một loại nguyên liệu tương ứng sẽ tự động cung cấp Phương pháp này

public void method(List<T> l) { 

} 

được thay thế với

public void method(List<Object> l) { 

} 

Nếu bạn đọc về các loại ký tự đại diện, bạn sẽ thấy rằng List<Number>List<Object> hoặc ArrayList<Integer>List<Object> không có bất kỳ mối quan hệ loại nào. List<Object> là một loại phụ của Collecion<?> do đó phương pháp này được gọi.

+0

Thực ra, lý do ở đây không đủ để trả lời câu hỏi. Trình biên dịch quyết định phương thức quá tải để gọi, điều này xảy ra * trước * loại xóa. –

-1

khi bạn đối phó với phương pháp quá tải bạn phải đặt ba khái niệm trong tâm trí của bạn:

  1. Mở rộng
  2. Boxing
  3. Var_args

vấn đề của bạn nằm ở điểm đầu tiên được mở rộng , trình biên dịch java ưu tiên cho từng khái niệm này theo thứ tự như chúng được liệt kê ở trên, vì vậy nó thích mở rộng và khi bạn gọi phương thức của mình là test.method(new ArrayList<Integer>()); trình biên dịch phát hiện rằng ArrayList<Integer>() có thể được mở rộng thành Collection<?> và vì nó có mức độ ưu tiên cao nhất, hãy gọi các phiên bản này và bỏ qua các phiên bản khác Lưu ý: nếu bạn thay đổi khai báo hai phương thức còn lại thành private void overloadedMethod(ArrayList<?> o)private void overloadedMethod(List<?> o) trình biên dịch cũng sẽ gọi số Collection<?> phiên bản bởi vì đó là ưa thích một

+0

No. nếu private void overloadedMethod (Danh sách o) {// thì phương thức List sẽ được gọi qua Bộ sưu tập . – AmitG

+0

bạn đã thử nó chưa ?? –

+0

"@Java Player: Tôi luôn ghé thăm diễn đàn này trong văn phòng và cập nhật bản thân càng sớm càng tốt. BTW bạn đã thử chưa? Nếu bạn cố gắng, vui lòng bỏ kết luận tại đây – AmitG

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