简体   繁体   English

如何传递静态/类变量的值?

[英]How is the value of a static / class variable passed around?

A static / class variable is defined in a type / class and is said to associate with the type / class that it is defined in and is independent of an instances of the type / class. 静态/类变量在类型/类中定义,并且被称为与其定义的类型/类相关联,并且独立于类型/类的实例。 There is exactly one static / class variable in the type / class and is best used for constant like properties, whose value would be common amongst any instances of the class. 类型/类中只有一个静态/类变量,最好用于常量like属性,其值在类的任何实例中都很常见。 The state of a static / class variable is always exists in the class and therefore there is only one variable at any moment in the class and the keyword static is used to define this nature of the variable. 静态/类变量的状态始终存在于类中,因此在类中的任何时刻只有一个变量,而关键字static用于定义变量的这种性质。 The static / class variable in best practice is to be initialized once and this is ensured using the keyword final. 最佳实践中的static / class变量将初始化一次,并使用关键字final确保。 A final static variable is to be initialized with an immutable collection as in a new String() or new Integer(); 最终的静态变量将使用不可变的集合进行初始化,如新的String()或new Integer();

Now my question is how is the value from the static variable used? 现在我的问题是静态变量的值是如何使用的? And what is the use of this variable called? 这个变量的用途是什么? Eg does it copy it's value from the class that it is contained in or is it an explicit reference to the variable in the class? 例如,它是从包含它的类中复制它的值还是它是对类中变量的显式引用?

eg 例如

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.

    }
}

There is space specifically allocated for the storage of static variables. 存在专门用于存储static变量的空间。 This is specified in the JLS, 8.3.1.1 , which states 这在JLS,8.3.1.1中规定 ,其中说明了这一点

If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. 如果一个字段被声明为static,那么无论该类最终可以创建多少个实例(可能为零),都只存在该字段的一个化身。 A static field, sometimes called a class variable, is incarnated when the class is initialized. 初始化类时,会生成静态字段(有时称为类变量)。

It's worth noting that these variables aren't open for garbage collected until the class is unloaded (which doesn't usually happen often), which is a potential for unintended memory references being held. 值得注意的是,在卸载类(通常不会经常发生)之前,这些变量对于收集的垃圾是不开放的,这可能会导致意外的内存引用。

Accessing static members could possibly be referred to as 'static access' (I've heard it used before) but generally it doesn't have its own term. 访问静态成员可能被称为“静态访问”(我以前听说过它)但通常它没有自己的术语。

Static variables associate with the class itself, not among instances of the class. 静态变量与类本身相关联,而不是与类的实例相关联。 Anything marked with the static keyword is initialized when the class is loaded at run-time. 在运行时加载类时,将初始化标记为static关键字的任何内容。 This is why you can call them with the class name and why you can use them without creating an object. 这就是为什么你可以用类名调用它们以及为什么你可以在不创建对象的情况下使用它们。

The JLS specifies that using a static variable is called: using a static variable . JLS指定使用静态变量: using a static variable Just kidding. 开玩笑。

It is simply a reference. 这只是一个参考。

In this case, as commonValue is defined as final and String is immutable, you cannot see it. 在这种情况下,由于commonValue被定义为finalString是不可变的,因此您无法看到它。 But suppose the following code: 但是假设以下代码:

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);
    }

}

As @Francisco Spaeth has pointed, the JLS is clear: there is only one static value shared between the instances. 正如@Francisco Spaeth指出的那样,JLS很明确:实例之间只共享一个静态值。
But a class can be loaded in the same program with different classLoaders, and that means it may have a different static value for each classLoader. 但是一个类可以使用不同的classLoader加载到同一个程序中,这意味着每个classLoader可能有不同的静态值。 As an example: 举个例子:

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));

    }

}

If you run this code you will be something like 如果您运行此代码,您将会是这样的

193798032450350
193798062432257

so you can see two different values in the same static field of the same class, by using different classloaders. 因此,您可以通过使用不同的类加载器在同一个类的同一静态字段中看到两个不同的值。

But that is a very strange case... 但这是一个非常奇怪的案例......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM