2012-05-09 130 views
40

可能性の重複:
なぜ配列定数はイニシャライザでのみ使用できますか?

Arrays constants can only be used in initializers error

Iは、配列を研究し、そして私は1つの行に配列を宣言し、初期化のこの短いカット法により来ました。私はコードの次の操作を行うことを試みたとき例えば、

int[] a = {1, 2, 3, 4, 5}; 

しかし、私は「配列定数のみを初期化子で使用することができます」と言って、このコンパイラエラーを得ました。

int[] a; 
a = {1, 2, 3, 4}; 

なぜですか?

+13

これは重複していません。 OPは、なぜ*どうやって*どうやっていないのかを尋ねている。 – Jeremy

+6

Meh;それは偽りのリンクの質問は、 "それは動作するように私はそれを行う"と言うことを確信していない、この質問は "どうして他の方法は実際に動作しない"と尋ねる。違いは完全に異なった答えにつながります。この質問には既に*どのように*働かせるかがあります。 –

+0

これらの種類の質問は面白いですが、答えるのは非常に不可能です。私たちができるのは推測です。しかし、この仕様書の一部を書いた人には教訓の瞬間として(なぜこのデザインをしていないのですか?)、これを尋ねるのは本当に面白いでしょう。 – yshavit

答えて

0

私は最初の方法で配列を初期化することができます。配列を割り当てることはできません。理由の理解には、配列の実装方法に関するいくつかの理論が関係するかもしれません。コンパイラは、配列が最初の行の宣言と初期化で宣言されたときの配列の大きさを知る必要があります。コンパイラはサイズを推測できますが、2番目の行では推測できません。

+1

OPはすでにもう1つが動作していないことを知っていて、*理由*を尋ねています。答えはそれをまったく解決しません。 –

+0

なぜコンパイラはcurly brasceの要素を読み取ることができず、1番目の場合のようにサイズを知ることができます - int [] a = {1,2,3}; –

+0

javaは静的に型指定されているため、コンパイラは配列のメモリを割り当てることができるように、初期化の時点で配列のサイズを知る必要があります。 – cobie

84

JLS says soですので、許可されていません。構文は、宣言および配列作成式でのみ許可されます。次のように私の推測であり、new T[]を必要とするため、実際の根本的な理由としては

int[] a; 
a = new int[]{1, 2, 3, 4}; 

後者は、同じ結果を達成するための代替方法を提供します。以下の配列初期化子を考えてみましょう:

{1, 2, 3, 4} 

異なるタイプの配列を初期化するために使用することができます。

new int[]{1, 2, 3, 4}; 
new float[]{1, 2, 3, 4}; 
new double[]{1, 2, 3, 4}; 

new T[]ビットが必要とされなかった場合、私は裸{1, 2, 3, 4}の中に問題を引き起こす可能性があると思われます意味分析。この構文が許可された場合、言語仕様を呼び出すために機能の選択の複雑さに対処しなければならない

void f(float[] x) { ... } 
void f(double[] x) { ... } 
void g() { 
    f({1, 2, 3, 4}); 
} 

:ここでは、私のような例を考えています。

同様に、{null}の種類を明確にすることはできません。 Object[],Integer[],Serializable[]などとすることができます。

最後に、空の配列{}が最も難しいでしょう。ここでは、オブジェクトの配列かスカラーの配列かどうかはわかりません。

これらの複雑さをすべて処理する代わりに、言語設計者はnew T[]の構文を要求することによってそれらを回避することを選択したようです。

+0

私は知っていたが、私の質問はなぜそれが許されないのか? –

+0

Meh - コンパイラは 'arrn'の型を知っています。私はコンパイラの簡素化を買うことができましたが、それについては難しいことは何もありません。 –

+2

@DaveNewton:必ずしもそうではありません。 '{1、2、3、4}'が 'float []'と 'double []'のためにオーバーロードされる関数に渡される可能性を考慮してください。何が起こるはずですか? – NPE

5

短い答えはbecause the language spec says soです。

なぜですか?私はそれがをタイプすると思う。最初のケースでは、パーサ/コンパイラは配列変数を初期化するコンテキスト内にあることを知っているので、中括弧は配列の初期化子であると推測できます。

後者の場合、中括弧が何を意味するのかがすぐにわかりません。おそらく、タイピングは、構文解析の後の段階で実行されるため、単に意味を推測することは実行可能ではありません。あなたが得ることができる

int[] a; 
// then later 
a = new int[] { 1, 2, 3, 4 }; 
+1

Javaは「技術的に冗長な」構文で有名です。それについては「技術的に」ありません。 –

0

唯一の答えは、哲学的な性質のものである:あなたが(具体的かつ技術的に重複して)再び型を宣言する場合

この引数を使用すると、非常によく似た構文を使用することができるという点で、重さを持っているようです。暗黙の配列型を許可しないという決定は、Javaの一般的な設計原則に従っており、事柄を簡単かつ明白に保ちます。同じように、すべてのダウンキャストを明示的に指定する必要があるのか​​、狭いタイプ変換を行うべきなのかを尋ねることができます。 Javaはブルーカラー言語であり、明白+明示はそのコア値です。

関連する問題