最好和最干净的方法是什么?具体来说,我需要静态初始化块中的一些代码才能在该类中运行,但我想让它看起来尽可能干净。
6 回答
加载!=初始化。
您希望您的类被初始化(这是在执行静态块时,除其他外)。
Java语言规范的摘录说:
类或接口类型 T 将在第一次出现 > 下列任何一项之前立即初始化:
- T 是一个类,并创建了一个 T 的实例。
- T 是一个类,并且调用了 T 声明的静态方法。
- 分配了一个由 T 声明的静态字段。
- 使用了由 T 声明的静态字段,并且该字段不是常量变量(第 4.12.4 节)。
- T 是一个顶级类,并且执行一个词法嵌套在 T 中的断言语句(第 14.10 节)。
在类 Class 和包 java.lang.reflect 中调用某些反射方法也会导致类或接口初始化。在任何其他情况下都不会初始化类或接口。
Doh,anovstrup,已经说过:只需创建一个名为init
. 一定要好好记录……不过,在格式良好的代码的上下文中,我个人看不到任何用例。
您可以使用以下代码来强制初始化一个类:
//... Foo.class ... //OLD CODE
... forceInit(Foo.class) ... //NEW CODE
/**
* Forces the initialization of the class pertaining to
* the specified <tt>Class</tt> object.
* This method does nothing if the class is already
* initialized prior to invocation.
*
* @param klass the class for which to force initialization
* @return <tt>klass</tt>
*/
public static <T> Class<T> forceInit(Class<T> klass) {
try {
Class.forName(klass.getName(), true, klass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new AssertionError(e); // Can't happen
}
return klass;
}
try
{
Class.forName(class name as string)
}
catch(ClassNotFoundException e)
{
whatever
}
那应该这样做。
@Longpoke
也许我误解了一些东西。你能创建一个加载类但不执行静态初始化程序的示例吗?这是一个示例,它只打印出它已加载的内容:
package test;
public class TestStatic
{
public static void main(String[] args)
{
try
{
Class.forName("test.Static");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
加载以下静态类:
package test;
public class Static
{
static
{
System.out.println("Static Initializer ran...");
}
}
如果在满足您列出的条件之前未运行静态初始化程序,那么为什么在我运行测试时会执行此 println ?那就是我满足您列出的哪个条件?
类之间不可见的依赖关系不是一个好主意。我建议将静态初始化程序块中的代码移动到静态方法并直接在依赖类中调用它。可以重写静态初始化程序块以调用新创建的静态方法。
一种解决方案是调用静态方法:
public class A {
static { DebugUtils.FLAG_TEST_USER = true; }
static void init() {}
}
然后调用A.init()
强制初始化。
但是,这样做完全是一种代码味道。考虑用单例对象中的标准构造函数替换您的静态代码。
如果您需要静态初始化 Class 中的某些内容,则意味着必须有依赖于它的客户端类。
如果有一个客户端,或者我们称它为初始化块的自然归宿,我认为在此处初始化它是最干净的。
对于许多相同的客户端情况,从这些类中验证另一个类中的静态初始化是否成功可能是一个好主意。然后记录耦合,并且您确定该类总是在第一个客户需要它之前被初始化。