在Java中匿名代码块有什么实际用途吗?
public static void main(String[] args) {
// in
{
// out
}
}
请注意,这不是关于命名块,即
name: {
if ( /* something */ )
break name;
}
。
发布于 2009-10-13 21:36:31
它们限制变量的作用域。
public void foo()
{
{
int i = 10;
}
System.out.println(i); // Won't compile.
}
但在实践中,如果您发现自己在使用这样的代码块,这可能是您想要将该块重构为一个方法的信号。
发布于 2013-06-17 06:37:35
通常最好的方法是使用make the scope of local variables as small as possible。匿名代码块可以帮助实现这一点。
我发现这对switch
语句特别有用。考虑下面的示例,不使用匿名代码块:
public String manipulate(Mode mode) {
switch(mode) {
case FOO:
String result = foo();
tweak(result);
return result;
case BAR:
String result = bar(); // Compiler error
twiddle(result);
return result;
case BAZ:
String rsult = bar(); // Whoops, typo!
twang(result); // No compiler error
return result;
}
}
和匿名代码块:
public String manipulate(Mode mode) {
switch(mode) {
case FOO: {
String result = foo();
tweak(result);
return result;
}
case BAR: {
String result = bar(); // No compiler error
twiddle(result);
return result;
}
case BAZ: {
String rsult = bar(); // Whoops, typo!
twang(result); // Compiler error
return result;
}
}
}
我认为第二个版本更干净,更容易阅读。而且,它将在switch中声明的变量的范围缩小到它们声明时的情况,根据我的经验,这是99%的情况下您想要的。
但是请注意,这不会改变失败的行为-您仍然需要记住包括一个break
或return
来防止它!
发布于 2009-10-13 23:10:29
我认为你和/或其他答案混淆了两个不同的语法结构;即实例初始化器和块。(顺便说一句,“命名块”实际上是一个带标签的语句,其中的语句恰好是一个块。)
实例初始化器在类成员的语法级别上使用;
public class Test {
final int foo;
{
// Some complicated initialization sequence; e.g.
int tmp;
if (...) {
...
tmp = ...
} else {
...
tmp = ...
}
foo = tmp;
}
}
根据@dfa的示例,Initializer构造最常用于匿名类。另一个用例是对'final‘属性进行复杂的初始化;例如,参见上面的示例。(但是,更常见的做法是使用常规构造函数。上面的模式更常用于静态初始化器。)
另一个结构是一个普通的块,出现在一个代码块中,比如method;
public void test() {
int i = 1;
{
int j = 2;
...
}
{
int j = 3;
...
}
}
块最常用作控制语句的一部分,用于对一系列语句进行分组。但是当你在上面使用它们时,它们(只是)允许你限制声明的可见性;例如上面的j
。
这通常意味着你需要重构你的代码,但它并不总是清晰的。例如,您有时会在用Java编写的解释器中看到这种事情。切换臂中的语句可以分解到单独的方法中,但这可能会对解释器的“内部循环”造成显著的性能影响;
switch (op) {
case OP1: {
int tmp = ...;
// do something
break;
}
case OP2: {
int tmp = ...;
// do something else
break;
}
...
};
https://stackoverflow.com/questions/1563030
复制相似问题