繁体   English   中英

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

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

静态/类变量在类型/类中定义,并且被称为与其定义的类型/类相关联,并且独立于类型/类的实例。 类型/类中只有一个静态/类变量,最好用于常量like属性,其值在类的任何实例中都很常见。 静态/类变量的状态始终存在于类中,因此在类中的任何时刻只有一个变量,而关键字static用于定义变量的这种性质。 最佳实践中的static / class变量将初始化一次,并使用关键字final确保。 最终的静态变量将使用不可变的集合进行初始化,如新的String()或new Integer();

现在我的问题是静态变量的值是如何使用的? 这个变量的用途是什么? 例如,它是从包含它的类中复制它的值还是它是对类中变量的显式引用?

例如

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.

    }
}

存在专门用于存储static变量的空间。 这在JLS,8.3.1.1中规定 ,其中说明了这一点

如果一个字段被声明为static,那么无论该类最终可以创建多少个实例(可能为零),都只存在该字段的一个化身。 初始化类时,会生成静态字段(有时称为类变量)。

值得注意的是,在卸载类(通常不会经常发生)之前,这些变量对于收集的垃圾是不开放的,这可能会导致意外的内存引用。

访问静态成员可能被称为“静态访问”(我以前听说过它)但通常它没有自己的术语。

静态变量与类本身相关联,而不是与类的实例相关联。 在运行时加载类时,将初始化标记为static关键字的任何内容。 这就是为什么你可以用类名调用它们以及为什么你可以在不创建对象的情况下使用它们。

JLS指定使用静态变量: using a static variable 开玩笑。

这只是一个参考。

在这种情况下,由于commonValue被定义为finalString是不可变的,因此您无法看到它。 但是假设以下代码:

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很明确:实例之间只共享一个静态值。
但是一个类可以使用不同的classLoader加载到同一个程序中,这意味着每个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

因此,您可以通过使用不同的类加载器在同一个类的同一静态字段中看到两个不同的值。

但这是一个非常奇怪的案例......

暂无
暂无

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

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