Java 静态初始化块

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2420389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:23:09  来源:igfitidea点击:

Static Initialization Blocks

javastaticinitializationstatic-blockinitialization-block

提问by Roman

As far as I understood the "static initialization block" is used to set values of static field if it cannot be done in one line.

据我所知,如果不能在一行中完成,则“静态初始化块”用于设置静态字段的值。

But I do not understand why we need a special block for that. For example we declare a field as static (without a value assignment). And then write several lines of the code which generate and assign a value to the above declared static field.

但我不明白为什么我们需要一个特殊的块。例如,我们将一个字段声明为静态(没有赋值)。然后编写几行代码,为上面声明的静态字段生成并赋值。

Why do we need this lines in a special block like: static {...}?

为什么我们需要在特殊块中使用此行,例如:static {...}

采纳答案by Frederik Wordenskjold

The non-static block:

非静态块:

{
    // Do Something...
}

Gets called every timean instance of the class is constructed. The static blockonly gets called once, when the class itself is initialized, no matter how many objects of that type you create.

每次构造类的实例时调用。在静态块只被调用一次,当类本身初始化,无论该类型的有多少对象创建。

Example:

例子:

public class Test {

    static{
        System.out.println("Static");
    }

    {
        System.out.println("Non-static block");
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test t2 = new Test();
    }
}

This prints:

这打印:

Static
Non-static block
Non-static block

回答by Pierre-Antoine LaFayette

You can execute bits of code once for a class before an object is constructed in the static blocks.

在静态块中构造对象之前,您可以为类执行一次代码位。

E.g.

例如

class A {
  static int var1 = 6;
  static int var2 = 9;
  static int var3;
  static long var4;

  static Date date1;
  static Date date2;

  static {
    date1 = new Date();

    for(int cnt = 0; cnt < var2; cnt++){
      var3 += var1;
    }

    System.out.println("End first static init: " + new Date());
  }
}

回答by Pointy

Here's an example:

下面是一个例子:

  private static final HashMap<String, String> MAP = new HashMap<String, String>();
  static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

The code in the "static" section(s) will be executed at class load time, before any instances of the class are constructed (and before any static methods are called from elsewhere). That way you can make sure that the class resources are all ready to use.

“静态”部分中的代码将在类加载时执行,在构造类的任何实例之前(以及在从其他地方调用任何静态方法之前)。这样您就可以确保类资源都可以使用了。

It's also possible to have non-static initializer blocks. Those act like extensions to the set of constructor methods defined for the class. They look just like static initializer blocks, except the keyword "static" is left off.

也可以有非静态初始化块。这些就像对为类定义的构造函数方法集的扩展。它们看起来就像静态初始化程序块,只是省略了关键字“static”。

回答by Jon Skeet

If they weren't in a static initialization block, where would they be? How would you declare a variable which was only meant to be local for the purposes of initialization, and distinguish it from a field? For example, how would youwant to write:

如果它们不在静态初始化块中,它们会在哪里?您如何声明一个仅用于初始化目的的局部变量,并将其与字段区分开来?例如,想怎么写:

public class Foo {
    private static final int widgets;

    static {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        widgets = first + second;
    }
}

If firstand secondweren't in a block, they'd look like fields. If they were in a block without staticin front of it, that would count as an instance initialization block instead of a static initialization block, so it would be executed once perconstructed instance rather than once in total.

如果first并且second不在一个块中,它们看起来就像字段。如果它们在一个没有static前面的块中,那将被视为实例初始化块而不是静态初始化块,因此每个构造的实例将执行一次而不是总共执行一次。

Now in this particular case, you could use a static method instead:

现在在这种特殊情况下,您可以改用静态方法:

public class Foo {
    private static final int widgets = getWidgets();

    static int getWidgets() {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        return first + second;
    }
}

... but that doesn't work when there are multiple variables you wish to assign within the same block, or none (e.g. if you just want to log something - or maybe initialize a native library).

...但是当您希望在同一个块中分配多个变量或没有(例如,如果您只想记录某些内容 - 或者可能初始化本机库)时,这不起作用。

回答by Marcus Leon

If your static variables need to be set at runtime then a static {...}block is very helpful.

如果您的静态变量需要在运行时设置,那么static {...}块非常有用。

For example, if you need to set the static member to a value which is stored in a config file or database.

例如,如果您需要将静态成员设置为存储在配置文件或数据库中的值。

Also useful when you want to add values to a static Mapmember as you can't add these values in the initial member declaration.

当您想向静态Map成员添加值时也很有用,因为您无法在初始成员声明中添加这些值。

回答by BalusC

It's also useful when you actually don't want to assign the value to anything, such as loading some class only onceduring runtime.

当您实际上不想将值分配给任何东西时,它也很有用,例如在运行时加载某个类一次

E.g.

例如

