Java:什么是静态{}?

发布于 2024-08-11 08:47:28 字数 414 浏览 1 评论 0原文

有人能给我解释一下下面是什么吗?

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

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

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

这东西什么时候才能执行?

Can someone explain me what the following is?

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

What does this static { ...} do?

I know about static variables from C++, but is that a static block or something?

When is this stuff going to get executed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

小红帽 2024-08-18 08:47:29

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

例如,与构造函数相反,静态初始值设定项不是继承的,并且仅在 JRE 加载和初始化类时执行一次。在上面的示例中,初始化完成后,类变量 foo 的值为 998877。

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

The primary use of static initializers blocks are to do various bits of initialization that may not be appropriate inside a constructor such that taken together the constructor and initializers put the newly created object into a state that is completely consistent for use.

In contrast to constructors, for example, static initializers aren't inherited and are only executed once when the class is loaded and initialized by the JRE. In the example above, the class variable foo will have the value 998877 once initialization is complete.

Note also that static initializers are executed in the order in which they appear textually in the source file. Also, there are a number of restrictions on what you can't do inside one of these blocks such as no use of checked exceptions, no use of the return statement or the this and super keywords.

花辞树 2024-08-18 08:47:29

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

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 版本的闭包时很有用。

I want to add that static variables and static initializers are executed in order of appearance at the time of class loading. So, if your static initializer relies on some static variable, it must be initialized before the particular static block, e.g.

final static String JDBC_DRIVER = getJdbcDriver( );

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

In this example getJdbcDriver will get executed before static initializer. Also, there may be more than 1 static initializer in the class. Once again they are executed in order of appearance.

I also want to mention the existence of instance initializers here, as they do come as surprise when seen for the first time. They look like a code block inside the class body, like this.

class MyClass
{
  final int intVar;

  {
    intVar = 1;
  }
}

In general case their use is somewhat unnecessary, because of the constructor, but they are useful in implementing Java's version of closures.

明天过后 2024-08-18 08:47:29

每当第一次加载类时,都会执行静态初始化块。如果更高级别的操作第一次对相关类执行 Class#forName("yourpackage.YourClass")new YourClass() ,则可能会发生这种情况。

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

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

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

The static initializer block get executed whenever the class is to be loaded for the first time. That can happen if something at higher level is doing a Class#forName("yourpackage.YourClass") or a new YourClass() on the class in question for the first time.

By a coincidence, the decent JDBC drivers also have something similar inside. They namely registers themselves in the DriverManager using a static initializer block:

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

so that whenever you do a Class.forName("somepackage.ThisDriver"), you will effectively register the driver in the DriverManager so that you can get a connection from it afterwards.

往昔成烟 2024-08-18 08:47:29

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

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

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

In addition to all above , there is a minute difference in using class constructor and class initializer. Constructor as we know that will be usually used to initialized the objects and if we have static variables then static block is usually used in order to initialize them when the class will be loaded.

When we have static variables and static block then static variables initialized first and then the block.

When class is first loaded, static block initializes before the class constructor.

咽泪装欢 2024-08-18 08:47:29

静态初始化块

  • 是一个普通的代码块

  • 它用大括号 { } 括起来

  • 它前面有 static 关键字

    类 Foo {
        静止的 {
            // 初始化代码放在这里:
            做某事();
        }
    }
    
  • 类可以有任意数量的静态初始化块

  • 它们可以出现在类中的任何位置body

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

有一种替代静态初始化块的方法:

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

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

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

    private static int initializeClassVariable() {
        // initialization code goes here:
        int v = 255;
        return v;
    }
}

static initialization block

  • is a normal block of code

  • it is enclosed in braces { }

  • it is preceded by the static keyword

    class Foo {
        static {
            // initialization code goes here:
            doSomething();
        }
    }
    
  • class can have any number of static initialization blocks

  • they can appear anywhere in the class body

  • they are called in the order of apperence in the code

There is an alternative to static initialization blocks:

  • write a private static method
  • and assign it to the static class variable

The advantage of this approach is that the static method can be invoked later to reinitialize the class variable.

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

    private static int initializeClassVariable() {
        // initialization code goes here:
        int v = 255;
        return v;
    }
}
太阳公公是暖光 2024-08-18 08:47:28

静态块称为 类静态初始值设定项 - 它在类第一次加载时运行(也是唯一一次运行[脚注])。

该特定块的目的是检查 MySQL 驱动程序是否位于类路径上(并抛出/log 错误(如果不是)。


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

The static block is called a class static initializer - it gets run the first time the class is loaded (and it's the only time it's run [footnote]).

The purpose of that particular block is to check if the MySQL driver is on the classpath (and throw/log error if it's not).


[footnote] The static block run once per classloader that loads the class (so if you had multiple class loaders that are distinct from each other (e.g. doesn't delegate for example), it will be executed once each.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文