質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

4回答

351閲覧

配列のnewの有無について

nainai

総合スコア18

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2019/02/11 17:22

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

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

この2つの表記方法は同じ役割を果たしていると言えるのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

同じ役割を果たしていると言えるのでしょうか?

後者は
・ローカル変数やフィールドの宣言と同時に与える「初期値」としてのみ許される

前者は
・ローカル変数やフィールドへの再代入の右辺やメソッドへの実引数などにも使える「一般的な式」

というところが役割として違う点です。つまり使える場面の違いです。後者がメソッドの実引数にも使えると便利な気もしますが・・・

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

java

1class A { 2 void foo() { 3 // (A) 4 int[] a = { 10, 20 }; 5 6 // (B) 7 a = new int[] { 10, 20 }; 8 9 // (C) 10 a = new int[2]; 11 a[0] = 10; 12 a[1] = 20; 13 } 14}

コンパイルしてbyte codeを見てみますと・・・

bash

1$ javac A.java 2$ javap -v A.class 3... 4 Code: 5 stack=4, locals=2, args_size=1 6 # ----- (A) ----- int[] a = { 10, 20 }; 7 0: iconst_2 8 1: newarray int # 要素数2の配列を生成 9 3: dup # 配列をスタック上にコピー 10 4: iconst_0 # 0をスタックに積む 11 5: bipush 10 # 10をスタックに積む 12 7: iastore # stack[2](=配列)のstack[1](=0)番目にstack[0](=10)を格納 13 8: dup # 以下同様 14 9: iconst_1 15 10: bipush 20 16 12: iastore 17 13: astore_1 # 配列をローカル変数aに代入 18 # ----- (B) ----- a = new int[] { 10, 20 }; 19 14: iconst_2 # (A)と全く同じ 20 15: newarray int 21 17: dup 22 18: iconst_0 23 19: bipush 10 24 21: iastore 25 22: dup 26 23: iconst_1 27 24: bipush 20 28 26: iastore 29 27: astore_1 30 # ----- (C) ----- 31 28: iconst_2 32 29: newarray int # 要素数2の配列を生成 33 31: astore_1 # 配列をローカル変数aに代入(これが(A),(B)と意味的に違う) 34 32: aload_1 # あとは若干byte codeが違うが意味的に(A),(B)と同じ 35 33: iconst_0 36 34: bipush 10 37 36: iastore 38 37: aload_1 39 38: iconst_1 40 39: bipush 20 41 41: iastore 42...

(A)(B)は全く同じbyte codeになっており「配列の全体の要素値が確定してから変数へ代入される」のに対して、(C)は「まず全要素が要素型によって決まる値(intなら0)の配列が変数へ代入されてから各要素が初期化される」のがわかります((C)はそう書いているので当たり前ですが...)。

投稿2019/02/11 18:49

編集2019/02/12 02:33
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nainai

2019/02/12 08:31

理解できました、回答ありがとうございます。
guest

0

同じです。ただし、newがない方は変数宣言と同時にしか使えません。

java

1int[] a = {1, 2, 3}; 2// a = {4, 5, 6}; // コンパイルエラー 3a = new int[]{4, 5, 6};

投稿2019/02/11 18:33

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nainai

2019/02/12 08:32

わかりやすかったです、ありがとうございます。
guest

0

同じバイトコードが生成されていましたので, 同じ役割を果たしていると言えると思います.

投稿2019/02/11 17:58

jimbe

総合スコア12612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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の場合、どちらも変わらないということだと思います。

投稿2019/02/11 18:18

kts_h

総合スコア207

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nainai

2019/02/12 08:32

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問