static {
    try {
        Class.forName("com.example.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
    }
}

Hey, there's another benefit, you can use it to handle exceptions. Imagine that getStuff()here throws an Exceptionwhich reallybelongs in a catch block:

嘿,还有一个好处,你可以用它来处理异常。试想一下,getStuff()在这里抛出Exception真的属于一个catch块:

private static Object stuff = getStuff(); // Won't compile: unhandled exception.

then a staticinitializer is useful here. You can handle the exception there.

那么static初始化器在这里很有用。您可以在那里处理异常。

Another example is to do stuff afterwards which can't be done during assigning:

另一个例子是之后做一些在分配期间无法完成的事情:

private static Properties config = new Properties();

static {
    try { 
        config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
    } catch (IOException e) {
        throw new ExceptionInInitializerError("Cannot load properties file.", e);
    }
}

To come back to the JDBC driver example, any decent JDBC driver itself also makes use of the staticinitializer to register itself in the DriverManager. Also see thisand thisanswer.

回到 JDBC 驱动程序示例,任何合适的 JDBC 驱动程序本身也使用static初始化程序在DriverManager. 另请参阅答案。

回答by D.Shawley

There are a few actual reasons that it is required to exist:

有几个实际原因需要它存在:

  1. initializing static finalmembers whose initialization might throw an exception
  2. initializing static finalmembers with calculated values
  1. 初始化static final可能引发异常的成员
  2. static final用计算值初始化成员

People tend to use static {}blocks as a convenient way to initialize things that the class depends on within the runtime as well - such as ensuring that particular class is loaded (e.g., JDBC drivers). That can be done in other ways; however, the two things that I mention above can only be done with a construct like the static {}block.

人们倾向于使用static {}块作为一种方便的方式来初始化该类在运行时内所依赖的东西 - 例如确保加载特定的类(例如,JDBC 驱动程序)。这可以通过其他方式完成;然而,我上面提到的两件事只能通过像static {}块这样的构造来完成。

回答by Arun

static block is used for any technology to initialize static data member in dynamic way,or we can say for the dynamic initialization of static data member static block is being used..Because for non static data member initialization we have constructor but we do not have any place where we can dynamically initialize static data member

静态块用于任何以动态方式初始化静态数据成员的技术,或者我们可以说静态数据成员的动态初始化正在使用静态块..因为对于非静态数据成员初始化我们有构造函数但我们没有我们可以动态初始化静态数据成员的任何地方

Eg:-class Solution{
         // static int x=10;
           static int x;
       static{
        try{
          x=System.out.println();
          }
         catch(Exception e){}
        }
       }

     class Solution1{
      public static void main(String a[]){
      System.out.println(Solution.x);
        }
        }

Now my static int x will initialize dynamically ..Bcoz when compiler will go to Solution.x it will load Solution Class and static block load at class loading time..So we can able to dynamically initialize that static data member..

现在我的静态 int x 将动态初始化 ..Bcoz 当编译器将转到 Solution.x 它将在类加载时加载解决方案类和静态块加载..所以我们可以动态初始化该静态数据成员..

}

}

回答by user1508893

I would say static blockis just syntactic sugar. There is nothing you could do with staticblock and not with anything else.

我会说static block只是语法糖。你不能用static块做任何事情,而不能用其他任何东西。

To re-use some examples posted here.

重用这里发布的一些示例。

This piece of code could be re-written without using staticinitialiser.

这段代码可以在不使用static初始化程序的情况下重写。

Method #1: With static

方法#1:使用 static

private static final HashMap<String, String> MAP;
static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

Method #2: Without static

方法#2:没有 static

private static final HashMap<String, String> MAP = getMap();
private static HashMap<String, String> getMap()
{
    HashMap<String, String> ret = new HashMap<>();
    ret.put("banana", "honey");
    ret.put("peanut butter", "jelly");
    ret.put("rice", "beans");
    return ret;
}

回答by Randa Sbeity

So you have a static field (it's also called "class variable" because it belongs to the class rather than to an instance of the class; in other words it's associated with the class rather than with any object) and you want to initialize it. So if you do NOT want to create an instance of this class and you want to manipulate this static field, you can do it in three ways:

所以你有一个静态字段(它也被称为“类变量”,因为它属于类而不是类的实例;换句话说,它与类而不是任何对象相关联)并且你想要初始化它。因此,如果您不想创建此类的实例,而想操作此静态字段,则可以通过三种方式进行操作:

1- Just initialize it when you declare the variable:

1- 只需在声明变量时初始化它:

static int x = 3;

2- Have a static initializing block:

2- 有一个静态初始化块:

static int x;

static {
 x=3;
}

3- Have a class method (static method) that accesses the class variable and initializes it: this is the alternative to the above static block; you can write a private static method:

3-有一个访问类变量并初始化它的类方法(静态方法):这是上述静态块的替代方法;您可以编写一个私有静态方法:

public static int x=initializeX();

private static int initializeX(){
 return 3;
}

Now why would you use static initializing block instead of static methods?

现在为什么要使用静态初始化块而不是静态方法?

It's really up to what you need in your program. But you have to know that static initializing block is called once and the only advantage of the class method is that they can be reused later if you need to reinitialize the class variable.

这真的取决于你在你的程序中需要什么。但是你必须知道静态初始化块被调用一次,类方法的唯一优点是如果你需要重新初始化类变量,它们可以被重用。

let's say you have a complex array in your program. You initialize it (using forloop for example) and then the values in this array will change throughout the program but then at some point you want to reinitialize it (go back to the initial value). In this case you can call the private static method. In case you do not need in your program to reinitialize the values, you can just use the static block and no need for a static method since you're not gonna use it later in the program.

假设您的程序中有一个复杂的数组。你初始化它(例如使用for循环),然后这个数组中的值将在整个程序中改变,但在某个时候你想重新初始化它(回到初始值)。在这种情况下,您可以调用私有静态方法。如果您不需要在您的程序中重新初始化值,您可以只使用静态块而不需要静态方法,因为您以后不会在程序中使用它。

Note: the static blocks are called in the order they appear in the code.

注意:静态块按照它们在代码中出现的顺序被调用。

Example 1:

示例 1:

class A{
 public static int a =f();

// this is a static method
 private static int f(){
  return 3;
 }

// this is a static block
 static {
  a=5;
 }

 public static void main(String args[]) {
// As I mentioned, you do not need to create an instance of the class to use the class variable
  System.out.print(A.a); // this will print 5
 }

}

Example 2:

示例 2:

class A{
 static {
  a=5;
 }
 public static int a =f();

 private static int f(){
  return 3;
 }

 public static void main(String args[]) {
  System.out.print(A.a); // this will print 3
 }

}