Подтвердить что ты не робот

Параметр "foo" не должен быть назначен - какой вред?

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

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.)

4b9b3361

Ответ 1

Не похоже, чтобы кто-то делал здесь случай с притеснениями.

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

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

  • Использовать неизменность, и это значение для значений параметров так же, как и все остальное. Примитивы - это всего лишь вырожденный случай того же самого, он (вообще) легче рассуждать о неизменяемых переменных. Ref, Эффективный 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: "Использование окончательного модификатора, когда это применимо в Java..." , "конечное ключевое слово в параметрах метода" , "Вы окончательно определили локальные переменные и параметры метода в Java" .

Ответ 2

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

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

Ответ 3

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

void doStuff() {
    doStuff(DEFAULT_VALUE);
}

void doStuff(final String val) {
    assert (val != null); // or whatever
    ...
}

Ответ 4

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

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

alt text

Ответ 5

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