配列変数の理解に苦しんでます。

解決済

回答 6

投稿

  • 評価
  • クリップ 0
  • VIEW 712

prog1717nm

score 52

public class Swap {
  public static void main(String[] args) {
   int[] a={10, 20};
   int[] b={10, 20};

   swap(a);
   System.out.printf("%3d%3d\n", a[0], a[1]);
   swapVal(b[0], b[1]);
   System.out.printf("%3d%3d\n", b[0], b[1]);
  }

  static void swap(int[] a) {
   int x=a[0]; a[0]=a[1]; a[1]=x;
  }

  static void swapVal(int x, int  y) {
   int w=x; x=y; y=w;
  }
}

上のプログラムの実行結果は
20 10
10 20

なのですが、なぜ配列aだけしか逆にならないんでしょうか?
配列bも『int w=x; x=y; y=w;』の部分で10と20の値が入れかわり、逆になると思うのですが。教えて下さい。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

checkベストアンサー

+1

変数宣言において、newを用いて宣言するものはすべてオブジェクト型変数です。
オブジェクト型→参照渡し(正確には違うけど)
プリミティブ型→値渡し
となっています。

int[] a={10, 20};
これにはnewがないじゃないか!となると思いますが、これはコンパイル時に
int[] a = new int[]{20, 10};
という形に直しています。これにはnewがあります。

値を代入しない配列の宣言も
int[] a = new int[3];
みたいにnewがありますし。

この場合は、aはnewを代入したオブジェクト型変数
a[0]とa[1]はそれぞれ20と10という値を代入したプリミティブ型変数(のようなもの)です。
これはbでも同じです。

参照渡しは、渡した先と値を共有する。
値渡しは、渡した先と値を共有しません。

だから今回のような結果になります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

配列bも『int w=x; x=y; y=w;』の部分で10と20の値が入れかわり、逆になると思うのですが。教えて下さい。 

配列bじゃなくて、swapValメソッドの中のローカル変数が書き換わっているだけです。
仮引数がint x, int yなので、実引数のb[0]b[1]の「値」がメソッドに渡ります。
つまり、下記と同じです。

int x = b[0];
int y = b[1];
int w=x; x=y; y=w;
System.out.printf("%3d%3d\n", b[0], b[1]);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

javaの関数呼び出し時の引数は値をコピーしているだけです。

従って、bについてはコピーされたもの同士を入れ替えているのでオリジナルに影響はありません。一方、aについては配列を渡しています。配列を辿って、この中身を変更しているのでオリジナルの中身にも影響が出ます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

メソッドの引数にはその値のコピーが渡されるだけです。swapValにbの配列要素を渡したところでは、メソッド内の変数が「xが10、yが20」という情報があるだけで、それが「配列bの要素だ」ということは一切なくなります。このxとyの値を入れ替えようが、配列bからは関係のない話なので、配列bの要素に変化はありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

既に素敵な回答が他の方から出てますので蛇足で。

配列変数以外にも、
意識しないといけない点があるので順番に説明します。
先ずそれぞれのメソッドがやっている事を確認しましょう。

  • Swapメソッドについて
static void swap(int[] a) {
   int x=a[0]; a[0]=a[1]; a[1]=x;
  }


上記がやっている事ですが、
引数で受け取った配列の各要素の数値を入れ替えた上で配列に設定し直しています。
これは質問者さんの想定通りですので特に問題ないですね。

  • SwapValメソッドについて
static void swapVal(int x, int  y) {
   int w=x; x=y; y=w;
  }

上記は呼び出し元から値をコピーして受け取った数値を、当該メソッドのローカル変数で入れ替えています。

つまりやってることが全然違っていたりします。

ついでなので上記に出てきた値渡し、ローカル変数についても説明します。

値をコピーして受け取るとは

int型やdouble型などの基本データ型を引数として受け取るとこの挙動となります。
今回のケースだとswapValメソッドには配列bの各要素の数値がコピーされた状態となり、この時点で元々のb配列との関連は一切なくなっています。
これは値渡し(call by value)とも呼ばれます。

また値渡しと関連するもので参照渡し(call by reference)というものも存在します。
厳密には違うものですがswapメソッドの方がちょうどそれに近い振る舞いをします(配列は参照型データ)。
この辺りは最初につまづきやすい所なので以下のリンクなどで目を通してしておくと良いでしょう。
【Java初心者】値渡しと参照渡し

ローカル変数とは

ローカル変数とは宣言されたブロックでのみ有効となる変数の事です。
上記のコードだとswapValメソッド内で宣言されたint型の変数たちは、
このメソッド内でしか有効となりません。
もう一つ例を挙げると、

if (条件) {
    int i = 10;
}
// i = 0; ifブロック内で宣言されているためそもそもコンパイルエラー


上記の変数iはifブロック内でのみしか有効となりません。
こういう有効範囲の事を変数のスコープとか言ったりします。

ローカル変数と対になる用語としてグローバル変数というのもあります。
興味あったら調べてみると良いと思います。

・最後に
色々覚える事も多くて大変かと思いますが、
一つずつ確実に吸収していく事がプログラミング向上の近道です。
頑張ってくださいね^^

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

既に詳しい説明があるので詳細は省きますが、値渡しと参照渡しは理解し辛いですよね。
簡単に覚えるために以下に回答をしておきます。

Javaは型の種類として大きく2つあります。

1.具体的な整数値や実数値を格納するためのプリミティブ型
2.クラスインスタンスや、プリミティブ型を配列にした、参照型

プリミティブ型は以下のとおり

byte
short
int
long
char
float
double
boolean

以下はプリミティブ型のラッパークラス(一部名称が違いますが、頭が大文字です)

Byte
Short
Integer
Long
Character
Float
Double
Boolean

他にも先に説明した、プリミティブ型の配列は全て参照型、
それ以外のクラスも全て参照型となります。

プリミティブ型は値渡しなので、呼び出し先の関数内で値を変更しても、呼び出し元では不変。
参照型は参照渡しなので、呼び出し先の関数内で中身の値を変更したら、呼び出し元でも変更される。

いかがでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる