Private final static attribute vs private final attribute

В Java, какая разница между:

private final static int NUMBER = 10;

и

private final int NUMBER = 10;

Оба являются private и final, разница - это атрибут static.

Что лучше? И почему?

Ответ 1

В общем случае static означает "связанный с самим типом, а не с экземпляром типа".

Это означает, что вы можете ссылаться на статическую переменную, не создавая экземпляров этого типа, и любой код, ссылающийся на переменную, ссылается на одни и те же данные. Сравните это с переменной экземпляра: в этом случае существует одна независимая версия переменной для экземпляра класса. Так, например:

Test x = new Test();
Test y = new Test();
x.instanceVariable = 10;
y.instanceVariable = 20;
System.out.println(x.instanceVariable);

распечатывает 10: y.instanceVariable и x.instanceVariable являются отдельными, потому что x и y относятся к разным объектам.

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

Test x = new Test();
Test y = new Test();
x.staticVariable = 10;
y.staticVariable = 20;
System.out.println(x.staticVariable);

то это будет печатать 20 - там только одна переменная, а не одна на экземпляр. Было бы более понятно написать это как:

Test x = new Test();
Test y = new Test();
Test.staticVariable = 10;
Test.staticVariable = 20;
System.out.println(Test.staticVariable);

Это делает поведение более очевидным. Современные IDE обычно предлагают изменить второй список на третий.

Нет причин для объявления, например

private final int NUMBER = 10;

Если он не может измениться, то нет экземпляра на экземпляр.

Ответ 2

Для final ему могут быть присвоены разные значения во время выполнения при инициализации. Например,

