2

クラス スコープでフィールドをインスタンス化できるのに、それらのフィールドでメソッドを呼び出すことができないのはなぜですか?

public class MethodInFieldTest {
List<Object> list = new ArrayList<>();

// compilation error
// list.add(new Object());

// Compiles just fine, how I usually do it
{
    list.add(new Object());
}

// compilation error
// addObject();

public void addObject() {
    list.add(new Object());
}


//usual way of handling this
//constructor one
public MethodInFieldTest(... stuff) {
    list.add(new Object());
}

//constructor two
public MethodInFieldTest(..) {
    list.add(new Object());
}

//etc

//...

//ugly way of doing it
//  List<Object> list = new ArrayList<>(Arrays.asList(new Object[]{new Object(), new Object()}));

public static void main(String[] args) {
    System.out.println(new MethodInFieldTest().list);
}
}

たとえば、いくつかのデフォルト値でリストを開始するのが理にかなっていることがよくあります。クラスに複数のコンストラクターがある場合は、コンストラクターにデフォルト値を追加するか、コードで以下に示す醜い方法を使用する必要があります。「醜い」方法はリストに対しては機能しますが、クラスのデフォルト状態 (オブジェクトコンストラクターによって提供されない状態) を必要とする他のオブジェクトに対しては、プライベートヘルパーメソッドを使用する必要があります。必ずしも大きな不便ではなく、なぜクラスフィールドでそれを行うことができないのだろうかと思いますが、その理由について興味があります。

4

3 に答える 3

6

なぜ私はそれを行うことができないのですか?

率直な答えは、Java 言語仕様で次のように指定されているためです。

{
    list.add(new Object());
}

インスタンス初期化子です。これは、クラスのインスタンスが作成されるときに実行される単純なコード ブロックであり、実際の Java コードを含めることができます。

一方で、

List<Object> list = new ArrayList<>();

インスタンス変数の初期化子です。

「言語仕様では、Javaコードを初期化ブロックに入れずにクラススコープで実行できないのはなぜですか」と尋ねる場合、技術的には可能ですが、そのようなコードは読みにくく、維持するのが非常に難しいと言えます。 - インスタンス変数の宣言を他の Java コードと混在させる可能性があります。インスタンス初期化子を使用すると、オブジェクトの作成時に、通常のメソッドと同様に実行されるコード ブロックが1 つだけ存在します。

クラスのロード時に実行される静的イニシャライザもあることに注意してください- それらの構文は次のとおりです。

static {
    // Java code
    // ...
}

Java コードとインスタンス変数宣言を混在させることができる場合、コードをクラスまたはインスタンスの初期化中に実行するかどうかを決定するために、さらに別の構文が必要になります。

于 2013-05-23T18:25:43.367 に答える