宣言にない場合の配列初期化構文


141

私は書くことができます:

AClass[] array = {object1, object2}

私も書くことができます:

AClass[] array = new AClass[2];
...
array[0] = object1;
array[1] = object2;

しかし、私は書くことができません:

AClass[] array;
...
array = {object1, object2};

これがJavaによってブロックされるのはなぜですか?

私はそれを回避する方法を知っていますが、時々それはより簡単になるでしょう。

例えば:

public void selectedPointsToMove(cpVect coord) {

    if (tab == null) {
        if (arePointsClose(coord, point1, 10)) {
            cpVect[] tempTab = {point1};
            tab = tempTab;
        } else if (arePointsClose(point2, coord, 10)) {
            cpVect[] tempTab = {point2};
            tab = tempTab;
        } else {
            cpVect[] tempTab = {point1,point2};
            tab = tempTab;
        }
    }
}

この単純な質問は、Javaで配列を操作する方法を学んで以来、私を悩ませてきました。


申し訳ありませんが、テキスト形式に関するいくつかの理由で、中国でのテキストレイアウトボタンが表示されない:S
ジェイソン・ロジャース

コードの場合は、4つのスペース以上でインデントされていることを確認してください。
マット

もう1つの問題は、貼り付けたコードにタブ文字が含まれていることです。これはフォーマットを壊します。
スティーブンC

沖のおかげで、日食はインデントにタブを使用しているため、コピーして貼り付けると、混乱を招きます。編集に感謝
Jason Rogers

EclipseはインデントにTAB文字を使用しないように再構成できます。言い訳にはしないでください。
スティーブンC

回答:


137

これがJavaによってブロックされるのはなぜですか?

Javaデザイナーに尋ねる必要があります。制限には、微妙な文法上の理由があるかもしれません。配列の作成/初期化構造の一部はJava 1.0にはなく、(IIRC)はJava 1.1に追加されていることに注意してください。

しかし、「なぜ」は重要ではありません...制限があり、それと共存する必要があります。

私はそれを回避する方法を知っていますが、時々それはより簡単になるでしょう。

あなたはこれを書くことができます:

AClass[] array;
...
array = new AClass[]{object1, object2};

9
新しい宣言なしでは、ステートメントブロックと配列初期化子の間に違いはありません(JavaScriptのように、誤解を招く可能性があります)
bestss

10
それ混乱を招くでしょう ...そして解析するのは難しいでしょう{o1()}が有効な式であり{o1();}、有効なステートメントブロックであったかどうかを検討します。パーサーは「}」または「;」に到達する必要があります 2つのケースを区別する前に。文法の問題はまったく微妙ではありません!
Stephen C

19

なぜかという質問に答えてみましょう。Java配列は、より動的なArrayListのようなクラスに比べて非常にシンプルで初歩的です。Javaは、宣言時に配列に割り当てるメモリ量を知りたいと考えています。ArrayListははるかに動的であり、そのサイズは時間とともに変化する可能性があります。

長さ2で配列を初期化し、後で長さ3が必要になった場合は、取得したものを破棄して、まったく新しい配列を作成する必要があります。したがって、「新しい」キーワード。

最初の2つの例では、宣言時に割り当てるメモリ量を指定します。3番目の例では、配列名は何も指すポインターにならないため、初期化時に、新しい配列を明示的に作成して、適切な量のメモリを割り当てる必要があります。

私はそれを言うでしょう(そして誰かがよりよく知っているなら、私を訂正してください)最初の例

AClass[] array = {object1, object2}

実際に意味する

AClass[] array = new AClass[]{object1, object2};

しかし、Javaデザイナが行ったことは、宣言時に配列を作成する場合に、より迅速に記述できるようにすることでした。

推奨される回避策は適切です。実行時に時間またはメモリ使用量が重要な場合は、配列を使用します。重要ではなく、理解しやすく、扱いやすいコードが必要な場合は、ArrayListを使用してください。


2
これは、Oracleの引用:「ショートカット構文を使用して配列を作成および初期化することもできます」で述べたショートカットです。その理由は、配列のどこかで newを使用してメモリ内にある程度のスペースを割り当てる必要があるためです。Newはショートカットで暗黙的ですが、ショートカットは宣言でのみ有効です。それ以外では、ショートカットは許可されておらず、newは必須です。

3
申し訳ありませんが、「なぜ」の質問に答えようとしても、水はありません。コンパイラーは、許可されるイニシャライザ形式の場合と同じように{}... と...の間の式を数えることによって、配列がどれだけ大きい必要があるかを計算できます。
スティーブンC

8

なぜだか分からない。

しかし、何か動的なものが必要な場合は、Collection ArrayListを検討してみませんか。

ArrrayListは、任意のオブジェクトタイプにすることができます。

また、強制的に配列として必要な場合は、toArray()メソッドを使用できます。

例えば:

            ArrayList<String> al = new ArrayList<String>();
            al.add("one");
            al.add("two");
            String[] strArray = (String[]) al.toArray(new String[0]);

これがお役に立てば幸いです。


2
配列の戻り値の型をString []にキャストする必要はありません。規約により、返される配列は指定された配列と同じ型です。docs.oracle.com/javase/6/docs/api/java/util/...
はAnkur Agarwalさん

4

この巨大なnew AClass[] { ... }構文が気に入らない人のために、ここにいくつかの砂糖があります:

public AClass[] c(AClass... arr) { return arr; }

この小さな関数を好きなように使用してください:

AClass[] array;
...
array = c(object1, object2);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.