Class Test{
  public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

Таким образом, каждый экземпляр имеет различное значение поля a.

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

Class TestStatic{
      public static final int a;
}

TestStatic t1  = new TestStatic();
t1.a = 10;
TestStatic t2  = new TestStatic();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.

Ответ 3

A static переменная остается в памяти на протяжении всего срока службы приложения и инициализируется во время загрузки класса. Переменная non static инициализируется каждый раз, когда вы создаете объект new. Обычно лучше использовать:

private static final int NUMBER = 10;

Почему? Это уменьшает объем памяти в каждом экземпляре. Возможно, это также благоприятно для хитов кэша. И это имеет смысл: static следует использовать для вещей, которые совместно используются во всех экземплярах (объекты a.k.a.) определенного типа (a.k.a. class).

Ответ 4

static означает "связанный с классом"; без него переменная связана с каждым экземпляром класса. Если он статичен, значит, у вас будет только один в памяти; если нет, у вас будет один для каждого создаваемого вами экземпляра. static означает, что переменная останется в памяти до тех пор, пока класс загружен; без него переменная может быть gc'd, когда ее экземпляр.

Ответ 5

Читая ответы, я не нашел реального теста, который действительно дошел до сути. Вот мои 2 цента:

public class ConstTest
{

    private final int         value             = 10;
    private static final int  valueStatic       = 20;
    private final File        valueObject       = new File("");
    private static final File valueObjectStatic = new File("");

    public void printAddresses() {


        System.out.println("final int address " +
                ObjectUtils.identityToString(value));
        System.out.println("final static int address " +
                ObjectUtils.identityToString(valueStatic));
        System.out.println("final file address " + 
                ObjectUtils.identityToString(valueObject));
        System.out.println("final static file address " + 
                ObjectUtils.identityToString(valueObjectStatic));
    }


    public static void main(final String args[]) {


        final ConstTest firstObj = new ConstTest();
        final ConstTest sndObj = new ConstTest();

        firstObj.printAdresses();
        sndObj.printAdresses();
    }

}

Результаты для первого объекта:

final int address [email protected]
final static int address [email protected]
final file address [email protected]
final static file address [email protected]

Результаты для 2-го объекта:

final int address [email protected]
final static int address [email protected]
final file address [email protected]
final static file address [email protected]

Заключение:

Как я думал, java делает разницу между примитивным и другими типами. Примитивные типы в Java всегда "кэшируются", то же самое для строк литералов (а не для новых объектов String), поэтому никакой разницы между статическими и нестационарными членами.

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

Изменение значения valueStatic до 10 даже будет продолжаться, поскольку Java предоставит те же адреса двум переменным int.

Ответ 6

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

Рассмотрим следующий пример:

public class TestClass {
    private final static double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

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

Однако при попытке выполнить следующий пример:

public class TestClass {
    private final double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

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

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

Ответ 7

Как уже сказал Джон, статическая переменная, также называемая переменной класса, является переменной, которая существует в экземплярах класса.

Я нашел пример этого здесь:

public class StaticVariable
{
  static int noOfInstances;
  StaticVariable()
  {
    noOfInstances++;
  }
  public static void main(String[] args)
  {
    StaticVariable sv1 = new StaticVariable();
    System.out.println("No. of instances for sv1 : " + sv1.noOfInstances);

    StaticVariable sv2 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for st2 : "  + sv2.noOfInstances);

    StaticVariable sv3 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for sv2 : "  + sv2.noOfInstances);
    System.out.println("No. of instances for sv3 : "  + sv3.noOfInstances);
  }
}

Вывод программы приведен ниже:

Как мы видим в этом примере, каждый объект имеет свою собственную копию переменной класса.

C:\java>java StaticVariable
No. of instances for sv1 : 1
No. of instances for sv1 : 2
No. of instances for st2 : 2
No. of instances for sv1 : 3
No. of instances for sv2 : 3
No. of instances for sv3 : 3

Ответ 8

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

Например:

class A
{
    final int f;
    static final int sf = 5;

    A(int num)
    {
        this.f = num;
    }

    void show()
    {
        System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n", this.toString(), this.f, sf);
    }

    public static void main(String[] args)
    {
        A ob1 = new A(14);
        ob1.show();

        A ob2 = new A(21);
        ob2.show();

    }
}

Что отображается на экране:

Об объекте: A @addbf1  Финал: 14  Статический финал: 5

Об объекте: A @530daa  Финал: 21  Статический финал: 5

Анонимный студент 1-го курса, Греция

Ответ 9

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

Для вашей основной цели: если вы не используете NUMBER по-разному в разных экземплярах класса, я бы посоветовал использовать final и static. (Вам просто нужно иметь в виду не копировать скомпилированные файлы классов, не учитывая возможные проблемы, как описано в моем примере. Большинство случаев этого не происходит, не беспокойтесь:))

Чтобы показать вам, как использовать разные значения в экземплярах, проверьте этот код:

public class JustFinalAttr {
  public final int Number;

  public JustFinalAttr(int a){
    Number=a;
  }
}

...System.out.println(new JustFinalAttr(4).Number);

Ответ 10

Вот мои два цента:

final           String CENT_1 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";
final   static  String CENT_2 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";

Пример:

package test;

public class Test {

    final long OBJECT_ID = new Random().nextLong();
    final static long CLASSS_ID = new Random().nextLong();

    public static void main(String[] args) {
        Test[] test = new Test[5];
        for (int i = 0; i < test.length; i++){
            test[i] = new Test();
            System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same value
            System.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different
        }
    }
}

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

Ответ 11

очень мало, а статический

Нет большой разницы, поскольку они оба являются константами. Для большинства объектов данных класса статичность означает нечто, связанное с самим классом, причем имеется только одна копия независимо от того, сколько объектов было создано с помощью нового.

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

Ответ 12

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

Ответ 13

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

частное конечное значение переменной будет как константа для каждого объекта.

Вы можете ссылаться на java.lang.String или искать пример ниже.

public final class Foo
{

    private final int i;
    private static final int j=20;

    public Foo(int val){
        this.i=val;
    }

    public static void main(String[] args) {
        Foo foo1= new Foo(10);

        Foo foo2= new Foo(40);

        System.out.println(foo1.i);
        System.out.println(foo2.i);
        System.out.println(check.j);
    }
}

//Выходные данные:

10
40
20

Ответ 14

Статический - это один и тот же член во всех экземплярах класса и самом классе.
Нестатический - один для каждого экземпляра (объекта), поэтому в вашем конкретном случае это пустая трата памяти, если вы не ставите статическую.

Ответ 15

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

Однако вы можете сделать переменную теперь общедоступной, так как никто не может ее изменить так же, как "System.out", она снова зависит от ваших намерений и того, чего вы хотите достичь.

Ответ 16

Давайте скажем, если класс будет иметь не один экземпляр, а затем какой-то другой памяти:

private static final int ID = 250; или private final int ID = 250;

Я понял, что static будет ссылаться на тип класса только с одной копией в памяти, а нестационарная будет в новой ячейке памяти для каждой переменной экземпляра. Однако внутренне, если мы просто сравниваем один экземпляр одного и того же класса (т.е. Более 1 экземпляр не будет создан), тогда есть ли какие-либо накладные расходы в пространстве, используемом 1 статической конечной переменной?

Ответ 17

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

public class ExperimentFinal {

private final int a;
private static final int b = 999; 

public ExperimentFinal(int a) {
    super();
    this.a = a;
}
public int getA() {
    return a;
}
public int getB() {
    return b;
}
public void print(int a, int b) {
    System.out.println("final int: " + a + " \nstatic final int: " + b);
}
public static void main(String[] args) {
    ExperimentFinal test = new ExperimentFinal(9);
    test.print(test.getA(), test.getB());
} }

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

Ответ 18

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

public class City {

    // base price that is always same for all objects[For all cities].
    private static double iphone_base_price = 10000;

    // this is total price = iphone_base_price+iphone_diff;
    private double iphone_citi_price;

    // extra price added to iphone_base_price. It is constant per city. Every
    // city has its own difference defined,
    private final double iphone_diff;

    private String cityName = "";

    // static final will be accessible everywhere within the class but cant be
    // changed once initialized.
    private static final String countryName = "India";

    public City(String cityName, double iphone_diff) {
        super();
        this.iphone_diff = iphone_diff;
        iphone_citi_price = iphone_base_price + iphone_diff;
        this.cityName = cityName;

    }

    /**
     * get phone price
     * 
     * @return
     */
    private double getPrice() {

        return iphone_citi_price;
    }

    /**
     * Get city name
     * 
     * @return
     */
    private String getCityName() {

        return cityName;
    }

    public static void main(String[] args) {

        // 300 is the
        City newyork = new City("Newyork", 300);
        System.out.println(newyork.getPrice() + "  " + newyork.getCityName());

        City california = new City("California", 800);
        System.out.println(california.getPrice() + "  " + california.getCityName());

        // We cant write below statement as a final variable can not be
        // reassigned
        // california.iphone_diff=1000; //************************

        // base price is defined for a class and not per instances.
        // For any number of object creation, static variable value would be the same
        // for all instances until and unless changed.
        // Also it is accessible anywhere inside a class.
        iphone_base_price = 9000;

        City delhi = new City("delhi", 400);
        System.out.println(delhi.getPrice() + "  " + delhi.getCityName());

        City moscow = new City("delhi", 500);
        System.out.println(moscow.getPrice() + "  " + moscow.getCityName());

        // Here countryName is accessible as it is static but we can not change it as it is final as well. 
        //Something are meant to be accessible with no permission to modify it. 
        //Try un-commenting below statements
        System.out.println(countryName);

        // countryName="INDIA";
        // System.out.println(countryName);

    }

}

Ответ 19

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

Ответ 20

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

Ответ 21

Это может помочь

public class LengthDemo {
public static void main(String[] args) {
    Rectangle box = new Rectangle();
    System.out.println("Sending the value 10.0 "
            + "to the setLength method.");
    box.setLength(10.0);
    System.out.println("Done.");
    }
}