Java: 静态初始化块什么时候有用?

static块中进行初始化有什么区别:

public class staticTest {


static String s;
static int n;
static double d;


static {
s = "I'm static";
n = 500;
d = 4000.0001;
}
...

以及个人静态初始化:

public class staticTest {


static String s = "I'm static";
static int n    = 500;
static double d = 4000.0001;


....
123629 次浏览

在你的例子中,没有什么不同; 但是通常初始值比在单个表达式中舒适地表达更复杂(例如,它是一个 List<String>,其内容最好由 for循环表达; 或者它是一个 Method,可能不存在,因此需要异常处理程序) ,和/或静态字段需要按照特定的顺序设置。

有时候,您需要做的不仅仅是为静态变量赋值。因为不能在类主体中放置任意语句,所以可以使用静态初始化器块。

静态初始化块允许更复杂的初始化,例如使用条件:

static double a;
static {
if (SomeCondition) {
a = 0;
} else {
a = 1;
}
}

Or when more than just construction is required: when using a builder to create your instance, exception handling or work other than creating static fields is necessary.

静态初始化块也在内联静态初始化器之后运行,因此以下内容是有效的:

static double a;
static double b = 1;


static {
a = b * 4; // Evaluates to 4
}

严格来说,没有它你也能逃脱。有些人更喜欢多行初始化代码进入静态方法。我很高兴使用静态初始化器来进行相对简单的多语句初始化。

当然,我几乎总是使我的静态 final和指向一个不可修改的对象。

一个典型的用法:

private final static Set<String> SET = new HashSet<String>();


static {
SET.add("value1");
SET.add("value2");
SET.add("value3");
}

如果没有静态初始化程序,您将如何做到这一点?

静态代码块允许使用多个指令初始化字段,按声明的不同顺序初始化字段,还可以用于条件初始化。

更确切地说,

static final String ab = a+b;
static final String a = "Hello,";
static final String b = ", world";

将不起作用,因为 a 和 b 是在 ab 之后声明的。

然而,我可以使用一个静态 init.block 来克服这个问题。

static final String ab;
static final String a;
static final String b;


static {
b = ", world";
a = "Hello";
ab = a + b;
}


static final String ab;
static final String a;
static final String b;


static {
b = (...) ? ", world" : ", universe";
a = "Hello";
ab = a + b;
}

初始化过程中的异常处理是另一个原因。例如:

static URL url;
static {
try {
url = new URL("https://blahblah.com");
}
catch (MalformedURLException mue) {
//log exception or handle otherwise
}
}

这对于像上面那样恼人地抛出已检查异常的构造函数很有用,或者对于可能容易出现异常的更复杂的初始化逻辑也很有用。

static block can be used to initialize 单身 instance, to prevent using 同步 getInstance() method.

静态关键字(无论是变量还是块)属于该类。因此,当调用该类时,将执行这些变量或块。所以大部分的初始化将在 static 关键字的帮助下完成。因为它属于类本身,所以类可以直接访问它,而不需要创建类的实例。

让我们举个例子,有一个鞋类 一些变量,如颜色,大小,品牌等 制造公司只有一个品牌比我们应该初始化为一个 静态变量。因此,当鞋类被调用时,不同的类型 (通过创建类的实例)在 时间,颜色和大小会占据记忆,每当新鞋 但在这里,品牌是所有鞋子的共同财产,因此它将 不管生产多少双鞋,都要占用记忆一次。

例如:

    class Shoe {
int size;
String colour;
static String brand = "Nike";


public Shoe(int size, String colour) {
super();
this.size = size;
this.colour = colour;
}


void displayShoe() {
System.out.printf("%-2d %-8s %s %n",size,colour, brand);
}


public static void main(String args[]) {
Shoe s1 = new Shoe(7, "Blue");
Shoe s2 = new Shoe(8, "White");


System.out.println("=================");
s1.displayShoe();
s2.displayShoe();
System.out.println("=================");
}
}

如果您希望在类首次使用之前初始化指定的类静态类型,那么静态初始化块非常有用。随后的使用不会调用任何静态初始化块。它与实例初始化器(初始化实例成员)正好相反。

我们使用构造函数有条件地初始化实例变量。

如果希望有条件地初始化类/静态变量,并且不想创建对象(只有在创建对象时才能调用构造函数) ,那么需要静态块。

static Scanner input = new Scanner(System.in);
static int widht;
static int height;


static
{
widht = input.nextInt();
input.nextLine();
height = input.nextInt();
input.close();


if ((widht < 0) || (height < 0))
{
System.out.println("java.lang.Exception: Width and height must be positive");
}
else
{
System.out.println("widht * height = " + widht * height);
}
}

你可以在 static{}中使用 try/catch 块,如下所示:

MyCode{


static Scanner input = new Scanner(System.in);
static boolean flag = true;
static int B = input.nextInt();
static int H = input.nextInt();


static{
try{
if(B <= 0 || H <= 0){
flag = false;
throw new Exception("Breadth and height must be positive");
}
}catch(Exception e){
System.out.println(e);
}


}
}

附注: 由 这个转载!

当你想在加载类的时候计算某个表达式时,你可以使用静态块,但是要记住:

必须在静态块中处理异常,这意味着不能从静态块引发异常。