Почему переменная экземпляра должна быть окончательной?

Я прочитал этот вопрос о неизменяемых объектах и остался с вопросом относительно неизменяемых объектов и конечного поля:

Почему нам нужно, чтобы переменная экземпляра в неизменяемом классе была окончательной?

Например, рассмотрим этот неизменяемый класс:

public final class Immutable 

{

  private final int someVal;

  public Immutable(int someVal)
 {

    this.someVal= someVal;
  }

  public int getVal() {

    return val;
}

}

Если в приведенном выше коде нет методов набора и переменная экземпляра устанавливается только в конструкторе, почему требуется, чтобы переменная экземпляра была объявлена ​​окончательной?


person Naz    schedule 23.03.2015    source источник
comment
прочитайте процитированный вопрос еще раз, окончательными должны быть не переменные экземпляра, а класс.   -  person Henry    schedule 23.03.2015
comment
да, я читал это, но мой вопрос был в том, почему переменные экземпляра в этом классе должны быть окончательными?   -  person Naz    schedule 23.03.2015
comment
Может быть, дело в этом: он не должен быть окончательным, но он должен быть окончательным (чтобы однозначно было ясно, что он не будет изменен).   -  person Marco13    schedule 24.03.2015
comment
@ Marco13 не требуется, чтобы переменная экземпляра была окончательной, но мне нужно сделать ее окончательной. Так что это просто хорошая практика кодирования   -  person Naz    schedule 24.03.2015


Ответы (4)


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

Если бы переменная была public, вам строго нужно было бы сделать ее final, чтобы гарантировать, что интерфейсный код не может изменить свое значение.

Обратите внимание, что вопрос, на который вы ссылаетесь, не имеет прямого отношения, поскольку в нем обсуждаются классы, которые являются final, а не переменными. Создание класса final означает, что он не может быть унаследован, а не неизменен. Однако, безусловно, следует учитывать содержание этого вопроса и ответ на него при создании неизменяемых объектов; но тем не менее это отдельный вопрос.

person Dolda2000    schedule 23.03.2015

Помечая все поля класса 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. На мой взгляд, лучше заставить код говорить сам за себя.

person Laf    schedule 23.03.2015
comment
Это было хорошим объяснением с точки зрения программирования, например, когда мой код меняют через некоторое время. - person Naz; 24.03.2015
comment
В вопросе, на который вы ссылаетесь, есть очень хороший момент о маркировке вашего класса final, который вы должны принять во внимание. - person Laf; 24.03.2015

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

И комбинация ключевого слова static final используется, чтобы сделать переменную постоянной. Переменная, объявленная как final, никогда не сможет изменить свое значение после инициализации.

Поскольку в неизменяемом классе вам никогда не нужно изменять состояние свойства / поля, поэтому лучше сделать его окончательным.

person Razib    schedule 23.03.2015

Предыдущие ответы неверны.

Чтобы быть неизменным, объект должен объявлять все свойства как final.

Модель памяти Java предоставляет определенные гарантии для полей final, которые защищают их от возврата неверных значений по умолчанию при наличии гонок данных между потоками.

См. Пример 17.5-2 в https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5-110.

person elifr    schedule 27.11.2018
comment
объясните свой ответ здесь ссылки недостаточно - person Hanzala; 27.11.2018
comment
Не просто предоставляйте ссылки приятелю. Дайте также некоторые объяснения. - person Harshith Rai; 27.11.2018