静态域的作用范围是在同一个类之内,类不仅有名称上的区别,还有classloader,即类加载器的问题,同一个class文件被不同的类加载器加载后,即便它们有相同的名称,但是它们并不是同一个类。因此在不同类加载器中同名类的静态变量是不共享的。下面做一个测试,来验证它。下面的Test类有一个静态域value,两个方法分别增加value的值和打印状态。
private static int value = 1;
public void increase() {
value++;
}
public void print() {
System.out.println("My Class Loader: "
+ this.getClass().getClassLoader() + ", Value: " + value);
}
}
下面的类StaticTest,运行时创建两个类加载器,分别载入同一个class文件,并通过反射依次调用print, increase,print方法。如果静态域在整个JVM内共享,那么value被加了两次,最后会输出3;否则应该输出2。由于类加载器会先向父类加载器请求类,找不到的时候才会自己加载,所以在运行这个测试时,一定不要把Test类先放到classpath中。
import java.net.URL;
import java.net.URLClassLoader;
public class StaticTest {
public static void main(String[] args) throws Exception {
URL[] classURLs = new URL[] {
new URL("file:/home/sulong/tmp/")
};
URLClassLoader classLoader1 = new URLClassLoader(classURLs);
URLClassLoader classLoader2 = new URLClassLoader(classURLs);
test(classLoader1);
System.out.println("--------------------");
test(classLoader2);
}
private static void test(ClassLoader loader)
throws Exception {
Class clazz = loader.loadClass("Test");
Object testObj = clazz.newInstance();
invoke(clazz, testObj, "print");
invoke(clazz, testObj, "increase");
invoke(clazz, testObj, "print");
}
private static void invoke(Class clazz, Object obj, String name)
throws Exception {
Method method1 = clazz.getMethod(name, new Class[]{});
method1.invoke(obj, new Object[]{});
}
}
下面是我的机器上运行时的测试结果:
My Class Loader: java.net.URLClassLoader@7987aeca, Value: 2
--------------------
My Class Loader: java.net.URLClassLoader@5d0385c1, Value: 1
My Class Loader: java.net.URLClassLoader@5d0385c1, Value: 2