Зупиніть перепризначення змінної
Хоча ці відповіді інтелектуально цікаві, я не читав короткої простої відповіді:
Використовуйте ключове слово остаточне, коли ви хочете, щоб компілятор не дозволяв зміні перепризначати інший об'єкт.
Незалежно від того, чи є змінна статичною змінною, змінною члена, локальною змінною або змінною аргументу / параметра, ефект абсолютно однаковий.
Приклад
Подивимося ефект в дії.
Розглянемо цей простий метод, де обом змінним ( 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.
}
Позначте локальну змінну як остаточну . Це призводить до помилки компілятора.
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";
}
Замість цього позначимо змінну параметра як остаточну . Це теж призводить до помилки компілятора.
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.
}
Мораль історії:
Якщо ви хочете, щоб змінна завжди вказувала на один і той же об'єкт, позначте змінну остаточною .
Ніколи не переназначайте аргументи
Як хороша практика програмування (будь-якою мовою), ви ніколи не повинні призначати змінну параметра / аргументу об'єкту, відмінному від об'єкта, переданого методом виклику. У наведених вище прикладах рядок ніколи не слід писати arg =
. Оскільки люди роблять помилки, а програмісти - люди, давайте попросимо компілятора допомогти нам. Позначте кожну змінну параметрів / аргументів як "остаточну", щоб компілятор міг знайти та позначити будь-які подібні повторні призначення.
В ретроспективі
Як зазначається в інших відповідях ... Враховуючи оригінальну дизайнерську мету Java допомогти програмістам уникнути німих помилок, таких як читання минулого кінця масиву, Java повинна була бути розроблена для автоматичного застосування всіх змінних параметрів / аргументів як "остаточних". Іншими словами, Аргументи не повинні бути змінними . Але задній погляд - це 20/20 бачення, і у дизайнерів Java на той час були повні руки.
Отже, завжди додайте final
до всіх аргументів?
Чи слід додати final
до кожного заявленого параметра методу?
- Теоретично, так.
- На практиці ні.
➥ Додайте final
лише тоді, коли код методу довгий або складний, де аргумент може бути помилково встановлений для локальної або членської змінної та, можливо, повторно призначений.
Якщо ви придбаєте практику ніколи не призначати аргумент, ви будете схильні додати "" final
до кожного. Але це нудно і робить декларацію дещо складнішою для читання.
Короткий простий код, де аргумент, очевидно, є аргументом, а не локальною змінною та змінною члена, я не намагаюся додавати final
. Якщо код цілком очевидний, і я не маю шансів, щоб я, ані будь-який інший програміст не займався технічним обслуговуванням чи рефакторингом, помилково помилявся з змінною аргументом як чимось, крім аргументу, тоді не турбуйтеся. У своїй роботі я додаю final
лише довший чи більше залучений код, де аргумент може бути помилковим для локальної чи членської змінної.
Ще один випадок доданий для повноти
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
}