如何知道Java类是否已初始化

时间:2010-08-12 10:01:44

标签: java unit-testing class initialization

如何知道某个类是否已初始化?

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

2 个答案:

答案 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;
}

我提到它很难看吗? :)