提问人:Aaron 提问时间:7/26/2012 更新时间:7/26/2012 访问量:134
静态/类变量的值是如何传递的?
How is the value of a static / class variable passed around?
问:
静态/类变量在类型/类中定义,据说与定义它的类型/类相关联,并且独立于类型/类的实例。类型/类中只有一个静态/类变量,最适合用于常量类属性,其值在类的任何实例中都是通用的。静态/类变量的状态始终存在于类中,因此类中任何时候都只有一个变量,关键字静态用于定义变量的这种性质。最佳实践中的静态/类变量将初始化一次,这使用关键字 final 来确保。最后一个静态变量将使用不可变集合进行初始化,如新的 String() 或新的 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 指定使用静态变量被调用:。开玩笑。using a static variable
有专门为存储变量分配的空间。这在 JLS 8.3.1.1 中指定,其中指出static
如果一个字段被声明为静态,则只存在一个化身 字段,无论有多少个实例(可能为零) 类最终可能会被创建。静态字段,有时称为 类变量,在初始化类时化身。
值得注意的是,在卸载类之前,这些变量不会对垃圾回收开放(这通常不会经常发生),这可能会导致意外的内存引用被保留。
访问静态成员可以称为“静态访问”(我以前听说过它),但通常它没有自己的术语。
它只是一个参考。
在这种情况下,由于被定义为不可变的,因此您看不到它。但假设以下代码: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 很清楚:实例之间只有一个共享的静态值。
但是一个类可以用不同的 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
因此,通过使用不同的类加载器,您可以在同一类的同一静态字段中看到两个不同的值。
但这是一个非常奇怪的案例......
评论