繁体   English   中英

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

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

我正在读Java类,我遇到了静态初始化器。 但是,当你可以在第一时间设置默认值时,我看不到使用它们的意义。 例如,

static int a;
static {
    a = 5;
} 

static int a = 5

在类定义中。

这两者有区别吗? 如果不是,您何时使用静态初始化程序与默认值?

没有不同。

什么时候使用静态初始化程序与默认值?

当评估表达式的代码更复杂时,尤其是涉及异常时。

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);
    }
}

但是,将代码移动到私有静态方法可能是最佳实践。

final static int a = complexCalculation();

这两者有区别吗?

不在您发布的示例中。 但是static {}表单可以包含任意代码,包括循环,try / catch等。

如果不是,您何时使用静态初始化程序与默认值?

当您需要额外功能时。

如果记忆服务,则没有有效的区别。 但是,静态块有助于实现可读性,或者用于执行多个步骤的任务。 从我大学一年级的这个(坏)例子来看:

// 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+\\]");
}

在Java 8之前,涉及for循环的代码我不相信能够作为单个赋值的一部分工作。 虽然Java 8的流可以让我这样做作为赋值的一部分,但memoryMatchersugarMatcher的工作会复制一些工作,这是不太理想的。

Is there a difference between these two?

不,在这种情况下,没有区别,因为在静态初始化程序块中,您只是为变量赋值。但在某些非常复杂的情况下,情况可能并非如此。

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

当初始化值可用并且初始化可以放在一行上时,这很有效。 然而,这种形式的初始化由于其简单性而具有局限性。 如果初始化需要一些逻辑(例如,错误处理或for循环来填充复杂的数组),则简单的赋值是不合适的。

静态初始化块是用大括号{}括起来的常规代码块,前面是static关键字。 这是一个例子:

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

一个类可以有任意数量的静态初始化块,它们可以出现在类体中的任何位置。 运行时系统保证按照它们在源代码中出现的顺序调用静态初始化块。

静态块有一个替代方法 - 您可以编写一个私有静态方法:

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

    private static varType initializeClassVariable() {

        // initialization code goes here
    }
}

私有静态方法的优点是,如果需要重新初始化类变量,它们可以在以后重用。

Is there a difference between these two?

不,在这种情况下,您共享的代码

如果不是,您何时使用静态初始化程序与默认值?

在许多情况下,如果应用程序只需要一个对象实例,则需要静态初始化程序。 您可以使用静态块,您可以在其中实现如何获取单个实例的逻辑。

没有区别。 实际上,编译器会将短格式更改为声明加静态块。 如果在结果类上运行“javap”,它们是相同的。

使用编译器在JDK中提供的“javap”工具是查看代码并确切知道“有什么区别”的好方法!

public class Test {

    //static int a= 5;

    static int a;
    static {
        a = 5;
    }

}

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