Подтвердить что ты не робот

Когда целесообразно использовать пустые конечные переменные?

Я просмотрел еще один question о конечных переменных и заметил, что вы можете объявлять конечные переменные без их инициализации (blank final variable). Есть ли причина, по которой это желательно сделать, и когда это выгодно?

4b9b3361

Ответ 1

Это полезно для создания неизменяемых объектов:

public class Bla {
    private final Color color;

    public Bla(Color c) {this.color = c};

}

Bla неизменен (после его создания он не может измениться, поскольку цвет является окончательным). Но вы все равно можете создавать различные Blas, создавая их с различными цветами.

См. также этот вопрос, например.

EDIT

Возможно, стоит добавить, что "чистый финал" имеет очень специфическое значение в Java, что, похоже, создало некоторую путаницу в комментариях - cf Java Спецификация языка 4.12.4:

Пустое окончание - это конечная переменная, в декларации которой отсутствует инициализатор.

Затем вы должны назначить эту пустую конечную переменную в конструкторе.

Ответ 2

Конечное свойство класса должно иметь значение, назначенное до создания объекта. Таким образом, последней точкой, в которой вы можете назначить для них значение, является конструктор.

Это часто используется для неизменяемых объектов.

 public class Foo {

  private final Bar bar;

  public Foo(Bar bar) {
    this.bar = bar;
  }

  public Bar getBar() {
   return new Bar(bar);
 } 
}

Что wiki говорит об этом

Оборонительное копирование.

Ответ 3

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

Вот как вы делаете неизменяемые объекты и используется в шаблоне построителя.

class Builder{
    final BuilderContext context;

    private Builder(BuilderContext context){
        this.context=context;
    }       

    public static Builder New(){
        return new Builder(new BuilderContext());
    }

Ответ 4

Конечные переменные пустым должны быть назначены "где-то" в конструкторе. Скорее построенный пример:

public class Test {
    final int sign;
    public Test(String upDown) {
        if (upDown.equals("up")) {
            sign = +1;
        } else {
            sign = -1;
        }
    }
}

Ответ 5

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

class A {
  final URLConnection conn;
  A(String url) {
    try {
      this.conn = new URL(url).openConnection();
    } catch (IOException | MalformedURLException e) {
      // Maybe this isn't fatal, so just handle the Exception
      // here and move on happily
    }
  }
}

Ответ 6

Используйте пустую конечную переменную внутри метода, чтобы показать, что все пути кода, которые используют переменную, назначают эту переменную ровно один раз (или генерируют исключение). Компиляторы Java гарантируют, что перед его использованием будет назначена пустая конечная переменная.

Пример кода внутри некоторого метода:

  final Foo foo;
  if (condition1()) {
    foo = makeFoo(1);
  } else if (condition2()) {
    throw new BarException();
  } else {
    foo = makeFoo(-1);
  }
  ...
  blahBlahBlah(foo);

Использование пустых конечных переменных сообщает следующему читателю кода, что компилятор гарантирует, что кто-то назначил foo перед вызовом blahBlahBlah (foo).

Вопрос задает вопрос о "пустых конечных переменных". Обсуждение "пустых финальных полей" - это другое обсуждение и интересное само по себе.

Ответ 7

заметил, что вы можете объявить переменные final без их инициализации

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

Ответ 8

Из Wikipedia

Пустой финал, который был представлен в Java 1.1, является конечной переменной, в декларации которой отсутствует инициализатор. Пустой финал может быть назначен только один раз и должен быть не назначен при назначении. Для этого компилятор Java выполняет анализ потока, чтобы гарантировать, что для каждого присваивания пустой конечной переменной переменная определенно не назначена перед назначением; в противном случае возникает ошибка времени компиляции.

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