Параметр '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
в вмещающем классе.)
5 ответов
Не похоже, что здесь кто-то сделал дело обманщика.
Я обычно не изменял бы параметры, и фактически я склонен отмечать свои параметры final
чтобы явно запретить это. Несколько причин:
Назначение параметра может быть перепутано с попыткой использовать его в качестве "выходного параметра", ref: javapractices.com, и ясность - это все
Неизменность предпочтения, и это касается значений параметров, как и все остальное. Примитивы - это просто вырожденный случай одного и того же, (как правило) легче рассуждать об неизменяемых переменных. Ссылка, эффективный элемент 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
}
Смежные вопросы (и связанный аргумент) в Stackru: "Использование модификатора final, когда это применимо в Java...", "Ключевое слово final в параметрах метода", "Окончательно ли вы определяете локальные переменные и параметры метода в Java".
Иногда считается плохой практикой переназначать параметры внутри метода. Это, вероятно, происходит из C/C++, где вызов doSomething(myVar)
может измениться myVar
после того, как метод завершен. Но это не относится к Java.
ИМХО, если вы делаете это первым делом в методе, это прекрасно. Каждый, кто читает ваш код, поймет, что происходит. Тем не менее, это может привести к путанице, если глубоко погрузиться в код.
По моему опыту, использование null
в качестве сторожа для параметра по умолчанию это больше идиома в Python. В Java вы можете просто перегрузить метод.
void doStuff() {
doStuff(DEFAULT_VALUE);
}
void doStuff(final String val) {
assert (val != null); // or whatever
...
}
Существует предпочтение компилятора, которое определяет, будет ли экземпляр назначения параметра проигнорирован, помечен предупреждением или помечен с ошибкой.
Перейдите в строку меню - выберите "Window..Preferences", затем в древовидном элементе управления диалогового окна "Preferences" выберите "Java..Compiler..Errors / Warnings", затем посмотрите в разделе "Стиль кода" для настройки "Назначение параметра".
Я подозреваю, что это Preston; скорее руководство для программистов, чем реальная потенциальная проблема. Некоторые могут счесть вводящим в заблуждение распоряжение исходным значением параметра.