お世話になっております。JAVAに関しての質問です。

配列を

int num[]; ①

のように宣言したとします。
そして、この後になんらかの処理が続いたとします。
そして、それから、

num[] = new int [5]; ②

と設定することはできます。
ですが、②の代わりに

num[] = {1,2,3,4,5}; ③

などとすることはできません。
③に関しては、①のところで

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

ならOKですが、

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

などという形を取ることもできません。
なぜ④のような初期化の形式だけがOKで
③⑤がNGなのか、疑問に思いました。

ご存知の方おりましたら、ご教授下さいますよう
お願いします。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2006/06/12 22:04:26
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答1件)

id:tomo_k No.1

回答回数426ベストアンサー獲得回数26

ポイント60pt

http://www.geocities.jp/turtle_wide/java/javalect/out02.htm

1の場合は、単にnumへのポインタ領域が確保されるだけで配列のインスタンス化はされない。つまり、プログラムとしてはどれだけのメモリを確保していいかわからないのでメモリの確保が行われない。

2の場合はまずint型5個分の領域が確保され(new)(インスタンス化され)なおかつ、1で確保したポインタ領域に確保したメモリ領域の先頭アドレスが書き込まれる。

3の場合は1で実際のメモリ領域は確保していないのにポインタ領域に配列のようなものを書き込もうとしている。型があわないためにエラーとなる。

4の場合の書き方をしたときは、インスタンス化される決まりになっている。

5は1→3と同じなので省略。

id:mimio17

ありがとうございます。

>3の場合は1で実際のメモリ領域は確保していないのにポインタ領域に配列のようなものを書き込もうとしている。型があわないためにエラーとなる。

冷静に考えたら、そうですよね。。

>4の場合の書き方をしたときは、インスタンス化される決まりになっている。

う~ん、やはりそういった"決まり"なんですね。

丁寧に回答して下さり、ありがとうございました!

2006/06/12 22:03:45
  • id:quintia
    ありゃ、出遅れてしまいましたか。せっかくなのでコメントに入れておきます。


    3, 5 の式では右辺の「配列の型」、あるいは「なんの型の配列か」が不定だからです。
    num = new int[] {1, 2, 3, 4, 5 };
    は可能ですね。


    なぜ変数宣言の時点で初期化するのに、右辺に配列の型の宣言が不要なのかといえば、自動的に左辺の型で配列を作ってしまうからです。
    int arrayOfInt[] = {1,2,3,4,5};
    float arrayOfFloat[] = {1,2,3,4,5};

    System.out.println("arrayOfInt class=? " + arrayOfInt.getClass().getName());
    System.out.println("arrayOfFloat class=? " + arrayOfFloat.getClass().getName());
    の結果は、
    arrayOfFnt class=? [I
    arrayOfFloat class=? [F
    になります。右辺に書いてあるのは、同じ {1, 2, 3, 4, 5} という記述でも実際に生成されるインスタンスは異なっていて、左辺の型が適用されているのが判ります。


    「基本型の配列」がクラスになっていて、かつリテラルでインスタンスの生成をする際に記法が省略できることから起こる「不思議」なわけです。
    {1, 2, 3, 4, 5} というリテラルが「実際にどんなインスタンスを生成しているのか?」、あるいは「コンパイラから見て、どんなインスタンスを生成するべきかが判るか?」を考えればいいかと。


    とはいえ、話が基本型の配列なので納得できないと思いますので、少し続けて、「クラス配列」のことを考えてみましょう。
    List a = new ArrayList();
    List b = new ArrayList();

    List[] arrayOfList = {a, b};
    Object[] arrayOfObject = {a, b};

    System.out.println("arrayOfList class=? " + arrayOfList.getClass().getName());
    System.out.println("arrayOfObject class=? " + arrayOfObject.getClass().getName());
    この結果は、
    arrayOfList class=? [Ljava.util.List;
    arrayOfObject class=? [Ljava.lang.Object;
    になります。これは上の議論と同じです。


    さて、上のソースに続けて、
    arrayOfObject = new Object[]{a, b}:
    arrayOfObject = new List[]{a, b}:
    のどちらが書けるでしょうか?
    どちらも書けます。どちらにするかは、ソースを書く側に委ねられています。
    arrayOfObject = {a, b}:
    を許さないのは、「ソースを書く側に委ねられて」いることを強調したいからだと思います。
  • id:quintia
    質問が終了しているのに気がついて途中で筆を置いたので、変な論旨で終わってますね。

    「変数宣言の時点で右辺に型を省略した配列リテラルを書いているんだから、生成する配列の型は変数宣言の型と同じでいいんだろう」と判断してのことでしょうね。

    と結ぶべきでした。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません