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

Java-静态初始值设定项与静态变量的默认值,java,static,Java,Static,我读了一些Java类的书,发现了静态初始值设定项。但是,当您可以首先设置默认值时,我看不到使用它们的意义。 比如说, static int a; static { a = 5; } 对 static int a = 5 在类定义中 这两者之间有区别吗?如果没有,您什么时候会使用静态初始值设定项与默认值?没有区别 什么时候使用静态初始值设定项而不是默认值 当计算表达式的代码更复杂时,尤其是当涉及异常时 static int a ; static { String x = Sy

我读了一些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+\\]");
}
//在生物文件解析期间使用的初始内存值模式
专用静态模式存储器匹配器;
私有静态模式匹配器;
私有静态模式generalMemoryMatcher;
//块来创建内存匹配器
静止的{
最终StringBuilder=新StringBuilder();
//附加每个糖值,用管道分隔
建造商。附加(“(?i)(”);
for(最终糖:Sugar.values()){
append(sugar.toString());
builder.append(“|”);
}
//用右括号替换最终管道,并创建sugarMatcher
sugarMatcher=Pattern.compile(builder.replace(
builder.length()-1,builder.length(),“”“).toString();
//添加一些内容以捕获“:”和空格,然后
//创建内存匹配器
memoryMatcher=Pattern.compile(builder.insert(4)(“”)
.insert(builder.length()-1,“| mem\\[-?\\d+\\\]”)
.append(“:\\s*-?\\d*|\\s*)”).toString();
//应该匹配mem[]
generalMemoryMatcher=Pattern.compile(“mem\\[-?\\d+\\\]”;
}
在Java8之前,涉及
for
循环的代码,我不认为能够作为单个赋值的一部分工作。虽然Java8的streams允许我将此作为任务的一部分,但
memoryMatcher
sugarMatcher
的工作将复制一些工作,这并不是真正需要的

Is there a difference between these two?
不,在本例中,是您共享的代码

如果不是,您什么时候会使用静态初始值设定项而不是默认值


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

这两者之间有区别吗?

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

如果没有,什么时候使用静态初始值设定项与默认值比较?

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

静态初始化块是一个普通的代码块,用大括号括起来,{},前面有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
    }
}

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

没有区别。事实上,编译器为您将简短形式更改为声明加静态块。如果在生成的类上运行“javap”,则它们是相同的

JDK中附带编译器的“javap”工具是查看代码并准确了解“区别”的好方法

javap-c测试类

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
}
从“Test.java”编译而来
公开课考试{
静态int a;
静态{};
代码:
0:iconst_5
1:putstatic#10//字段a:I
4:返回
公开考试();
代码:
0:aload_0
1:invokespecial#15//方法java/lang/Object。“:()V
4:返回
}
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
}