Инициализировать статическое конечное поле в конструкторе

public class A 
{    
    private static final int x;

    public A() 
    {
        x = 5;
    }
}
  • final означает, что переменная может быть назначена только один раз (в конструкторе).
  • static означает, что это экземпляр класса.

Я не понимаю, почему это запрещено. Где эти ключевые слова мешают друг другу?


person Yaron Levi    schedule 23.02.2011    source источник


Ответы (7)


Конструктор будет вызываться каждый раз при создании экземпляра класса. Таким образом, приведенный выше код означает, что значение x будет повторно инициализироваться каждый раз при создании экземпляра. Но поскольку переменная объявлена ​​окончательной (и статической), вы можете сделать это только

class A {    
    private static final int x;

    static {
        x = 5;
    }
}

Но, если вы удалите статику, вам разрешено сделать это:

class A {    
    private final int x;

    public A() {
        x = 5;
    }
}

Или это:

class A {    
    private final int x;

    {
        x = 5;
    }
}
person adarshr    schedule 23.02.2011
comment
Очевидно, никто не удосужился объяснить, что статические переменные — это переменные, существующие во всех экземплярах класса. Таким образом, они могут быть созданы только один раз, когда класс загружается, а не когда создается потенциально много экземпляров класса. - person iheanyi; 26.08.2014
comment
Кроме того, я бы рекомендовал просто присваивать в объявлении, а не в статическом блоке. Это просто чище и, вероятно, это то, что хотел сделать ОП: private static final int x = 5; - person qwertzguy; 14.07.2016
comment
Что, если вы хотите передать значение 5 из другого компонента/класса, вместо того, чтобы жестко запрограммировать его? - person user1156544; 04.04.2019

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

Если вам нужна пользовательская логика для инициализации вашего статического конечного поля, поместите ее в статический блок.

person Sean Patrick Floyd    schedule 23.02.2011
comment
Хорошо, но вы только что объяснили, что происходит. Я спрашиваю, почему? В смысле без финала работает, без статики работает. таким образом, объединение обоих создает новую логику? - person Yaron Levi; 23.02.2011
comment
@YaronLevi, он только что сказал это ... статическое поле является членом самого класса. В вашем конструкторе вы присваиваете значение переменной. Слово final означает, что вы можете присвоить значение переменной только ОДИН раз, в вашем коде вы присваиваете значение переменной каждый раз, когда создается экземпляр класса, потому что переменная является статической (членом класса). Если вы избавитесь от статики, вы можете присвоить ей значение в конструкторе, поскольку каждый раз это новая переменная. Если вы избавитесь от final, то это будет просто статическая переменная, которой вы можете присвоить новое значение в любое время. - person user12345613; 23.02.2012
comment
@ user12345613 дал довольно хорошее объяснение. В одиночку, финальная или статическая работа; но после объединения статические конечные силы есть только одно такое поле для этого класса во всех экземплярах, и его можно инициализировать только один раз, независимо от того, сколько экземпляров. - person user908645; 31.03.2016

Подумайте о том, что происходит, когда вы создаете экземпляр объекта во второй раз. Он пытается установить его СНОВА, что категорически запрещено, поскольку является статическим финалом. Его можно установить только один раз для всего класса, а не экземпляра.

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

private static final x=5;

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

person rfeak    schedule 23.02.2011

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

Если вы установите его в своем конструкторе, вы позволите установить переменную более одного раза.

Следовательно, вы должны инициализировать его напрямую или предложить статический метод для его инициализации.

person ap2cu    schedule 23.02.2011

Final не означает, что его нужно инициализировать в конструкторе. В общем вот что делается:

 private static final int x = 5;

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

public class Car {
   static String name;
   public Car(String name) {
      this.name = name;
   }
}

...

Car a = new Car("Volkswagen");
System.out.println(a.name); // Produces Volkswagen

Car b = new Car("Mercedes");
System.out.println(b.name); // Produces Mercedes
System.out.println(a.name); // Produces Mercedes
person i.am.michiel    schedule 23.02.2011

Подумай об этом. Вы можете сделать это с помощью своего кода:

A a = new A();
A b = new A(); // Wrong... x is already initialised

Правильные способы инициализации x:

public class A 
{    
    private static final int x = 5;
}

or

public class A 
{    
    private static final int x;

    static
    {
        x = 5;
    }
}
person Lukas Eder    schedule 23.02.2011

Статический

Ключевое слово static означает, что член объекта, в данном случае поле, не привязан к экземпляру класса, а вместо этого является членом класса. Если статический член является полем, он инициализируется во время загрузки класса.

Он доступен через класс, а не через экземпляр (хотя последнее не невозможно, это считается дурным тоном), поэтому он доступен без запуска конструктора вообще — никогда.

Финал

Ключевое слово final, примененное к полю объекта, означает, что оно может быть назначено только один раз и что оно должно быть назначено во время инициализации.

Статический финал

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

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

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

Синглтон

Если вы ищете члена класса, которому назначаете только один раз, но читаете много раз, вы имеете дело с одиночка. Шаблон singleton обычно используется для доступа к общему ресурсу.

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

person SQB    schedule 24.12.2019