Параметр 'foo' не должен быть назначен - какой вред? - PullRequest
29 голосов
/ 20 октября 2010

Сравните этот метод:

void doStuff(String val) {
    if (val == null) {
        val = DEFAULT_VALUE;
    }

    // lots of complex processing on val
}

... к этому методу:

void doStuff(String origVal) {
    String val = origVal;
    if (val == null) {
        val = DEFAULT_VALUE;
    }

    // lots of complex processing on val
}

Для первого метода Eclipse выдает предупреждение «Параметр val не должен быть назначен». Почему?

На мой взгляд, первый чище. Во-первых, это не заставляет меня придумывать двух хороших имен для val (придумать одно хорошее достаточно сложно).

(Примечание. Предположим, что во включающем классе нет поля с именем val.)

Ответы [ 5 ]

35 голосов
/ 20 октября 2010

Не похоже, что здесь кто-то сделал дело обманщика.

Как правило, я бы не изменял параметры, и фактически я стараюсь пометить свои параметры final, чтобы явно запретить это. Несколько причин:

  • Присвоение параметра может быть перепутано с попыткой использовать его в качестве «выходного параметра» , ref: javapractices.com , и ясность - это все

  • Неизменность Favor , и это касается значений параметров так же, как и всего остального. Примитивы - это просто вырожденный случай одного и того же, (как правило) легче рассуждать об неизменных переменных. Ссылка, Эффективный элемент Java 13 или javapractices.com

  • И, наконец (NPI), Используйте финал свободно , javapractices.com . Каким бы уродливым это ни было в сигнатурах параметров, я считаю, что оно имеет тенденцию выявлять неожиданные ошибки и выделяет изменяемые переменные, которые обычно должны быть исключением. Большинство изменчивых переменных в большинстве кода существуют либо для лени, либо для ощущения того, что это как-то влияет на производительность, когда разумно выбранные, неизменные и хорошо названные промежуточные вычисления более понятны, легче читаются и проверяются и могут быть чисто оптимизированы для производительности без вашей помощи.

Я не могу говорить разумно с вашим конкретным случаем в резюме, но, исключая все другие вещи, которые я мог бы сделать по-другому, я бы предпочел:

void doStuff(final String origVal)
{
    final String valOrDefault = (origVal == null) ? DEFAULT_VALUE : origVal;
    //lots of complex processing on valOrDefault 
}

или даже (при условии, что вы не справитесь с нулевым значением в реальном методе только с одним аргументом, оно должно быть частью чего-то более сложного) ... Кроме того, в общем, методы, которые принимают null как Параметр должен быть явно задокументирован как таковой, хотя бы для того, чтобы подтвердить предположение, что нулевые параметры должны быть исключением. Во втором методе вы можете даже использовать аннотацию @NonNull .

/**
  * @param origVal string giving value, possibly null, in which case DEFAULT_VALUE is assigned
  */
void doStuff(final String origVal, ... )
{
    final String valOrDefault = (origVal == null) ? DEFAULT_VALUE : origVal; 
    // similar mucking about to make all the parameters behave, separate from
    // actually operating on them...
    ...
    reallyDoStuff(valOrDefault,...);
}

private void reallyDoStuff(final String value, ...)
{
   assert (value != null);
   // do your complex processing
}

Смежные вопросы (и связанный аргумент) в StackOverflow: "Использование модификатора final везде, где это применимо в Java ..." , "Ключевое слово final в параметрах метода" , " Окончательно ли вы определяете локальные переменные и параметры метода в Java ".

14 голосов
/ 20 октября 2010

Иногда считается плохой практикой переназначать параметры внутри метода.Вероятно, это происходит из C / C ++, где вызов doSomething(myVar) может изменить myVar после завершения метода.Но это не относится к Java.

ИМХО, если вы сделаете это первым делом в методе, это прекрасно.Каждый, кто читает ваш код, поймет, что происходит.Впрочем, это может сбить с толку, если глубоко погрузиться в код.

7 голосов
/ 20 октября 2010

По моему опыту, использование null в качестве часового для параметра по умолчанию - больше идиома в Python. В Java вы можете просто перегрузить метод.

void doStuff() {
    doStuff(DEFAULT_VALUE);
}

void doStuff(final String val) {
    assert (val != null); // or whatever
    ...
}
6 голосов
/ 20 октября 2010

Существует предпочтение компилятора, которое определяет, будет ли экземпляр назначения параметра проигнорирован, помечен предупреждением или помечен с ошибкой.

Перейдите в строку меню - выберите Window..Preferences, затем В древовидном элементе управления диалогового окна Preferences выберите Java..Compiler..Errors / Warnings, затем посмотрите в разделе «Стиль кода» для «Параметра».Назначение ».

alt text

1 голос
/ 20 октября 2010

Я подозреваю, что это проблема стиля ;скорее руководство для программистов, чем реальная потенциальная проблема.Некоторые могут посчитать неправильным удаление исходного значения параметра.

...