Java 如何强制初始化类?

Java 如何强制初始化类?,java,coding-style,static-initializer,Java,Coding Style,Static Initializer,做这件事最好最干净的方法是什么?具体来说,我需要一些静态初始值设定项块中的代码才能在该类中运行,但我希望使其看起来尽可能干净。类之间不可见的依赖关系不是一个好主意。我建议将静态初始值设定项块中的代码移动到静态方法中,并在依赖类中直接调用它。可以重写静态初始值设定项块以调用新创建的静态方法 try { Class.forName(class name as string) } catch(ClassNotFoundException e) { whatever } 应该这样做 @朗普克

做这件事最好最干净的方法是什么?具体来说,我需要一些静态初始值设定项块中的代码才能在该类中运行,但我希望使其看起来尽可能干净。

类之间不可见的依赖关系不是一个好主意。我建议将静态初始值设定项块中的代码移动到静态方法中,并在依赖类中直接调用它。可以重写静态初始值设定项块以调用新创建的静态方法

try
{
  Class.forName(class name as string)
}
catch(ClassNotFoundException e)
{
  whatever
}
应该这样做

@朗普克

也许我误解了什么。您能否创建一个示例,其中加载了一个类,但未执行静态初始值设定项?下面是一个示例,它只打印已加载的内容:

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()
强制初始化


然而,这样做根本就是一种代码味道。考虑在一个单独的对象中用一个标准构造函数替换静态代码。

如果您需要静态初始化一个类中的某个类,这意味着必须有依赖于此的客户端类。 如果有一个客户机,或者我们称之为初始化块的自然主页,我认为在那里初始化它是最干净的


对于多个相等客户机的情况,最好从这些类验证另一个类中的静态初始化是否成功。然后记录耦合,确保在第一个客户端需要它之前初始化该类。

加载!=初始化

您希望初始化您的类(这是在执行静态块时进行的)

该报告的一段摘录说:

类或接口类型T将在第一次出现>以下任何一项之前立即初始化:

  • T是一个类,并且创建了T的一个实例
  • T是一个类,调用由T声明的静态方法
  • 分配了一个由T声明的静态字段
  • 使用T声明的静态字段,该字段不是常量变量(§4.12.4)
  • T是一个顶级类,执行嵌套在T中的assert语句(§14.10)
在类和包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;
} 
/。。。Foo.class//旧代码
... forceInit(Foo.class)//新代码
/**
*强制初始化与相关的类
*指定的类对象。
*如果该类已经存在,则此方法不执行任何操作
*在调用之前初始化。
*
*@param klass要强制初始化的类
*@返回克拉斯
*/
公共静态类forceInit(类klass){
试一试{
类.forName(klass.getName(),true,klass.getClassLoader());
}catch(classnotfounde异常){
抛出新断言错误(e);//不可能发生
}
返回克拉斯;
} 

我见过这种类型的建议:Class aClass=A.Class;但是它看起来有点难看,并且生成了一个未使用的变量警告。您可以使用
@SuppressWarnings(“unused”)
引用这样的类文本来抑制警告,这样不会导致类被初始化。在旧版本中,它是这样做的,但在Java 5中,它不是这样。@erickson尽管如果你使用
-source 1.4-target 1.4
编译,它仍然会在1.5+上初始化类。@Tom H。是的,但你为什么要这样做?+1引用规范!谢谢朗博克。这很有道理。请参阅我在上面关于使用此选项覆盖标志的评论。我当然可以在静态函数中这样做,我只是认为在静态块中设置静态变量更好…不必在静态块中设置变量,存在静态初始值设定项,因此可以使用多个语句初始化静态变量,而普通的静态变量声明(即:
static intx=123;static inty=newthing().getY();
)只能包含表达式。出于性能原因这样做怎么样?例如,在显示初始屏幕时强制进行静态初始化?这是一个非常特殊的用途。我希望有一组静态标志,可以覆盖以进行测试。有点像设置属性。将此初始化放在函数调用中会打开door表示在那里运行的所有类型的代码,但我宁愿将其限制为静态{DebugUtils.FLAG_TEST_USER=true;}所有可以在静态方法中运行的代码都可以在静态块中运行,对吗?它是如何被限制的?我想我很困惑…因为静态块通常都有变量初始化,所以我认为它是有限的。所以没有限制?@Artem:在静态块中,静态块几乎可以做任何事情保证在任何代码访问该类之前自动执行该类的。等等,我不知道这是否是因为您对我的答案的评论而提出的问题。对于其中一个,您可以使用class.forName的重载形式。第二个参数确定是否初始化该类。另一种可能性是使用Static.class获取对该类的引用,这不会引发初始化。非常感谢您向我解释它!我从未使用过t