[英]Java Syntactic Sugar
今天碰到這塊代碼,不知道是怎么操作的。 我知道如何創建匿名類,但我習慣於看到方法簽名而不僅僅是一對大括號。 這些大括號之間的代碼是否放入靜態塊中? 它會進入構造函數嗎? 或者它完全是別的東西?
conext.checking(new Expectations() {
{ // <- what does this pair of braces do?
oneOf(alarm).getAttackAlarm(null);
}
});
它是一個實例初始值設定項,它在創建的對象的上下文中調用代碼。
這相當於
Expectations exp = new Expectations();
exp.oneOf(alarm).getAttackAlarm(null);
conext.checking(exp)
編寫它的人可能認為他通過不聲明變量(不是真的)或者它是更干凈的代碼(我不同意)來提高效率。
這些初始值設定項的主要用途是在實例化映射時,即:
Map map = new HashMap() {{
put("key1", "value1");
put("key2", "value2");
}};
我認為這實際上更具可讀性。
它是一個初始化塊,但不一定是靜態初始化塊。 它實際上是匿名內部類的構造函數。 您通常會看到這種“雙括號初始化”模式來方便地創建和填充集合:
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
});
它是一個實例初始化器(不是靜態初始化器)。
考慮一個類的定義
public class Foo {
private int i = getDefaultValue();
private static int getDefaultValue() {
return 5;
}
}
初始化i
getDefaultValue()
調用本質上是一個代碼塊,每次構造 Foo 實例時都會運行該代碼塊。 該符號擴展了該函數以允許更復雜的初始化。 例如
public class Foo {
private int i;
{
int z = 4 + 5;
i = z + getDefaultValue();
}
private static int getDefaultValue() {
return 5;
}
}
在 JMock 中使用它的方式是一種技巧,可以使期望具有閉包構造的外觀。
發生什么事了? 外大括號創建一個從 Exception 派生的新匿名類。 內部大括號定義了一個初始化器並設置了oneOf()
等。
為什么要這樣做? 這是用於構造和初始化類實例的單行技巧。 e. 你有時會看到這樣的事情:
new HashSet<String>(){{ add("one"); add("two"); }}
初始化集合的內容。
缺點? 因為您在包含類中創建匿名類,所以該匿名類隱式包含對外部類的 this 引用。 通常不是問題,但如果(例如)您想序列化這樣構造的類,則可能會導致問題。
這是一個初始化塊。 如果不查看其余代碼,我無法判斷它的作用。
訣竅是想象“new Expectation()”替換為“class Something extends Expectation”。
任何內部類都沒有構造函數,因此您可以像這樣定義一個實例初始化器,即內部大括號集是實例初始化器。
new Expectations() {
{
oneOf(alarm).getAttackAlarm(null);
}
}
我相信,這背后的主要動機是創建一個新的名稱空間,在其中可以更輕松地引用Expection
定義的名稱。
例如,假設java.lang.Math
不是 final,
new Math()
{{
double x = sin(23.65);
double y = log(x);
...
}};
就好像我們有類似的東西
with names from Math
{
double x = sin(23.65);
double y = log(x);
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.