如何知道某个类是否已初始化?
Class cl = Class.forName("com.example.MyClass", false, getClass().getClassLoader());
// the false argument above indicates that the class should not be initialized
// but how can I check whether it already was?
cl.isInitialized(); // this does not exist, how can I know instead?
关于我为什么想知道:
在客户端的项目中,我们有一个丑陋的类(*),其中包含许多我要测试的静态成员。要使测试可预测,静态成员必须具有默认值,这些默认值在初始化时设置。如果JUnit测试为每个测试类启动一个新的JVM,这不是一个问题:每次执行时都会新加载该类。但是当我和其他人一起在Eclipse中执行测试时,相同的JVM用于多个测试,并且该类没有新加载,并且成员不再具有其默认值。我希望能够决定,测试是否有意义(因为该类将被新加载)或者我是否应该返回,因为如果静态成员已经被修改,测试就没有意义。
(*)计划重构,但不仅仅是现在
类的简化版
public class Settings {
public static Properties props;
static{
props.setProperty("key1", "val1");
props.setProperty("key2", "val2");
}
}
和测试类
public class SettingsTest extends TestCase {
public void testDefauts() throws Exception {
Class cl = Class.forName("Settings", false, getClass().getClassLoader());
if(cl.isInitialized){ // doesn't exist
// Cannot test default values, because class was already initialized
return;
}
Properties props = Settings.props; // Settings is initialized here
assertEquals("val1", props.getProperty("key1"));
assertEquals("val2", props.getProperty("key2"));
}
}
答案 0 :(得分:1)
类的静态初始化器(调用static { ... }
块的那个)是在第一次类加载器加载类时执行的。保证只允许它们被调用一次,并且在允许任何其他线程访问该类之前以线程安全的方式调用它们。
我不确定你所拥有的单元测试有多大价值。您正在测试static {...}
块放置在Properties对象中的值。是不是直接看到默认/初始值是什么,只是基于Settings
类本身的代码?换句话说,您正在测试不会失败的逻辑,除非有人更改默认值。
我认为你只是去除静态块的肮脏,静态的属性对象(它听起来像)其他线程/类正在修改等等,这样做要好得多;而不是花费大量时间试图找到一种合适的方法来测试难看的代码。
答案 1 :(得分:0)
Class.forName() will initialise it,但您可以在a way that doesn't中调用它。在任何情况下,您都可以知道它是否已经初始化。
修改强>
我误解了那里的问题。我以为你想知道之前是否没有已初始化。如果你的心情很难过,你可以在相关类的静态块中设置一些其他类的静态字段,如下所示:
public class UglyClass {
static {
AnotherUglyClass.uglyClassInitialized = true;
}
}
public class AnotherUglyClass {
public static boolean uglyClassInitialized = false;
}
我提到它很难看吗? :)