简体   繁体   English

Java - 静态初始值设定项与静态变量的默认值

[英]Java - Static initializers versus default values for static variables

I was doing some reading on Java classes, and I came upon static initializers. 我正在读Java类,我遇到了静态初始化器。 However, I can't see the point of using them when you can just set default values in the first place. 但是,当你可以在第一时间设置默认值时,我看不到使用它们的意义。 For example, 例如,

static int a;
static {
    a = 5;
} 

versus

static int a = 5

in a class definition. 在类定义中。

Is there a difference between these two? 这两者有区别吗? If not, when would you use static initializers versus default values? 如果不是,您何时使用静态初始化程序与默认值?

No difference. 没有不同。

when would you use static initializers versus default values? 什么时候使用静态初始化程序与默认值?

When the code to evaluate the expression is more complex, especially if exceptions are involved. 当评估表达式的代码更复杂时,尤其是涉及异常时。

static int a ;
static {
    String x = System.getProperty("abc");
    try{  
       a = Integer.parseInt(x);
    }
    catch (Exception e){
       throw new IllegalArgumentException
          ("missing or invalid system property 'abc': "+x);
    }
}

But then it is probably best practice to move the code into a private static method. 但是,将代码移动到私有静态方法可能是最佳实践。

final static int a = complexCalculation();

Is there a difference between these two? 这两者有区别吗?

Not in the example you posted. 不在您发布的示例中。 However the static {} form can include arbitrary code including loops, try/catch, etc. 但是static {}表单可以包含任意代码,包括循环,try / catch等。

If not, when would you use static initializers versus default values? 如果不是,您何时使用静态初始化程序与默认值?

When you need the extra features. 当您需要额外功能时。

If memory serves, there's no effective difference. 如果记忆服务,则没有有效的区别。 However, a static block can be helpful for readability purposes, or for doing tasks which take multiple steps. 但是,静态块有助于实现可读性,或者用于执行多个步骤的任务。 Take this (bad) example from my freshman year of college: 从我大学一年级的这个(坏)例子来看:

// Pattern of initial memory values, used during critter file parsing
private static Pattern memoryMatcher;
private static Pattern sugarMatcher;
private static Pattern generalMemoryMatcher;
// Block to create memoryMatcher
static {
    final StringBuilder builder = new StringBuilder();

    // Append each of the sugar values, separated by a pipe
    builder.append("(?i)(");
    for (final Sugar sugar : Sugar.values()) {
        builder.append(sugar.toString());
        builder.append("|");
    }

    // Replace final pipe with close parenthesis and create sugarMatcher
    sugarMatcher = Pattern.compile(builder.replace(
            builder.length() - 1, builder.length(), ")").toString());

    // Append some stuff to catch ": <number>" and whitespace, then
    // create memoryMatcher
    memoryMatcher = Pattern.compile(builder.insert(4, "(")
            .insert(builder.length() - 1, "|mem\\[-?\\d+\\]")
            .append(":\\s*-?\\d*|\\s*)").toString());

    // Should match mem[<number>]
    generalMemoryMatcher = Pattern.compile("mem\\[-?\\d+\\]");
}

Prior to Java 8, the code that involves the for loop I don't believe would be able to work as part of a single assignment. 在Java 8之前,涉及for循环的代码我不相信能够作为单个赋值的一部分工作。 While Java 8's streams would let me do this as part of an assignment, the work for memoryMatcher and sugarMatcher would replicate some work, which isn't really desirable. 虽然Java 8的流可以让我这样做作为赋值的一部分,但memoryMatchersugarMatcher的工作会复制一些工作,这是不太理想的。

Is there a difference between these two?

No, In this case there is no difference as in your static initializer block you are just assigning a value to a variable.But in some very complex scenarios this may not be the case. 不,在这种情况下,没有区别,因为在静态初始化程序块中,您只是为变量赋值。但在某些非常复杂的情况下,情况可能并非如此。

If not, when would you use static initializers versus default values?

This works well when the initialization value is available and the initialization can be put on one line. 当初始化值可用并且初始化可以放在一行上时,这很有效。 However, this form of initialization has limitations because of its simplicity. 然而,这种形式的初始化由于其简单性而具有局限性。 If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. 如果初始化需要一些逻辑(例如,错误处理或for循环来填充复杂的数组),则简单的赋值是不合适的。

A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. 静态初始化块是用大括号{}括起来的常规代码块,前面是static关键字。 Here is an example: 这是一个例子:

static {
    // whatever code is needed for initialization goes here
}

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. 一个类可以有任意数量的静态初始化块,它们可以出现在类体中的任何位置。 The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code. 运行时系统保证按照它们在源代码中出现的顺序调用静态初始化块。

There is an alternative to static blocks — you can write a private static method: 静态块有一个替代方法 - 您可以编写一个私有静态方法:

class Whatever {
    public static varType myVar = initializeClassVariable();

    private static varType initializeClassVariable() {

        // initialization code goes here
    }
}

The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable. 私有静态方法的优点是,如果需要重新初始化类变量,它们可以在以后重用。

Is there a difference between these two?

No, in this case the code that you shared 不,在这种情况下,您共享的代码

If not, when would you use static initializers versus default values? 如果不是,您何时使用静态初始化程序与默认值?

There are many scenarios, you need static initializers like , in case your application needs only one instance of an object. 在许多情况下,如果应用程序只需要一个对象实例,则需要静态初始化程序。 You can use static block in which you can implement the logic for how to get the single instance. 您可以使用静态块,您可以在其中实现如何获取单个实例的逻辑。

There is no difference. 没有区别。 In fact, the compiler changes the short form into a declaration-plus-static-block for you. 实际上,编译器会将短格式更改为声明加静态块。 If you run "javap" on the resulting classes they are identical. 如果在结果类上运行“javap”,它们是相同的。

The "javap" tool that comes in the JDK with the compiler is a great way to look at the code and know exactly "what is the difference"! 使用编译器在JDK中提供的“javap”工具是查看代码并确切知道“有什么区别”的好方法!

public class Test {

    //static int a= 5;

    static int a;
    static {
        a = 5;
    }

}

javap -c Test.class javap -c Test.class

Compiled from "Test.java"
public class Test {
  static int a;

  static {};
    Code:
       0: iconst_5
       1: putstatic     #10                 // Field a:I
       4: return

  public Test();
    Code:
       0: aload_0
       1: invokespecial #15                 // Method java/lang/Object."<init>":()V
       4: return
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM