見出し画像

【JavaSilver】配列の要素数を0でインスタンス化した場合の挙動について

JavaSilverの黒本の勉強をしていて詰まった、「配列の要素数を0でインスタンス化した場合」について理解を深めるために記載する。


プログラム

以下が解らなかったプログラム
このプログラムを実行すると、コンパイルエラーになるのではなく、ハッシュコードが出力されるらしい。
なんで、、、。

public class Main{
	public static void main(String[] args) {
		int[] array = new int[0];
		// 要素数0の配列を出力しようとするとハッシュコードが出力される。
		System.out.println(array);
	}
}

実行結果:[I@279f2327

ハッシュコードとは

まず、ハッシュコードが出力されるらしいけど、「ハッシュコードってなに?」というところから調べてみました。
Javaでいうハッシュコードとは「オブジェクトを一意に識別するためなどに使われる整数値」のことで、ハッシュ値とハッシュコードは同じ意味で使われることが多い。
例)
・appleをハッシュ化すると「8329」が返ってくる。
・orangeをハッシュ化すると「3481」が返ってくる。
・apple1をハッシュ化すると「2819」が返ってくる。
・もう一回appleをハッシュ化すると1回目同様に「8329」が返ってくる。
 →何度同じ文字列をハッシュ化しても同じ値が返ってくる。
 →文字列の一部が異なれば、ハッシュ値は違うものが返ってくる。
※ハッシュ値は例です。

JavaではHashMapやHashSet、equalsなどで使われているようです。
こちらは後日調べます。

~余談~
応用情報の勉強をしてた時に「暗号化」や「ハッシュ化」が出てきましたが、どちらもデータの中身がわからないようにするということらしいです。
異なるところは、簡単に言うと暗号化は復号化ができるがハッシュ化は復号化ができないこと。

配列の基礎知識

次に配列の基礎知識のおさらい。

配列とは

配列はプリミティブ型の配列と参照型の配列があります。
プリミティブ型の配列とは配列の中にデータをそのまま格納する。
参照型の配列はデータを格納するのではなく、データが格納されている参照先を配列に格納する。

配列のインスタンス化、初期化方法

int[] array = new int[2];
array[0] = 1;
array[1] = 5;
int[] array = {1, 5};

配列を初期化しないとどうなるのか

もし以下のプログラムを実行したらどうなるのか

int[] array = new int[2];
System.out.println(array[0]);

実行結果:0
なぜ初期化していないのに0が格納されるのか
 →配列を生成するとデータ型に合わせて初期化が行われるから

配列の初期化値
byte、short、int、long
 →初期化値「0」
float、double
 →初期化値「0.0」
char
 →初期化値「¥u0000」
boolean
 →初期化値「false」
参照型
 →初期化値「null」
 

なぜハッシュコードが出力されるのか

話を戻して、なぜハッシュコードが出力されるのかを考える。

なぜコンパイルエラーではないのか

要素が0の配列インスタンスを作っているだけで、(意味をなさない配列だけど)文法的には問題がないから。

なぜハッシュコードが出力されるのか

1.画面出力を行うprintlnメソッドでは、引数に参照を渡すとPrintStreamクラスの以下メソッドを呼び出す

    public void println(Object x) {
        String s = String.valueOf(x);
        if (getClass() == PrintStream.class) {
            // need to apply String.valueOf again since first invocation
            // might return null
            writeln(String.valueOf(s));
        } else {
            synchronized (this) {
                print(s);
                newLine();
            }
        }
    }

2.2行目でStringクラスのvalueofメソッドを呼び出す
呼び出し先では引数(obj)がnullでなければObjectクラスのtoStringメソッドを呼び出す処理が書かれている。

    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }

3.ObjectクラスのtoStringメソッド
戻り値としてクラス名@ハッシュコードを返す

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

今回printlnで出力するのは配列型変数arrayのため、arrayのクラス名@ハッシュコードが出力される。
要素数が0だからハッシュコードが出力される訳ではなく、配列型変数の値を出力しようとしているからハッシュコードが出力される。

例えば、以下のプログラムを実行した場合もハッシュコードが出力される。

		int[] array1 = new int[2];
		System.out.println(array1);


おわりに

理解ができなくて苦しんだハッシュコードが出力される件、めちゃくちゃ理解するのに時間がかかりました。
Javaって難しいですねえ。
でも難しいからこそ面白いですね。

今やっている内容は基礎の基礎だと思うので、これからも勉強続けていきます。

END

この記事が気に入ったらサポートをしてみませんか?