2012-05-17 39 views
46

Tôi đang cố gắng hiểu cách java xử lý với sự mơ hồ trong các cuộc gọi hàm. Trong đoạn mã sau, cuộc gọi đến method là mơ hồ, nhưng method2 không phải là !!!.Các phương thức java quá tải không rõ ràng với generics và varargs

Tôi cảm thấy cả hai đều mơ hồ, nhưng tại sao điều này lại biên dịch khi tôi nhận xét cuộc gọi đến method? Tại sao method2 cũng không rõ ràng?

public class A { 
    public static <K> List<K> method(final K arg, final Object... otherArgs) { 
     System.out.println("I'm in one"); 
     return new ArrayList<K>(); 
    } 

    public static <K> List<K> method(final Object... otherArgs) { 
     System.out.println("I'm in two"); 
     return new ArrayList<K>(); 
    } 

    public static <K, V> Map<K, V> method2(final K k0, final V v0, final Object... keysAndValues) { 
     System.out.println("I'm in one"); 
     return new HashMap<K,V>(); 
    } 

    public static <K, V> Map<K, V> method2(final Object... keysAndValues) { 
     System.out.println("I'm in two"); 
     return new HashMap<K,V>(); 
    } 

    public static void main(String[] args) { 
     Map<String, Integer> c = A.method2("ACD", new Integer(4), "DFAD"); 
     //List<Integer> d = A.method(1, "2", 3 ); 
    } 
} 

EDIT: này đã đưa ra trong ý kiến: Một số IDE báo cáo cả hai như là mơ hồ - IntelliJ và Netbeans cho đến nay. Tuy nhiên, nó biên dịch tốt từ dòng lệnh/maven.

+0

Tốt câu hỏi ... – Jivings

+0

Có lẽ nó sẽ làm tăng thời gian biên dịch nếu java kiểm tra cho các phương pháp không sử dụng – Joelmob

+0

@Joelmob tôi cảm thấy câu hỏi là tại sao 'method2' biên dịch khi nó có vẻ là cũng giống như mơ hồ như 'phương thức'. – Jivings

Trả lời

14

Một cách trực quan để kiểm tra xem method1 là cụ thể hơn so method2 là để xem liệu method1 thể được thực hiện bằng cách gọi method2 với các thông số tương tự

method1(params1){ 
    method2(params1); // if compiles, method1 is more specific than method2 
} 

Nếu có varargs, chúng tôi có thể cần phải mở rộng một vararg để 2 phương pháp có cùng số tham số.

Hãy kiểm tra hai method() đầu tiên trong ví dụ của bạn

<K> void method_a(K arg, Object... otherArgs) { 
    method_b(arg, otherArgs); //ok L1 
} 
<K> void method_b(Object arg, Object... otherArgs) { // extract 1 arg from vararg 
    method_a(arg, otherArgs); //ok L2 
} 

(trở lại các loại không được sử dụng trong việc xác định đặc hiệu, vì vậy họ bị bỏ qua)

Cả hai biên dịch, do đó mỗi là cụ thể hơn khác, do đó sự mơ hồ. Tương tự như vậy đối với các số method2() của bạn, chúng cụ thể hơn nhau. Do đó, lệnh gọi tới method2() không rõ ràng và không được biên dịch; nếu không thì đó là lỗi trình biên dịch.


Vì vậy, đó là những gì spec nói; nhưng nó có thích hợp không? Chắc chắn, method_a trông cụ thể hơn method_b. Trên thực tế, nếu chúng ta có một loại bê tông thay vì K

void method_a(Integer arg, Object... otherArgs) { 
    method_b(arg, otherArgs); // ok 
} 
void method_b(Object arg, Object... otherArgs) { 
    method_a(arg, otherArgs); // error 
} 

sau đó chỉ method_a là cụ thể hơn so method_b, không phải ngược lại.

Sự khác biệt phát sinh từ phép thuật suy luận kiểu. L1/L2 gọi một phương thức chung mà không có đối số kiểu rõ ràng, do đó trình biên dịch cố gắng suy ra các đối số kiểu. Mục tiêu của thuật toán suy luận loại là tìm đối số loại sao cho mã biên dịch! Không có gì ngạc nhiên khi biên dịch L1 và L2. L2 thực sự suy ra là this.<Object>method_a(arg, otherArgs)

Suy luận loại cố đoán phỏng đoán của lập trình viên, nhưng đôi khi phải đoán là sai. ý định thực sự của chúng tôi là thực sự

<K> void method_a(K arg, Object... otherArgs) { 
    this.<K>method_b(arg, otherArgs); // ok 
} 
<K> void method_b(Object arg, Object... otherArgs) { 
    this.<K>method_a(arg, otherArgs); // error 
} 
+0

Cảm ơn bạn đã kiểm tra trực quan .. nhưng nó không trả lời câu hỏi. Câu hỏi đặt ra là tại sao lời gọi phương thức ** không thành công ** nhưng phương thức 2 ** **. – Chip

+2

từ phân tích, gọi hàm 'method2' là mơ hồ vì thiếu phương thức * cụ thể nhất *. do đó nó là một lỗi trình biên dịch. – irreputable

+0

Nếu bạn làm rõ điều đó trong câu trả lời .. Tôi sẽ chấp nhận nó. – Chip

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