Почему переменная экземпляра должна быть окончательной?
Я прочитал этот вопрос об неизменных объектах и остался с вопросом относительно неизменных объектов и конечного поля:
Зачем нам нужна переменная экземпляра в неизменяемом классе, чтобы быть финальной?
Например, рассмотрим этот неизменный класс:
public final class Immutable
{
private final int someVal;
public Immutable(int someVal)
{
this.someVal= someVal;
}
public int getVal() {
return val;
}
}
Если в приведенном выше коде нет заданных методов и переменная экземпляра устанавливается только внутри конструктора, почему требуется, чтобы переменная экземпляра была объявлена как final?
4 ответа
Для создания переменной не требуется final
, Однако, если это правда, что вы явно намереваетесь никогда не менять переменную, часто хорошей практикой является сделать это final
, поскольку это не только навязывает инвариант против опечаток или других ошибок, но также объявляет намерение быть неизменным, например, для других программистов или для вас самих.
Если переменная была public
тогда вам бы строго нужно было это сделать final
чтобы гарантировать, что интерфейсный код не может изменить свое значение.
Обратите внимание, что вопрос, на который вы ссылаетесь, не имеет прямого отношения, поскольку в нем рассматриваются классы, которые final
, а не переменные. Создание класса final
означает, что оно не может быть унаследовано, не то, что оно является неизменным. Однако, безусловно, следует обратить внимание на содержание этого вопроса и его ответа при создании неизменных объектов; но это отдельный вопрос тем не менее.
Помечая все поля класса final
, вы даете понять, что вы хотите, чтобы ваш класс был неизменным.
Предположим, у вас есть следующий класс:
public class Immutable {
private int value;
public Immutable (int value) {
this.value = value;
}
public int getValue () {
return value;
}
}
Не существует метода установки, поэтому можно легко предположить, что этот класс неизменен. Что это, пока. Но в конечном итоге ваш класс будет изменен другим программистом, и этот программист может добавить некоторые методы в ваш класс:
public class Immutable {
private int value;
public Immutable (int value) {
this.value = value;
}
public int getValue () {
return value;
}
public void doSomething () {
value++;
}
}
Довольно просто непреднамеренно добавить метод, который изменяет состояние вашего объекта, если поля не являются final
, Отмечая их final
этот другой программист получит ошибку компиляции, когда попытается изменить поле, и должен будет спросить себя, почему это поле final
, и делает ли его модификация нарушает контракт этого класса.
Можно утверждать, что Javadoc следует использовать для документирования того, что указанный класс неизменен, но, честно говоря, не все читают Javadoc. На мой взгляд, сделать код лучше для себя.
Предыдущие ответы неверны.
Чтобы быть неизменным, объект должен объявить все свойства как final
,
Существуют определенные гарантии того, что модель памяти Java создает конечные поля, которые защищают их от возврата неправильных значений по умолчанию, когда между потоками существуют гонки данных.
См. Пример 17.5-2 в https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html.
В неизменяемом классе вы не можете изменить состояние его свойства / поля. Обычно это делается не предоставлением метода установки клиентскому коду класса.
И сочетание static final
Ключевое слово используется, чтобы сделать переменную константой. Переменная, объявленная как final, никогда не может изменить свое значение после инициализации.
Поскольку в неизменяемом классе вам никогда не нужно изменять состояние свойства / поля, поэтому лучше сделать его окончательным.