Почему varargs должен быть последним в сигнатуре метода?

Если я пытаюсь записать метод как ниже

public void someStuff(Object ... args, String a )

Я получаю эту ошибку

Объект типа аргумента переменной метода someStuff должен быть последним параметром.

Я не полностью понимаю требования типа аргумента переменной, чтобы быть последним. Любые исходные данные будут полезны.

21
задан wattostudios 6 May 2012 в 03:52
поделиться

5 ответов

следует соглашению C. Конвенция C в свою очередь основана на архитектурах ЦП, которые передают аргументы в стеке. Первые аргументы Non-Vararg в конечном итоге закреплены на неподвижном смещении в StackFrame. Если вы можете сначала поставить аргументы Vararg, смещение стека следующих аргументов будет зависеть от того, сколько параметров Vararg вы бы прошли. Это значительно усложнит сумму кода, необходимого для их доступа.

В вашем примере с сначала в сначала она концептуально на смещении 0 независима, как количество аргументов Vararg, которые следуют. Но с LINK A последняя, ​​это может быть на смещении 0, 4, 8, 12 и т. Д. - вам придется рассчитать args.size * 4 Каждый раз, когда вам нужно .

21
ответ дан 29 November 2019 в 06:49
поделиться

Временный аргумент должен быть последним, поэтому компилятор может работать, какой аргумент какой-то.

Например, скажем, вы проходите

«тест», «тест», «тест», «тест»

в вашу функцию

public void someStuff(Object ... args, String a)

Java не могут работать, если вы хотите переменную ARGS содержать 3 или 4 строки. Это может быть очевидно для вас на момент написания, но это неоднозначно.

Однако, когда это наоборот вокруг

public void someStuff(String a, Object ... args)

, компилятор Java видит первую строку, вставляю его в «A», а затем знает, что оставшиеся строки могут быть безопасно введены в ARGS, и в результате неоднозначности нет двусмысленности.

22
ответ дан 29 November 2019 в 06:49
поделиться

, потому что это сделало бы язык излишне сложным. Представьте себе, если вы также позволили другим синтаксисам:

public void someStuff(String a, Object ... args, String b)
{
}

или даже:

public void someStuff(String a, Object ... args, int b, Object ... args2)
{
}

Этот второй синтаксис означает строку, за которой следует любое количество аргументов объекта типа, за которым следует целое число, а затем дополнительные объекты. Уверен, что вы могли бы разработать язык, который мог бы принять такие вещи, но что, если вы также хотели указать, что args2 должен содержать хотя бы один элемент, но args может быть пустым? Почему мы не можем это сделать? Вы могут дизайн такого языка.

Это сводится к, насколько сложно вы хотите, чтобы правила были? В этом случае они выбрали простой вариант, который выполняет потребности.

9
ответ дан 29 November 2019 в 06:49
поделиться

Ну строка также является экземпляром объекта, так что если вы Использование Varargs Ваш массив Vararg должен быть последним параметром, потому что компилятор не может решить, что args и какова ваша строка a. Подумайте о вызове метода в качестве кортежа имени метода и списка объектов, которые являются вашими параметрами. Если у вас есть два метода так:

public void someStuff(Object ... args, String a )
public void someStuff(String a, String b)

Компилятор не мог решить, какой метод выбрать для некоторого цвета («Hello», «Hello»). Если вы поместите свою строку A в качестве первого аргумента, это может решить, что что-то может (строка, строка) более специфичны, чем что-то для некоторых (строка, объект).

3
ответ дан 29 November 2019 в 06:49
поделиться

При использовании метода с var args любой другой формат может привести к неоднозначности. Наличие последнего varargs предотвращает возможные неоднозначности, не требуя дополнительного синтаксиса для разрешения неоднозначности, что уменьшит пользу от функции.

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

public void varargsAreCool(String surname, String firstname, 
                           String... nicknames) {
    // some cool varargs logic
}

При использовании подобно varargsAreCool("Джон", "Смит") очевидно, что John Smith не имеет ни одного никнейма. При таком использовании vargsAreCool("Эндрю", "Джонс", "Дрю", "Джонси").

Теперь рассмотрим следующее недействительное объявление метода:

public void varargsAreCool(String surname, String... nicknames,
                           String firstname) {
    // some cool varargs logic
}

Когда используется как varargsAreCool("Джон", "Смит") это Smith кличка Джона или его фамилия? Если это его фамилия, как мне указать, что у него нет прозвищ? Для этого вам, вероятно, придется использовать метод вида varargsAreCool("John", new String[]{}, "Smith"), который является неуклюжим и несколько нарушает цель функции.

При таком использовании varargsAreCool("Эндрю", "Дрю", "Джонси", "Джонс") являются Дрю, Джонси и Джонс всеми прозвищами, а фамилия отсутствует? Опять же эта двусмысленность может быть решена, но за счет неуклюжего дополнительного синтаксиса.

0
ответ дан 29 November 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: