2012-01-12 36 views
13

Tôi đã tự hỏi tại sao nó không được phép trong Java quá tải Foo(Object[] args) với Foo(Object... args), mặc dù chúng được sử dụng theo một cách khác?Tại sao nó không được phép trong Java để quá tải Foo (Object ...) với Foo (Object [])?

Foo(Object[] args){} 

được sử dụng như:

Foo(new Object[]{new Object(), new Object()}); 

trong khi hình thức khác:

Foo(Object... args){} 

được sử dụng như:

Foo(new Object(), new Object()); 

Có bất kỳ lý do đằng sau này?

+0

câu hỏi thú vị +1 – mKorbel

+1

Tôi có thể thiếu điều gì đó, nhưng tại sao bạn cần quá tải? Nếu bạn khai báo phương thức của bạn là 'void foo (Object ... args)' thì bạn có thể gọi nó bằng ** hoặc ** 'foo (new Object(), new Object())' ** hoặc ** 'foo (đối tượng mới [] {new Object(), new Object()}) 'và nhận được kết quả tương tự. Xem [câu hỏi liên quan này] (http://stackoverflow.com/questions/1656901/varargs-and-the-argument) để biết ví dụ. –

+0

vararg chỉ là một cờ để chữ ký phương thức chuyển đổi mảng được khai báo cuối cùng (như 'int []' hoặc 'Object []') thành kiểu vararg. Khác hơn thế - không có sự khác biệt giữa chữ ký của phương thức. Câu hỏi tương tự sẽ không thể quá tải phương thức 'private' và' public'. – bestsss

Trả lời

25

Điều này 15.12.2.5 Choosing the Most Specific Method nói về điều này, nhưng nó khá phức tạp. ví dụ. Chọn giữa Foo (Số ... ints) và Foo (Số nguyên ... ints)

Vì lợi ích của tính tương thích ngược, đây là những điều tương tự.

public Foo(Object... args){} // syntactic sugar for Foo(Object[] args){} 

// calls the varargs method. 
Foo(new Object[]{new Object(), new Object()}); 

ví dụ: bạn có thể xác định main() như

public static void main(String... args) { 

Một cách để làm cho họ khác nhau là để có một đối số trước khi varargs

public Foo(Object o, Object... os){} 

public Foo(Object[] os) {} 

Foo(new Object(), new Object()); // calls the first. 

Foo(new Object[]{new Object(), new Object()}); // calls the second. 

Họ không phải là giống hệt nhau. Sự khác biệt tinh tế là trong khi bạn có thể truyền một mảng tới một varargs, bạn không thể xử lý một tham số mảng như là một varargs.

public Foo(Object... os){} 

public Bar(Object[] os) {} 

Foo(new Object[]{new Object(), new Object()}); // compiles fine. 

Bar(new Object(), new Object()); // Fails to compile. 

Ngoài ra, biến thể phải là thông số cuối cùng.

public Foo(Object... os, int i){} // fails to compile. 

public Bar(Object[] os, int i) {} // compiles ok. 
+0

+1 lời giải thích hay. Có bất kỳ thông số kỹ thuật ngôn ngữ nào được viết cho điều này không? –

+0

:-) Câu trả lời hay nhất +1 – mKorbel

+0

Hãy xem [câu hỏi này] (http://stackoverflow.com/q/14937948/597657). –

3

Câu trả lời trực tiếp nhất cho câu hỏi là có cả hai khai báo sẽ tạo ra sự mơ hồ trong logic tra cứu phương pháp. Nếu bạn tuyên bố cả hai trong cùng một lớp, sẽ có không có cách nào để tìm ra phương pháp nào bạn muốn khi gọi thusly:

Object[] a = new Object[10]; 
Foo(a); // array or vararg? 

Và Java đòi hỏi rằng có luôn là một phương pháp cụ thể nhất cho mỗi gọi phương pháp. Đối với số lý do tại sao, xem câu trả lời của Peter.

+0

chúng là * chính xác * giống nhau, không mơ hồ, chúng không thể tồn tại trong cùng một lớp – bestsss

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