Остановить переназначение переменной
Хотя эти ответы интеллектуально интересны, я не прочитал короткий простой ответ:
Используйте ключевое слово final , если хотите, чтобы компилятор предотвращал
Переопределение переменной для другого объекта.
Независимо от того, является ли переменная статической, переменной-членом, локальной переменной или переменной / параметром, эффект полностью одинаков.
Пример
Давайте посмотрим эффект в действии.
Рассмотрим этот простой метод, в котором двум переменным ( arg и x ) могут быть одновременно назначены разные объекты.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Пометить локальную переменную как final . Это приводит к ошибке компилятора.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Вместо этого давайте пометим переменную параметра как final . Это также приводит к ошибке компилятора.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Мораль истории:
Если вы хотите, чтобы переменная всегда указывала на один и тот же объект,
пометить переменную final .
Никогда не переназначать аргументы
Как хорошая практика программирования (на любом языке), вы никогда не должны повторно назначать переменную параметра / аргумента объекту, отличному от объекта, переданного вызывающим методом. В приведенных выше примерах никогда не следует писать строку arg =
. Поскольку люди делают ошибки, а программисты - люди, давайте попросим компилятор помочь нам. Пометьте каждую переменную параметра / аргумента как 'final', чтобы компилятор мог найти и пометить любое такое переназначение.
В ретроспективе
Как отмечено в других ответах ...
Учитывая первоначальную цель разработки Java, заключающуюся в том, чтобы помочь программистам избежать глупых ошибок, таких как чтение за концом массива, Java должна была быть спроектирована так, чтобы автоматически приводить все переменные параметра / аргумента как «final». Другими словами, Аргументы не должны быть переменными . Но задним числом является видение 20/20, и дизайнеры Java были заняты в то время.
Еще один случай, добавленный для полноты
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}