6

有人可以解释一下下面是什么吗?

public class Stuff
{
    static
    {
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
        }
        catch ( ClassNotFoundException exception )
        {
            log.error( "ClassNotFoundException " + exception.getMessage( ) );
        }
...
}

这个 static { ...} 有什么作用?

我知道 C++ 中的静态变量,但那是静态块还是什么?

这玩意什么时候执行?

4

6 回答 6

14

静态块称为类静态初始化器——它在类第一次加载时运行(也是唯一一次运行[脚注])。

该特定块的目的是检查MySQL驱动程序是否在类路径上(如果不在则抛出/记录错误)。


[脚注] 每个加载类的类加载器都会运行一次静态块(因此,如果您有多个彼此不同的类加载器(例如,不委托),它将每个执行一次。

于 2009-11-15T10:59:56.803 回答
8

静态初始化块的主要用途是在构造函数中执行可能不适合的各种初始化,以便将构造函数和初始化程序一起将新创建的对象置于完全一致的状态以供使用。

例如,与构造函数相比,静态初始化程序不会被继承,并且只会在 JRE 加载和初始化类时执行一次。在上面的示例中,一旦初始化完成,类变量 foo 的值将是 998877。

另请注意,静态初始化程序按照它们在源文件中以文本形式出现的顺序执行。此外,在其中一个块中不能执行的操作有许多限制,例如不使用检查异常、不使用 return 语句或 this 和 super 关键字。

于 2009-11-15T11:21:21.567 回答
1

我想补充一点,静态变量和静态初始化程序在类加载时按出现顺序执行。因此,如果您的静态初始化程序依赖于某个静态变量,则必须在特定静态块之前对其进行初始化,例如

final static String JDBC_DRIVER = getJdbcDriver( );

static
{
  try
  {
    Class.forName(JDBC_DRIVER);
  }
  catch ( ClassNotFoundException exception )
  {
    log.error( "ClassNotFoundException " + exception.getMessage( ) );
  }
}

在此示例getJdbcDriver中,将在静态初始化程序之前执行。此外,类中可能有超过 1 个静态初始化程序。它们再次按出现的顺序执行。

我还想在这里提到实例初始值设定项的存在,因为第一次看到它们时确实会感到惊讶。它们看起来像类体内的代码块,就像这样。

class MyClass
{
  final int intVar;

  {
    intVar = 1;
  }
}

在一般情况下,由于构造函数的原因,它们的使用在某种程度上是不必要的,但它们在实现 Java 版本的闭包时很有用。

于 2009-11-15T12:36:02.750 回答
1

每当第一次加载类时,都会执行静态初始化程序块。如果更高级别的某事第一次在相关课程上做 aClass#forName("yourpackage.YourClass")或 a时,就会发生这种情况new YourClass()

巧合的是,不错的 JDBC 驱动程序内部也有类似的东西。他们即在DriverManager使用静态初始化程序块中注册自己:

static {
    DriverManager.registerDriver(new ThisDriver());
}

这样每当您执行 a 时Class.forName("somepackage.ThisDriver"),您将有效地在 中注册驱动程序,DriverManager以便您之后可以从中获得连接。

于 2009-11-15T12:53:14.520 回答
1

除了以上所有内容之外,使用类构造函数和类初始值设定项也有细微差别。我们知道构造函数通常用于初始化对象,如果我们有静态变量,则通常使用静态块来在加载类时初始化它们。

当我们有静态变量和静态块时,静态变量首先初始化,然后是块。

首次加载类时,静态块在类构造函数之前初始化。

于 2012-06-02T05:25:10.637 回答
0

静态初始化块

  • 是一个普通的代码块

  • 它用大括号 { } 括起来

  • 它前面是 static 关键字

    class Foo {
        static {
            // initialization code goes here:
            doSomething();
        }
    }
    
  • 类可以有任意数量的静态初始化块

  • 它们可以出现在类主体的任何位置

  • 它们按代码中的出现顺序调用

静态初始化块有另一种选择:

  • 写一个私有静态方法
  • 并将其分配给静态类变量

这种方法的优点是可以稍后调用静态方法来重新初始化类变量。

class Foo {
    public static int myVar = initializeClassVariable();

    private static int initializeClassVariable() {
        // initialization code goes here:
        int v = 255;
        return v;
    }
}
于 2016-06-01T12:04:39.150 回答