Java语法糖

时间:2010-10-05 18:50:14

标签: java syntactic-sugar

我今天遇到了这段代码,我不知道它是如何工作的。我知道如何制作匿名类,但我习惯于看到一个方法签名,而不仅仅是一对大括号。这些大括号之间的代码是否放入静态块?它会进入构造函数吗?或者它完全是另一回事?

conext.checking(new Expectations() {
    { // <- what does this pair of braces do?
        oneOf(alarm).getAttackAlarm(null);
    }
});

7 个答案:

答案 0 :(得分:16)

它是一个实例初始值设定项,用于在创建的对象的上下文中调用代码。

这相当于

Expectations exp = new Expectations();
exp.oneOf(alarm).getAttackAlarm(null);
conext.checking(exp)

无论是谁编写它都可能认为他通过不声明变量(不是真的)或更清晰的代码(我不同意)来提高效率。

这些初始值设定项的主要用途是实例化地图,即:

Map map = new HashMap() {{
  put("key1", "value1");   
  put("key2", "value2"); 
}};

我认为实际上更具可读性。

答案 1 :(得分:3)

它是一个初始化块,但不一定是静态初始化块。它实际上是匿名内部类的构造函数。您通常会看到这种“双支撑初始化”模式,以方便地创建和填充集合:

private final Collection<Integer> FIXED_COLLECTION = Collections.unmodifiableCollection(new HashSet<Integer>() 
{ // first set of braces declares anonymous inner class
    { add(1); add(2); add(3); } // second set is initializer block
});

答案 2 :(得分:3)

这是一个实例初始化器(不是静态初始化器)。

考虑一个类的定义

public class Foo {
    private int i = getDefaultValue();

    private static int getDefaultValue() {
        return 5;
    }
}

getDefaultValue()的{​​{1}}调用实际上是一个代码块,每次构造一个Foo实例时都会运行。该表示法扩展了该功能以允许更复杂的初始化。 E.g。

i

在JMock中使用它的方式是一种给出期望闭包构造外观的技巧。

答案 3 :(得分:0)

这是一个初始化块。如果不查看剩下的代码,我无法分辨它的作用。

诀窍是想象“新的期望()”被“类别扩展期望”所取代。

答案 4 :(得分:0)

发生了什么事? 外部大括号创建一个从Exception派生的新匿名类。 内部大括号定义初始化并设置oneOf()等。

为什么这样?这是构建和初始化类实例的单线技巧。即你有时会看到这样的东西:

new Set<String>(){{add("one");add("two")}}

初始化集合的内容。

下行?因为您在包含类中创建了一个匿名类,所以该匿名类隐式包含对外部类的this引用。通常不是问题,但是如果(比方说)你想序列化你这样构建的类,它可能会引起问题。

答案 5 :(得分:0)

Anynoymous内部类没有构造函数,因此您可以像这样定义一个实例initilizer,即内部括号集是实例初始值设定项。

new Expectations() { 
    { 
        oneOf(alarm).getAttackAlarm(null); 
    }
}

答案 6 :(得分:0)

我认为,这背后的主要动机是创建一个新的名称空间,可以更容易地引用Expection中定义的名称。

例如,假设java.lang.Math不是最终的,

new Math()
{{
    double x = sin(23.65);
    double y = log(x);
    ...
}};

这几乎就像我们有像

这样的东西
with names from Math
{
    double x = sin(23.65);
    double y = log(x);
    ...
}