Как определяется величина статического / переменная класса ходило?


Переменная static / class определяется в типе / классе и считается связанной с типом / классом, в котором она определена, и независимой от экземпляров типа / класса. Существует ровно одна статическая переменная / class в типе / class и лучше всего используется для констант, подобных свойствам, значение которых было бы общим среди любых экземпляров класса. Состояние статической переменной / класса всегда существует в классе, и поэтому в любой момент времени в классе существует только одна переменная. класс и ключевое слово static используются для определения этой природы переменной. Статическая переменная / class в наилучшей практике должна быть инициализирована один раз, и это обеспечивается с помощью ключевого слова final. Конечная статическая переменная должна быть инициализирована неизменяемой коллекцией, как в новой строке () или новом целочисленном ();

Теперь мой вопрос заключается в том, как используется значение из статической переменной? И как называется использование этой переменной? Например, копирует ли он значение из класса, в котором он содержится, или является ли это явной ссылкой на переменную в классе?

Например

class GenericType {
    private final static String commonValue = new String("foobar");
} 
class AnotherGenericType {
    public static void main(String[] args) {
        System.out.println(GenericType.commonValue); //Displays foobar in the console.

    }
}
4 3

4 ответа:

Существует пространство, специально выделенное для хранения переменных static. Это указано в JLS, 8.3.1.1, который гласит

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

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

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

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

JLS указывает, что использование статической переменной называется: using a static variable. Просто шучу.

Это просто ссылка.

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

public class GenericType {
    public static Collection myCollection = new ArrayList();
}

public class Test {

    public static void main(String[] args) {
        // you are accessing the public static field
        GenericType.myCollection.add("first item");
        System.out.println(GenericType.myCollection);

        // now c holds a reference for the collection that is referred by myCollection field
        Collection c = GenericType.myCollection;
        GenericType.myCollection.add("second item");
        GenericType.myCollection = new ArrayList();

        // printing the object referred by c (the old reference hold by myCollection field)
        System.out.println(c);

        // and here the current reference of myCollection field
        System.out.println(GenericType.myCollection);
    }

}

Как указал @Francisco Spaeth, JLS ясен: существует только одно статическое значение, разделяемое между экземплярами.
Но класс может быть загружен в одну и ту же программу с разными загрузчиками классов, и это означает, что он может иметь разное статическое значение для каждого загрузчика классов. В качестве примера:

package classloaders;

import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;

class SampleClass{
    static public final long loadTime = System.nanoTime();
}

public class Main {

    public static void main(String[] args) throws Exception {

        URL url = new URL("file:///C:/workspaces/personal/JavaTest/bin/");
        ClassLoader cl1 = new URLClassLoader(new URL[]{url}, null);
        ClassLoader cl2 = new URLClassLoader(new URL[]{url}, null);

        Class<SampleClass> sampleClass = (Class<SampleClass>) cl1.loadClass("classloaders.SampleClass");
        Field field1 = sampleClass.getField("loadTime");
        field1.setAccessible(true);
        System.out.println(field1.get(null));

        Class<SampleClass> sampleClass2 = (Class<SampleClass>) cl2.loadClass("classloaders.SampleClass");
        Field field2 = sampleClass2.getField("loadTime");
        field2.setAccessible(true);
        System.out.println(field2.get(null));

    }

}

Если вы запустите этот код, то получите что-то вроде

193798032450350
193798062432257

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

, но это очень странный случай...