我正在阅读有关Java类的一些内容,并且我遇到了静态初始化器。但是,当你可以在第一时间设置默认值时,我看不到使用它们的意义。 例如,
static int a;
static {
a = 5;
}
与
static int a = 5
在类定义中。
这两者有区别吗?如果不是,您何时使用静态初始值设定项与默认值?
答案 0 :(得分:4)
没有区别。
何时使用静态初始值设定项与默认值?
当评估表达式的代码更复杂时,尤其是涉及异常时。
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();
答案 1 :(得分:2)
这两者之间有区别吗?
不在您发布的示例中。但是static {}
表单可以包含任意代码,包括循环,try / catch等。
如果不是,您何时使用静态初始值设定项与默认值?
当您需要额外功能时。
答案 2 :(得分:1)
如果有记忆,那就没有效果了。但是,静态块有助于实现可读性,或者用于执行多个步骤的任务。从我大学一年级的这个(坏)例子开始:
// 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的流可以让我在作业中执行此操作,但memoryMatcher
和sugarMatcher
的工作会复制一些工作,这是不可取的。
答案 3 :(得分:1)
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
}
}
私有静态方法的优点是,如果需要重新初始化类变量,它们可以在以后重用。
答案 4 :(得分:0)
Is there a difference between these two?
不,在这种情况下,您共享的代码
如果不是,您何时使用静态初始值设定项与默认值?
在许多场景中,如果您的应用程序只需要一个对象实例,则需要使用静态初始化程序。您可以使用静态块来实现如何获取单个实例的逻辑。
答案 5 :(得分:0)
没有区别。实际上,编译器会将短格式更改为声明加静态块。如果在结果类上运行“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
}