2011-10-02 32 views
8

Tôi có một câu hỏi liên quan đến đoạn mã sau:vấn đề Java với var-args và boxing

class VarArgsTricky { 
    static void wide_vararg(long... x) { 
     System.out.println("long..."); 
    } 

    static void wide_vararg(Integer... x) { 
     System.out.println("Integer..."); 
    } 

    public static void main(String[] args) { 
     int i = 5; 
     wide_vararg(i, i, i); // needs to widen and use var-args 
     Long l = 9000000000l; 
     wide_vararg(l, l); // prints sucessfully "long..." 
    } 
} 

Cuộc gọi đầu tiên wide_vararg thất bại trong việc biên dịch (nói rằng phương pháp này là ambigous) trong khi thứ hai chỉ biên dịch khỏe.

Bất kỳ giải thích nào về hành vi này? Cảm ơn!

+0

Nếu đây không chỉ là một thử nghiệm về quá tải, vui lòng đọc Hiệu quả Java SE: Mục 41 Sử dụng quá tải một cách thận trọng. – TJR

+0

Đây hoàn toàn là một thử nghiệm, chỉ để giải quyết một câu hỏi tiềm năng cho kỳ thi chứng chỉ OCPJP. –

Trả lời

1

Khi phương thức var-arg được gọi, các tham số được chuyển đổi thành một mảng thuộc loại đó tại thời gian biên dịch.

Trong lần gọi đầu tiên, các thông số được chuyển thành int []. Vì tất cả các mảng trong Java là các kiểu con trực tiếp của lớp Object, khái niệm mở rộng nguyên thủy không áp dụng trong trường hợp này, cả hai tình trạng quá tải trở nên áp dụng như nhau vì long [] và Integer [] ở cùng mức. Do đó sự mơ hồ

10

Các wide_vararg cuộc gọi đầu tiên là mơ hồ bởi vì trình biên dịch hoặc thể:

  • mở rộng int s để long s, và gọi phương thức đầu tiên wide_vararg, hoặc
  • autobox các int s để Integer s và gọi số thứ hai wide_vararg.

Nó không biết nó nên làm, tuy nhiên, do đó, từ chối biên dịch cuộc gọi phương thức không rõ ràng. Nếu bạn muốn gọi điện đầu tiên để biên dịch, hãy khai báo i dưới dạng Integer hoặc long, không phải là int.

+1

Theo K & B SCJP 6 cuốn sách mở rộng nhịp đập đấm bốc trong khi boxing beats var-args. Vì vậy, cuộc gọi đầu tiên nên chọn để mở rộng hơn là hộp số tự động. Nếu tôi được khai báo là một số nguyên thì nó cũng không biên dịch. Tất nhiên, công việc dài. Câu hỏi vẫn còn: tại sao nó không chọn mở rộng trên autoboxing? –

+0

Hm, bạn nói đúng. Tôi chưa chắc tại sao. Heck, nó có thể là một lỗi trình biên dịch. Dù có hay không varargs bị đánh bại bằng cách mở rộng hoặc đấm bốc là một câu hỏi không, mặc dù, vì không có sự lựa chọn không varargs. –

+1

Không có sự lựa chọn nào khác, đó là sự thật. Nó có thể là một số loại lỗi trình biên dịch hoặc một số tính năng kém được biết đến. Nó sẽ là thú vị để biết chính xác. –