2008-10-06 35 views
5

xem xét chữ ký phương pháp sau đây:mảng Object trong chữ ký phương pháp

public fooMethod (Foo[] foos) { /*...*/ } 

public fooMethod (Foo... foos) { /*...*/ } 

Giải thích: Các cựu mất một mảng của Foo-đối tượng như một cuộc tranh cãi - fooMethod(new Foo[]{..}) - trong khi sau này lấy một số lượng đối số tùy ý của loại Foo, và trình bày chúng như là một mảng của Foo: s trong phương thức - fooMethod(fooObject1, fooObject2, etc...).

Java ném phù hợp nếu cả hai được xác định, tuyên bố rằng chúng là phương thức trùng lặp. Tôi đã làm một số công việc thám tử, và phát hiện ra rằng tuyên bố đầu tiên thực sự đòi hỏi một mảng rõ ràng của các đối tượng Foo, và đó là cách duy nhất để gọi phương thức đó. Cách thứ hai thực sự chấp nhận cả số lượng đối số Foo tùy ý VÀ cũng chấp nhận một mảng các đối tượng Foo.

Vì vậy, câu hỏi là, vì phương pháp thứ hai có vẻ linh hoạt hơn, có bất kỳ lý do nào để sử dụng ví dụ đầu tiên hoặc tôi đã bỏ lỡ bất kỳ điều gì quan trọng không?

+0

Không biết Java, đây là cú đâm trong bóng tối, nhưng tôi cho rằng đầu tiên là hiệu quả hơn, bởi vì: a) bạn sẽ chỉ chuyển một con trỏ xung quanh, và b) bạn sẽ chuyển một con trỏ đến phần tiếp giáp của bộ nhớ. –

+0

@monoxide: Không, cả hai biểu mẫu tạo ra bytecode gọi tương đương, cả hai biểu mẫu đều yêu cầu tạo một mảng để truyền. –

+0

Dạng thứ hai chỉ đơn giản là cú pháp đường cho lần đầu tiên. Vì vậy, fooMethod (mới Foo (1), mới Foo (2)) là ở đây giống với fooMethod (new Foo [] {new Foo (1), new Foo (2)}) –

Trả lời

12

Những phương pháp này thực sự giống nhau.

Tính năng này được gọi là varargs và nó là một tính năng trình biên dịch. Đằng sau hậu trường là dịch sang phiên bản cũ.

Có một lỗ hổng nếu bạn xác định phương thức chấp nhận đối tượng ... và bạn đã gửi một tham số kiểu Object []!

+0

Java cảnh báo bạn về điều này và yêu cầu bạn viết mảng (đối tượng) (cho chế độ variadic) hoặc mảng (Object []) (đối với chế độ không phải là variadic). :-) –

1

Sau này được giới thiệu trong Java 5 và các thư viện hiện có đang dần được làm lại để hỗ trợ nó. Bạn vẫn có thể sử dụng trước đây để nhấn mạnh rằng phương thức này yêu cầu 2+ đầu vào, cộng với có những hạn chế về nơi mà ... có thể được sử dụng.

+0

Ngoại trừ nó nhấn mạnh không có gì sắp xếp, và trong thực tế cho phép 0 hoặc 1 đầu vào (trừ khi được quy định khác trong tài liệu, trong trường hợp này các hình thức variadic là tốt như vậy). –

0

Chắc chắn không có vấn đề về hiệu suất hoặc những thứ như vậy để xem xét, do đó, nó đi xuống đến ngữ nghĩa.

Bạn có mong đợi người gọi phương pháp của bạn có sẵn một mảng sẵn sàng của Foo không? Sau đó sử dụng phiên bản Foo []. Sử dụng biến thể varargs để nhấn mạnh khả năng có một "bó" của Foo thay vì một mảng.

Một ví dụ cổ điển cho varargs ist chuỗi định dạng (trong C#, dunno làm thế nào gọi của nó trong Java):

string Format(string formatString, object... args) 

Ở đây bạn mong đợi args để được các loại khác nhau, do đó, có một mảng các đối số sẽ là khá bất thường, do đó biến thể varargs.

Mặt khác trong một cái gì đó giống như

string Join(string[] substrings, char concatenationCharacter) 

sử dụng một mảng là hoàn toàn hợp lý.

Cũng lưu ý rằng bạn có thể có nhiều tham số mảng và chỉ có một tham số vararg ở cuối danh sách tham số.

3

Tôi muốn thêm vào lời giải thích của Shimi để thêm rằng một hạn chế khác của cú pháp varargs là vararg phải là tham số được khai báo cuối cùng. Vì vậy, bạn không thể thực hiện việc này:

void myMethod(String... values, int num); 

Điều này có nghĩa là mọi phương thức nhất định chỉ có thể có một tham số vararg.Trong trường hợp bạn muốn chuyển nhiều mảng, bạn có thể sử dụng varargs cho chỉ một trong số chúng.

Trong thực tế, varargs là lúc tốt nhất của họ khi bạn đang xử lý args như một số tùy ý của các giá trị riêng biệt, chứ không phải là một mảng. Java5 ánh xạ chúng vào một mảng đơn giản chỉ vì đó là điều thuận tiện nhất để thực hiện.

Ví dụ điển hình là String.format(). Ở đây, các vararg được so khớp với các phần giữ chỗ định dạng trong đối số đầu tiên.

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