Проблематично ли присвоить новое значение параметру метода? - PullRequest
20 голосов
/ 09 февраля 2010

Eclipse имеет возможность предупреждать о назначении параметра метода (внутри метода), например:

public void doFoo(int a){
   if (a<0){
      a=0; // this will generate a warning
   }
   // do stuff
}

Обычно я пытаюсь активировать (и учитывать) почти все доступные предупреждения компилятора, но в этом случае я не совсем уверен, стоит ли оно того.

Я вижу законные случаи для изменения параметра в методе (например: разрешение параметра быть "неустановленным" (например, ноль) и автоматическая подстановка значения по умолчанию), но мало ситуаций, когда это может вызвать проблемы, за исключением того, что это может быть немного запутанным, чтобы переназначить параметр в середине метода.

Используете ли вы такие предупреждения? Почему / почему нет?

Примечание:

Избегать этого предупреждения, конечно, эквивалентно созданию параметра метода final (только тогда это ошибка компилятора :-)). Итак, этот вопрос Почему я должен использовать ключевое слово "final" для параметра метода в Java? может быть связано.

Ответы [ 8 ]

13 голосов
/ 09 февраля 2010

Запутанная часть - причина предупреждения. Если вы переназначаете для параметра новое значение в методе (возможно, условное), тогда не ясно, что это такое. Вот почему это считается хорошим стилем: оставить параметры метода без изменений.

9 голосов
/ 09 февраля 2010

Для меня, пока вы делаете это рано и четко, это нормально. Как вы говорите, делать это глубоко в четырех условных выражениях на полпути в функцию из 30 строк - это не идеально.

Вы также, очевидно, должны быть осторожны, когда делаете это со ссылками на объекты, так как вызов методов для объекта, который вы получили, может изменить его состояние и передать информацию обратно вызывающей стороне, но, конечно, если вы вложили в свой собственный заполнитель , эта информация не передается.

Обратной стороной является то, что объявление новой переменной и присвоение ей аргумента (или значения по умолчанию, если аргумент требует значения по умолчанию) может быть более понятным и почти наверняка не будет менее эффективным - любой достойный компилятор (будь то основной компилятор) или JIT) оптимизирует его, когда это возможно.

8 голосов
/ 09 февраля 2010

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

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

7 голосов
/ 09 февраля 2010

Переназначение переменной параметра метода обычно является ошибкой, если параметр является ссылочным типом.

Рассмотрим следующий код:

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");
}

Многие ожидают, что после вызова doFoo myObject.Foo будет равно "Bar". Конечно, это не произойдет - поскольку Java не передает по ссылке , но передает по ссылке - то есть копию ссылки передается в метод. Переназначение на эту копию влияет только на локальную область, а не на позицию вызова. Это одна из наиболее часто неправильно понимаемых концепций.

1 голос
/ 09 февраля 2010

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

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

0 голосов
/ 09 февраля 2010

Вы должны писать код без побочных эффектов: каждый метод должен быть функцией , которая не меняется. В противном случае это команда , и это может быть опасно.

См. Определения для команды и функции на сайте DDD:

Функция : Операция, которая вычисляет и возвращает результат без видимых побочных эффектов.

Команда : операция, которая вносит некоторые изменения в систему (для Например, установка переменной). операция, которая намеренно создает побочный эффект.

0 голосов
/ 09 февраля 2010

Мне обычно не нужно присваивать новые значения параметрам метода.

Что касается передового опыта - предупреждение также позволяет избежать путаницы при обращении к коду, подобному:

       public void foo() {
           int a = 1;
           bar(a);
           System.out.println(a);
       }

       public void bar(int a) {
           a++;
       }
0 голосов
/ 09 февраля 2010

Я иногда использую его в таких ситуациях:

void countdown(int n)
{
   for (; n > 0; n--) {
      // do something
   }
}

, чтобы избежать введения переменной i в цикл for. Обычно я использую подобные трюки только в очень коротких функциях.

Лично мне очень не нравится "корректировать" параметры внутри функции таким образом. Я предпочитаю поймать их по утверждениям и убедиться, что контракт верен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...