14

今日、このコード ブロックに出くわしましたが、それがどのように機能するのかわかりません。匿名クラスの作成方法は知っていますが、中かっこのペアだけでなく、メソッド シグネチャも見慣れています。これらの中かっこの間のコードは静的ブロックに入れられていますか? それはコンストラクタに入りますか?それともまったく別のものですか?

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

7 に答える 7

18

作成されたオブジェクトのコンテキスト内でコードを呼び出すインスタンス初期化子です。

これは、

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

それを書いた人は誰でも、変数を宣言しないことでより効率的になっている (そうではありません) か、それがよりクリーンなコードである (私は同意しません) と考えたかもしれません。

これらの初期化子がこのように役立つ主な場所は、マップをインスタンス化するときです。

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

実際にはもう少し読みやすいと思います。

于 2010-10-05T18:57:48.960 に答える
4

これは初期化ブロックですが、必ずしも静的初期化ブロックではありません。これは事実上、匿名内部クラスのコンストラクターです。通常、コレクションを便利に作成および設定するために、この「二重中括弧の初期化」パターンが表示されます。

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
});
于 2010-10-05T19:00:08.057 に答える
3

これはインスタンス初期化子です (静的初期化子ではありません)。

クラスの定義を考える

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

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

getDefaultValue()その initalisesへの呼び出しiは、基本的に Foo のインスタンスが構築されるたびに実行されるコード ブロックです。表記法はその機能を拡張して、より複雑な初期化を可能にします。例えば

public class Foo {
    private int i;

    {
        int z = 4 + 5;
        i = z + getDefaultValue();
    }

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

JMock で使用される方法は、期待にクロージャ構造の外観を与えるためのトリックです。

于 2010-10-05T19:02:44.203 に答える
1

何が起こっていますか ?外側の中かっこは、Exception から派生した新しい匿名クラスを作成します。内側のブレースは初期化子を定義し、その他を設定しますoneOf()

なぜこれを行うのですか?これは、クラスのインスタンスを構築して初期化するためのワンライナー トリックです。e. あなたは時々このようなものを見る:

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

コレクションの内容を初期化します。

欠点?包含クラス内に匿名クラスを作成しているため、その匿名クラスには外側のクラスへの this 参照が暗黙的に含まれています。通常は問題ありませんが、(たとえば) このように構築したクラスをシリアライズしたい場合は、問題が発生する可能性があります。

于 2010-10-05T18:59:18.847 に答える
0

任意の内部クラスにはコンストラクターがないため、このようにインスタンス初期化子を定義できます。つまり、中括弧の内部セットがインスタンス初期化子です。

new Expectations() { 
    { 
        oneOf(alarm).getAttackAlarm(null); 
    }
}
于 2010-10-05T19:04:44.360 に答える
0

この背後にある主な動機は、で定義された名前を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);
    ...
}
于 2010-10-05T20:25:50.477 に答える
0

これは初期化ブロックです。残りのコードを見ないと、それが何をするのかわかりません。

秘訣は、「new Expectation()」が「クラスの何かが Expectation を拡張する」に置き換えられることを想像することです。

于 2010-10-05T18:53:41.573 に答える