Java中是否存在匿名代码块的实际用途?
public static void main(String[] args) {
// in
{
// out
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这不是关于命名块,即
name: {
if ( /* something */ )
break name;
}
Run Code Online (Sandbox Code Playgroud)
.
Dav*_*ler 123
它们限制了变量范围.
public void foo()
{
{
int i = 10;
}
System.out.println(i); // Won't compile.
}
Run Code Online (Sandbox Code Playgroud)
但实际上,如果你发现自己使用了这样一个代码块,那可能就是你想要将那个块重构为一个方法的迹象.
Ste*_*sen 43
@David Seiler的答案是正确的,但我认为代码块非常有用,应该经常使用,并不一定表明需要考虑到方法.我发现它们对于构造Swing组件树特别有用,例如:
JPanel mainPanel = new JPanel(new BorderLayout());
{
JLabel centerLabel = new JLabel();
centerLabel.setText("Hello World");
mainPanel.add(centerLabel, BorderLayout.CENTER);
}
{
JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0,0));
{
JLabel label1 = new JLabel();
label1.setText("Hello");
southPanel.add(label1);
}
{
JLabel label2 = new JLabel();
label2.setText("World");
southPanel.add(label2);
}
mainPanel.add(southPanel, BorderLayout.SOUTH);
}
Run Code Online (Sandbox Code Playgroud)
代码块不仅限制了变量的范围(这总是好的,尤其是在处理可变状态和非最终变量时),但它们也像XML/HTML一样说明了组件层次结构的方式.代码更易于阅读,编写和维护.
我将每个组件实例化分解为方法的问题是
在这个Swing示例中,我发现当复杂性确实超出可管理性时,它表明是时候将树的一个分支分解为一个新类而不是一堆小方法.
Kev*_*n K 23
通常最好使局部变量的范围尽可能小.匿名代码块可以帮助解决这个问题.
我发现这对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;
}
}
Run Code Online (Sandbox Code Playgroud)
并使用匿名代码块:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为第二个版本更清晰,更容易阅读.并且,它减少了在切换到声明它们的情况下声明的变量的范围,根据我的经验,这是你想要99%的时间.
但要注意,它并没有改变案件掉落的行为 - 你仍然需要记住包括break
或return
防止它!
Ste*_*n C 17
我认为你和/或其他答案混淆了两种不同的句法结构; 即实例初始化器和块.(顺便说一句,"命名块"实际上是一个标记语句,其中语句恰好是一个块.)
Instance Initializer用于类成员的语法级别; 例如
public class Test {
final int foo;
{
// Some complicated initialization sequence; e.g.
int tmp;
if (...) {
...
tmp = ...
} else {
...
tmp = ...
}
foo = tmp;
}
}
Run Code Online (Sandbox Code Playgroud)
根据@dfa的例子,Initializer构造最常用于匿名类.另一个用例是对'final'属性进行复杂的初始化; 例如,参见上面的例子.(但是,使用常规构造函数更常见.上面的模式更常用于静态初始化器.)
另一个构造是一个普通的块,并出现在代码块中,例如方法; 例如
public void test() {
int i = 1;
{
int j = 2;
...
}
{
int j = 3;
...
}
}
Run Code Online (Sandbox Code Playgroud)
块最常用作控制语句的一部分,用于对一系列语句进行分组.但是当你在上面使用它们时,它们(只是)允许你限制声明的可见性; 例如j
在上面.
这通常表明您需要重构代码,但并不总是很明确.例如,您有时会在使用Java编码的解释器中看到这种情况.交换机臂中的语句可以分解为单独的方法,但这可能会导致解释器的"内环"出现重大性能损失; 例如
switch (op) {
case OP1: {
int tmp = ...;
// do something
break;
}
case OP2: {
int tmp = ...;
// do something else
break;
}
...
};
Run Code Online (Sandbox Code Playgroud)
Osc*_*Ryz 12
您可以将它用作匿名内部类的构造函数.
像这样:
替代文字http://img113.imageshack.us/img113/888/capturadepantalla200910.png
这样就可以初始化对象,因为在对象构造期间执行了空闲块.
它不仅限于匿名内部类,它也适用于常规类.
public class SomeClass {
public List data;{
data = new ArrayList();
data.add(1);
data.add(1);
data.add(1);
}
}
Run Code Online (Sandbox Code Playgroud)
匿名块对于限制变量的范围以及双括号初始化非常有用.
相比
Set<String> validCodes = new HashSet<String>();
validCodes.add("XZ13s");
validCodes.add("AB21/X");
validCodes.add("YYLEX");
validCodes.add("AR2D");
Run Code Online (Sandbox Code Playgroud)
同
Set<String> validCodes = new HashSet<String>() {{
add("XZ13s");
add("AB21/X");
add("YYLEX");
add("AR5E");
}};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
38604 次 |
最近记录: |