Eclipse имеет опцию предупредить о присвоении на параметр метода (в методе), как в:
public void doFoo(int a){
if (a<0){
a=0; // this will generate a warning
}
// do stuff
}
Обычно я пытаюсь активировать (и внимание) почти все доступные предупреждения компилятора, но в этом случае я не действительно уверен, стоит ли это того.
Я вижу законные случаи для изменения параметра в методе (например: Разрешение параметра быть "сброшенным" (например, пустой указатель) и автоматически замена значением по умолчанию), но немного ситуаций, где это вызвало бы проблемы, за исключением того, что это могло бы немного сбивать с толку для переприсвоения параметра посреди метода.
Вы используете такие предупреждения? Почему / почему нет?
Примечание:
Предотвращение этого предупреждения, конечно, эквивалентно созданию параметра метода final
(только затем это - ошибка компилятора :-)). Так этот вопрос, Почему я должен использовать ключевое слово "финал" на параметре метода в Java? мог бы быть связан.
Для меня, пока ты делаешь это рано и ясно, все в порядке. Как вы говорите, делать это глубоко в четырех кондиционерах на полпути в 30-строчную функцию менее чем идеально.
Очевидно также, что нужно быть осторожным, когда делаешь это со ссылками на объект, так как вызов методов на данном объекте может изменить его состояние и передать информацию обратно вызывающему абоненту, но, конечно же, если вы подпишитесь в своем собственном хозяине, эта информация не будет передана.
Оборотная сторона состоит в том, что объявление новой переменной и присвоение ей аргумента (или по умолчанию, если аргумент нуждается в умолчании) вполне может быть более ясным и почти наверняка не будет менее эффективным - любой приличный компилятор (будь то первичный компилятор или JIT) оптимизирует его, когда это возможно.
Назначение параметра метода - это не то, что большинство людей ожидает в большинстве методов. Поскольку мы читаем код в предположении, что значения параметров фиксированы, присвоение обычно считается плохой практикой, хотя бы по соглашению и принципу наименьшего удивления .
Всегда есть альтернативы назначению параметров метода: обычно достаточно локальной временной копии. Но, как правило, если вы обнаружите, что вам нужно управлять логикой своей функции с помощью переназначения параметров, можно было бы извлечь выгоду из рефакторинга в более мелкие методы.
Непонятная часть является причиной предупреждения. Если переназначить параметру новое значение в методе (возможно, условное), то неясно, что такое a. Вот почему считается хорошим стилем оставлять параметры методов неизменными.
Переназначение переменной параметра метода обычно является ошибкой, если параметр является ссылочным типом.
Рассмотрим следующий код:
MyObject myObject = new myObject();
myObject.Foo = "foo";
doFoo(myObject);
// what's the value of myObject.Foo here?
public void doFoo(MyObject myFoo){
myFoo = new MyObject("Bar");
}
Многие люди ожидают, что at после вызова doFoo myObject.Foo будет равно «Bar». Конечно, не будет - потому что Java не передается по ссылке , а передается по значению ссылки , то есть копия ссылки передается методу. Переназначение этой копии влияет только на локальную область видимости, но не на callite. Это одна из наиболее часто неправильно понимаемых концепций.
Различные предупреждения компилятора могут подходить для разных ситуаций. Конечно, некоторые из них применимы к большинству или ко всем ситуациям, но это, кажется, не одна из них.
Я бы подумал об этом конкретном предупреждении как о том, что компилятор дает возможность предупредить о переназначении параметра метода, когда это необходимо, а не как о правиле, что параметры метода не должны быть переназначены. Ваш пример является для него вполне корректным.
Иногда я использую его в таких ситуациях:
void countdown(int n)
{
for (; n > 0; n--) {
// do something
}
}
, чтобы не вводить переменную i в цикл for. Обычно я использую такие «уловки» только в очень коротких функциях.
Лично мне очень не нравится "исправлять" параметры внутри функции таким образом. Я предпочитаю ловить их утверждениями и удостоверяться в правильности контракта.
Вы пишете код без побочных эффектов : каждый метод shoud - это функция , которая не изменяется . В противном случае это команда и это может быть опасно.
См. определения команды и функции на веб-сайте DDD :
Функция : Операция, которая вычисляет и возвращает результат без видимых побочных эффектов.
Команда : Операция, которая влияет на некоторые изменения в системе (для например, установка переменной). . операция, которая намеренно создает Побочное действие.
Обычно мне не нужно назначать новые значения параметрам метода.
Что касается передового опыта - предупреждение также позволяет избежать путаницы при столкновении с кодом вроде:
public void foo() {
int a = 1;
bar(a);
System.out.println(a);
}
public void bar(int a) {
a++;
}