配列2

<概要>配列を更に深く学びます。ちょっとややこしい……。

例題9-2-1 多次元配列。

○プログラム

public class Heikin6{
  public static void main(String[] args){
    int[][] tens={
      {63,90,75,45,81},
      {85,100,95,80,90},
      {100,100,100,100,100},
    };
    for(int i=0;i<tens.length;i++){
      int sum=0;
      for(int j=0;j<tens[i].length;j++){
        System.out.print("\t"+tens[i][j]);
          sum+=tens[i][j];
      }
      System.out.println("\t| "+(double)sum/tens[i].length);
    }
  }
}


○実行結果

D:\atsushi\Java\List9-6>java Heikin6
 63 90 75 45 81 | 70.8
 85 100 95 80 90 | 90.0
 100 100 100 100 100 | 100.0
-- Press any key to exit (Input "c" to continue) --

○解説

二次元配列はの宣言は int[][] tens=new int[3][5]; と書きます。
宣言と同時に初期化も行う場合は
int[][] tens={
  {63,90,75,45,81},
  {85,100,95,80,90},
  {100,100,100,100,100},
};

と書きます。
一次元配列と同じで、
new 演算子を使って明示的にメモリ領域を確保する必要はありません。

二次元配列は、配列の配列です。
したがって、tens.length フィールドの値は 3、
tens[0].length フィールドの値は 5 です。

例題9-2-2 要素数が一定ではない多次元配列。

○プログラム

public class Heikin6a{
  public static void main(String[] args){
    int[][] tens={
      {3,14,159,26,},
      {53,5,},
      {897,93,238,},
    };
    for(int i=0;i<tens.length;i++){
      int sum=0;
      for(int j=0;j<tens[i].length;j++){
        System.out.print("\t"+tens[i][j]);
        sum+=tens[i][j];
      }
      System.out.println("\t| "+(double)sum/tens[i].length);
    }
  }
}


○実行結果

D:\atsushi\Java\p221>java Heikin6a
 3 14 159 26 | 50.5
 53 5 | 29.0
 897 93 238 | 409.3333333333333
-- Press any key to exit (Input "c" to continue) --

○解説

多次元配列の要素数は一定でなくても問題ありません。
C言語、C++言語は一定でなければいけませんでしたね。

配列要素を区切るコンマ , は最後の要素の後には
付けても付けなくてもどちらでも構いません。

多次元配列の場合、体裁を整える為にコンマ , を付けるのが一般的です。

例題9-2-3 次のうち、配列の宣言として正しいものはどれですか?

(1) int a[3];
(2) int[] a=int[3];
(3) int[] a=new int[3];
(4) int[3] a={10,20,30};
(5) int[] a={10,20,30,};
(6) int a[]=new int[3];
(7) int a[]={10,20,30,};


○答え&解説

誤 (1) int a[3];

配列の長さは、ここには書けません。

誤 (2) int[] a=int[3];

new が抜けています。

正 (3) int[] a=new int[3];

問題ありません。

誤 (4) int[3] a={10,20,30};

配列の長さは、ここには書けません。

正 (5) int[] a={10,20,30,};

最後の配列要素 30 の後のコンマ , はあってもなくても構いません。

正 (6) int a[]=new int[3];

変数名の後に [] を書く、C言語、C++言語で見慣れた書き方も出来ます。
なんてC++言語プログラマに優しいんでしょうね(笑)。
これは (3) int[] a=new int[3]; と全く同じです。

正 (7) int a[]={10,20,30,};

(5) int[] a={10,20,30,}; と全く同じです。

○補足

多次元配列の宣言も int array[][]; のように書くことが出来ます。
これは int[][] array; と全く同じです。

○補足2

配列と普通の変数の宣言を一行に並べて書きたい場合は注意が必要です。
正 int array[],num;
誤 int[] array,num;
この場合、Java言語特有の書き方は出来ず、C++言語の書き方に倣うしかありません。
int[] array,num; では、num まで配列だと見なされてしまいます。

例題9-2-4 配列を戻り値とするメソッド。

○プログラム

public class MethodTest1{
  public static String[] getYourName(){
    String[] myoji_namae={"福沢","諭吉"};
    return myoji_namae;
  }
  public static void main(String[] args){
    String[] s=getYourName();
    System.out.println("名字は"+s[0]);
    System.out.println("名前は"+s[1]);
  }
}


○実行結果

D:\atsushi\Java\ListA8-2>java MethodTest1
名字は福沢
名前は諭吉
-- Press any key to exit (Input "c" to continue) --

○解説

getYourName メソッドの戻り値は String 型配列です。
正確には配列へのポインタです。
したがって、String[] s=getYourName(); は、配列に配列を代入しているのではなく、
配列のポインタをコピーしているのです。
もっとこのことを分かり易いプログラムで示せば、次のようになります。

int[][] tens={
  {63,90,75,45,81},
  {85,100,95,80,90},
  {100,100,100,100,100},
};
int[][] array=tens;


このプログラムも何ら問題ありません。

例題9-2-5 メソッドにポインタを渡す。

○プログラム

public class MethodTest3{
  public static void getYourName(String[] args){
    args[0]="福沢";
    args[1]="諭吉";
  }
  public static void main(String[] args){
    String[] s=new String[2];
    getYourName(s);
    System.out.println("名字は"+s[0]);
    System.out.println("名前は"+s[1]);
  }
}


○誤プログラム

public class MethodTest{
  public static void getYourName(String myoji,String namae){
    myoji="福沢";
    namae="諭吉";
  }
  public static void main(String[] args){
    String x,y;
    getYourName(x,y);
    System.out.println("名字は"+x);
    System.out.println("名前は"+y);
  }
}


○実行結果

D:\atsushi\Java\ListA8-4>java MethodTest3
名字は福沢
名前は諭吉
-- Press any key to exit (Input "c" to continue) --

○解説

C言語、C++言語プログラマーには見慣れたポインタ処理ですね。
ここで注意しなければならないのはメモリ領域を確保する箇所です。
配列はそれを参照する前に必ず初期化、つまりメモリ領域の確保を行わなければなりません。
このプログラムで最初に参照するのはメソッドに渡すときです。
したがって、その前にメモリ領域を確保しなければなりません。
ポインタだけ渡してメソッドの中でメモリ領域を確保することは出来ません。
それをやろうとして失敗したのが誤りとしたプログラムです。
String x,y; は、配列ではありませんがクラスは参照型なのでポインタです。
String クラスがメモリ領域を確保するのは、初期値である文字列を指定したときです。
配列で明示的にサイズを指定せずに、初期値を指定した場合と同じですね。
つまり、誤りとしたプログラムはメモリ領域を確保する前に参照してしまったのです。
だから、初期化されていない可能性をコンパイラに指摘されることになります。

//コンパイル

■D:\atsushi\Java\List8-6> javac MethodTest.java
MethodTest.java:8: 変数 x は初期化されていない可能性があります。
getYourName(x,y);
         ^
MethodTest.java:8: 変数 y は初期化されていない可能性があります。
getYourName(x,y);
          ^
エラー 2 個

○補足

main メソッドにも言えることですが、
仮引数 args という名前は自由に変更することが出来ます。

○補足2

メソッド内部で渡されたポインタから、その配列の長さを得ることが出来ます。

System.out.println(args.length);

これはC言語、C++言語では出来なかった芸当です。
Java言語の配列を指すポインタはただ者ではありませんね(笑)。


戻る / ホーム