Как передается значение статической переменной / переменной класса?

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

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

e.g

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.

    }
}

person Aaron    schedule 25.07.2012    source источник


Ответы (4)


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

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

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

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

person corsiKa    schedule 25.07.2012

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

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

person LastStar007    schedule 25.07.2012

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

В этом случае, поскольку 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);
    }

}
person Francisco Spaeth    schedule 25.07.2012

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

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

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

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

person Pablo Grisafi    schedule 25.07.2012