配列のnewの有無について
解決済
回答 4
投稿
- 評価
- クリップ 0
- VIEW 180
int[] a = new int[] {1, 2, 3};
と
int[] a = {1, 2, 3};
この2つの表記方法は同じ役割を果たしていると言えるのでしょうか?
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+5
同じ役割を果たしていると言えるのでしょうか?
後者は
・ローカル変数やフィールドの宣言と同時に与える「初期値」としてのみ許される
前者は
・ローカル変数やフィールドへの再代入の右辺やメソッドへの実引数などにも使える「一般的な式」
というところが役割として違う点です。つまり使える場面の違いです。後者がメソッドの実引数にも使えると便利な気もしますが・・・
void foo(int[] a)
(M1)
void foo(Object[] a)
(M2)
のどちらに適合するかfoo({1, 2, 3})
のような型なしの表現だと曖昧さが残ります。一方new int[] {...}
というように「要素の型が明確な式」ならM1のメソッドの引数であることがはっきりしますね。変数の宣言と同時にしか使わない初期値ならば「変数の型は自明」なので前述のような曖昧さが起きません。そういうわけで「初期値」だけはnew int[]
が省略できる簡便な構文を許しているのではないでしょうか?
実際の動作の結果についていえば、下のコードの(A)(B)は全く同じbyte codeにコンパイルされるようです。さらにいえば若干の意味的な違いを除けば(C)とほぼ同じ意味になります。
A.java
class A {
void foo() {
// (A)
int[] a = { 10, 20 };
// (B)
a = new int[] { 10, 20 };
// (C)
a = new int[2];
a[0] = 10;
a[1] = 20;
}
}
コンパイルしてbyte codeを見てみますと・・・
$ javac A.java
$ javap -v A.class
...
Code:
stack=4, locals=2, args_size=1
# ----- (A) ----- int[] a = { 10, 20 };
0: iconst_2
1: newarray int # 要素数2の配列を生成
3: dup # 配列をスタック上にコピー
4: iconst_0 # 0をスタックに積む
5: bipush 10 # 10をスタックに積む
7: iastore # stack[2](=配列)のstack[1](=0)番目にstack[0](=10)を格納
8: dup # 以下同様
9: iconst_1
10: bipush 20
12: iastore
13: astore_1 # 配列をローカル変数aに代入
# ----- (B) ----- a = new int[] { 10, 20 };
14: iconst_2 # (A)と全く同じ
15: newarray int
17: dup
18: iconst_0
19: bipush 10
21: iastore
22: dup
23: iconst_1
24: bipush 20
26: iastore
27: astore_1
# ----- (C) -----
28: iconst_2
29: newarray int # 要素数2の配列を生成
31: astore_1 # 配列をローカル変数aに代入(これが(A),(B)と意味的に違う)
32: aload_1 # あとは若干byte codeが違うが意味的に(A),(B)と同じ
33: iconst_0
34: bipush 10
36: iastore
37: aload_1
38: iconst_1
39: bipush 20
41: iastore
...
(A)(B)は全く同じbyte codeになっており「配列の全体の要素値が確定してから変数へ代入される」のに対して、(C)は「まず全要素が要素型によって決まる値(intなら0)の配列が変数へ代入されてから各要素が初期化される」のがわかります((C)はそう書いているので当たり前ですが...)。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
同じです。ただし、newがない方は変数宣言と同時にしか使えません。
int[] a = {1, 2, 3};
// a = {4, 5, 6}; // コンパイルエラー
a = new int[]{4, 5, 6};
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
同じバイトコードが生成されていましたので, 同じ役割を果たしていると言えると思います.
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
Javaでnew int[] {1, 2, 3};
とすると、配列の実体はヒープ領域に作成されます。
C言語の場合、ヒープ領域に配列の実体を作ろうとすると、int *a = (int *) malloc(sizeof(int) * 3);
とします。
ヒープ領域でメモリを確保する手段として、Javaの場合はnew
を、Cの場合はmalloc
を使う感じです。
話は変わって、C言語の場合、int a[] = {1, 2, 3};
すると、配列はスタック領域に確保されます。
それに対して、Javaの場合、int a[] = {1, 2, 3};
の場合でも配列の実体はヒープ領域に作成されます。
結果として、Javaの場合、どちらも変わらないということだと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 90.36%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/02/12 17:31