Параметр '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.)


person Matt McHenry    schedule 19.10.2010    source источник


Ответы (5)


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

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

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

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

    person andersoj    schedule 20.10.2010
    comment
    Я не понимаю, какое отношение имеют конечный и выходной параметры. Последний параметр по-прежнему является изменяемым и может использоваться как выходной параметр. С другой стороны, final запрещает назначать новые объекты параметру и проверяет наличие ссылки на исходный объект, чтобы его можно было использовать для вывода. Я думаю, что final не подчеркивает, что параметр не является выходным параметром. На самом деле все обстоит наоборот. Я ошибся? - person Sebastian vom Meer; 27.11.2012
    comment
    @SebastianG Если параметр является примитивом, то final предотвращает присвоение нового значения (и, таким образом, путать его с inout). Если параметр является ссылкой, final предотвращает его переназначение. Следовательно, сам параметр не является inout (java все равно передает ссылки по значению - stackoverflow.com/questions/40480/is-java-pass-by-reference), но, конечно, вы можете изменять любые переданные объекты и использовать эти побочные эффекты для вывода. Ключевое слово final не имеет к этому отношения. - person andersoj; 27.11.2012
    comment
    Мои 2 цента: в java нет параметров out! Любой, кого это смущает, должен вернуться в школу. Поскольку в java нет параметров по умолчанию, я проверяю значение null и, если это так, я присваиваю значение по умолчанию самому параметру. (Я знаю, что вы можете перегрузить методы, но есть случаи, когда вам это нужно - например, spring mvc) - person Daniele Torino; 24.09.2015

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

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

person Nikita Rybak    schedule 19.10.2010

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

void doStuff() {
    doStuff(DEFAULT_VALUE);
}

void doStuff(final String val) {
    assert (val != null); // or whatever
    ...
}
person Josh Lee    schedule 19.10.2010

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

Перейдите в строку меню - выберите Window..Preferences, затем в древовидной структуре диалогового окна Preferences выберите Java..Compiler..Errors / Warnings, затем найдите в разделе Code Style настройку «Parameter Assignment».

alt text

person Ladlestein    schedule 20.10.2010
comment
Вопрос заключался в том, что плохого в присвоении значения параметру. - person SantiBailors; 21.09.2018

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

person maerics    schedule 19.10.2010