2008-10-06 4 views
5

Рассмотрим следующие сигнатуры методов:массивы объектов в сигнатур метода

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

и

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

Пояснение: Первый принимает массив Foo-объектов в качестве аргумента - fooMethod(new Foo[]{..}) - в то время как последний принимает произвольное количество аргументов типа Foo и представляет их как массив Foo: s внутри метода - fooMethod(fooObject1, fooObject2, etc...).

Java выбрасывает подгонку, если оба определены, утверждая, что они являются дублирующими методами. Я проделал какую-то детективную работу и выяснил, что первая декларация действительно требует явного массива объектов Foo, и это единственный способ вызвать этот метод. Второй способ фактически принимает как произвольное количество аргументов Foo, так и принимает массив объектов Foo.

Итак, вопрос в том, что последний метод кажется более гибким, есть ли причины использовать первый пример, или я пропустил что-то жизненно важное?

+0

Не зная Java, это удар в темноте, но я предполагаю, что первое немного более эффективно, потому что: а) вы, вероятно, будете пропускать только один указатель, и b) вы будете передавая один указатель на смежную часть памяти. – 2008-10-06 12:11:30

+0

@monoxide: Нет, обе формы генерируют эквивалентный байт-код вызова, обе формы требуют создания массива для передачи. – 2008-10-06 12:13:58

+0

Вторая форма - это просто синтаксический сахар для первого. Итак, fooMethod (новый Foo (1), новый Foo (2)) здесь идентичен fooMethod (новый Foo [] {новый Foo (1), новый Foo (2)}) – 2008-10-06 12:14:51

ответ

12

Эти методы на самом деле одинаковы.

Эта функция называется varargs и является функцией компилятора. За кулисами это переводится в прежнюю версию.

Существует ошибка, если вы определяете метод, принимающий Object ... и вы отправили один параметр типа Object []!

1

Последний был представлен на Java 5, и существующие библиотеки постепенно перерабатываются для его поддержки. Вы все еще можете использовать первое, чтобы подчеркнуть, что для этого метода требуется 2+ входа, плюс есть ограничения на то, где ... можно использовать.

0

Есть, конечно, проблемы с производительностью или такие вещи, которые нужно учитывать, поэтому это сводится к семантике.

Ожидаете ли вы, что вызывающий абонент вашего метода будет иметь массив Foo под рукой? Затем используйте версию Foo []. Используйте вариант varargs, чтобы подчеркнуть возможность наличия «пучка» Foo вместо массива.

Классический пример для списков параметров ист строковый формат (в C#, не знают, как его называют в Java):

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

Здесь вы ожидаете арга быть разных типов, так что наличие массива аргументов было бы довольно unusal, следовательно вариант varargs.

С другой стороны, в чем-то вроде

string Join(string[] substrings, char concatenationCharacter) 

с использованием массива вполне разумно.

Также обратите внимание, что вы можете иметь несколько параметров массива и только один параметр vararg в конце списка paramater.

3

Я хотел бы добавить к объяснению Shimi, чтобы добавить, что другое ограничение синтаксиса varargs состоит в том, что vararg должен быть последним объявленным параметром. Таким образом, вы не можете это сделать:

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

Это означает, что любой данный метод может иметь только один параметр vararg.В тех случаях, когда вы хотите передать несколько массивов, вы можете использовать varargs только для одного из них.

На практике varargs являются лучшими, когда вы обрабатываете args как произвольное количество различных значений, а не как массив. Java5 сопоставляет их с массивом просто потому, что это было наиболее удобно.

Хорошим примером является String.format(). Здесь varargs сопоставляются с заполнителями формата в первом аргументе.

Смежные вопросы