JavaSilver対策〜nullを極めよう〜

私自身、紫本・白本・黒本と合計1500ページも色々な問題を解いてきたわけですが、後半は正直かなり傾向がわかってきました。というのも、問題文とか答えの選択肢を見ただけで何を引っ掛けようとしている問題なのか大体わかるようになってきます。「これはオーバーライド問題だな」とか「これは抽象メソッド問題だな」「これはnullの理解を聞いてるな」などです。

そこで当初個人的に苦手だった部分や私と同じようにプログラミング初心者の引っかかりそうなところを抽出して紹介していきます。

今回の内容を理解しておけばもったいないところで点数を落とさなくて済むようになるので点数アップも期待できると思います。

それでは早速本題に入っていきましょう！



<h1>目次</h1>

[1. フィールドの初期値](#フィールドの初期値)
[2. 配列型の出力](#配列型の出力)
　- [要素指定なし-ハッシュ値の出力-](#要素指定なし-ハッシュ値の出力-)
　- [要素指定あり](#要素指定あり)
　- [要素数の確認](#要素数の確認)
　- [明示的なnullの代入](#明示的なnullの代入)
[3. 最後に](#最後に)



<h2>フィールドの初期値</h2>
まずはこちらを押さえておきましょう。


```java
public class Main {
    static int A;
    static double B;
    static String C;
    static Integer D;
    static Object E;


    public static void main(String[] args) {
        System.out.println("int = " + A);      //int = 0
        System.out.println("double = " + B);   //double = 0.0
        System.out.println("String =" + C);    //String = null
        System.out.println("Integer =" + D);   //Integer = null
        System.out.println("Object =" + E);    //Object = null
    }
}
```
<strong>プリミティブ型</strong>と<strong>参照型</strong>ではフィールドで初期化しなかった場合の初期値に違いがあります。本試験ではこれを活用した問題が必ず出題されるので注意しましょう。
<h2>配列型の出力</h2>
<h3>要素指定なし-ハッシュ値の出力-</h3>
下記のような感じでnew（インスタンス化）した場合、要素を指定しないと<strong>ハッシュ値</strong>が出力されます。


```Java
public class Main {

    public static void main(String[] args) {
        
        int [] arrayInt1 = new int [0];
        int [] arrayInt2 = new int [3];
        String [] arrayString1 = new String[0];
        String [] arrayString2 = new String[3];


        System.out.println(arrayInt1);      //[I@2626b418
        System.out.println(arrayInt2);      //[I@5a07e868
        System.out.println(arrayString1);   //[Ljava.lang.String;@76ed5528
        System.out.println(arrayString2);   //[Ljava.lang.String;@2c7b84de
    }
}
```
<h3>要素指定あり</h3>
new int[0], new String[0]の場合、要素の数は0のため、インデックス番号0を指定すると保持している要素の数より大きい数を指定しているとして、「<strong>ArrayIndexOutOfBoundsException</strong>」の実行時例外が投げられます。

ちなみにnew int[3]の場合インデックス番号0、1、2では「0」が出力され、new String[3]の場合はインデックス番号0、1、2で「null」が出力されます。

```Java
public class Main {

    public static void main(String[] args) {
        
        int [] arrayInt1 = new int [0];
        int [] arrayInt2 = new int [3];
        String [] arrayString1 = new String[0];
        String [] arrayString2 = new String[3];


        System.out.println(arrayInt1[0]);      //実行時エラー
        System.out.println(arrayInt2[0]);      //0
        System.out.println(arrayString1[0]);   //実行時エラー
        System.out.println(arrayString2[0]);   //null
    }
}
```
<h3>要素数の確認</h3>
実際に要素の数を確認してみます。

この結果を見ると先ほど紹介した例外がスローされる理由がわかると思います。
```Java
public class Main {

    public static void main(String[] args) {
        
        int [] arrayInt1 = new int [0];
        int [] arrayInt2 = new int [3];
        String [] arrayString1 = new String[0];
        String [] arrayString2 = new String[3];


        System.out.println(arrayInt1.length);      //0
        System.out.println(arrayInt2.length);      //3
        System.out.println(arrayString1.length);   //0
        System.out.println(arrayString2.length);   //3
    }
}
```

ちなみに、要素が「0」ということなので、下記コードと同じ意味となります。混同してしまいそうな時はこちらを思い浮かべましょう。

```Java
int [] array = {}; //{}はnew int [0]と同じ意味
```

<h3>明示的なnullの代入</h3>
こちらも引っ掛け問題としてよく出題されます。

要素のインデックス番号0に「null」を代入する場合と直接nullを代入する場合です。

```Java
public class Main {

    public static void main(String[] args) {
        
        String [] arrayString1 = {null};
        String [] arrayString2 = null;

        System.out.println(arrayString1);   //[Ljava.lang.String;@2626b418
        System.out.println(arrayString2);   //null
    }
}
```
前者の場合は<strong>ハッシュ値</strong>が出力され、後者の場合は<strong>null</strong>が出力されます。

そろそろ混乱してくる頃かもしれません。この辺で「<strong>NullPointerException</strong>」はどんな場合にスローされるのか？これまでに紹介してきたことと比較しつつ、次はそれを確認していきたいと思います。
```Java
public class Main {

    public static void main(String[] args) {
        
        String [] arrayString1 = {null};
        String [] arrayString2 = null;

        System.out.println(arrayString1);   //[Ljava.lang.String;@2626b418
        System.out.println(arrayString1[0]);   //null
        System.out.println(arrayString1.length);   //1

        System.out.println(arrayString2);   //null
        System.out.println(arrayString2[0]);   //NullPointerException
        System.out.println(arrayString2.length);   //NullPointerException

    }
}
```
要素にnullを指定している場合は、インデックス番号0を指定した場合そのままnullが出力されます。確認のために要素の数を出力させると想定通り「1」が出力されます。

一方で、直接nullを代入している場合は、インデックス番号を指定すると「<strong>NullPointerException</strong>」がスローされます。ちなみに、ここで要素の数の確認を行おうとすると、そもそも何も参照していない状態のnullを代入しているのでこちらも<strong>NullPointerException</strong>となります。

試験では「<strong>それっぽそうな選択肢2つとコンパイルエラーか実行時エラー」</strong>のような選択肢があるので、コンパイルエラーなのか実行時エラーなのかそれともちゃんと出力されるものなのかを理解しておく必要があります。

次に、<span style="text-decoration: underline;">そのnullを出力させる配列型変数に文字列を連結させるとどうなるのか</span>を確認してみましょう。

```Java
public class Main {

    public static void main(String[] args) {
        
        String [] arrayString1 = {null};
        String [] arrayString2 = null;

        System.out.println(arrayString1[0] + " " + "Null"); //null Null
        System.out.println(arrayString2 + " " + "Null");    //null Null
    }
}
```

それぞれ正常に出力されていますね。これも試験によく出る形なので覚えておきましょう！

<h2>最後に</h2>
今回紹介したパターンはどれも出題される可能性があります。

nullを問う単体での問題なら身構えることができるので良いのですが、他のことを聞いてそうな問題に紛れ込ませている問題も少なくありません。
「長めのコードを読んだのに結局エラー問題かい」ということになりかねないので、そういった問題に労力を使わないためにも注視するところは初めに押さえながら問題を解き進めると時間効率も良くなると思います。

次回はJavaSilver対策として、「実は3秒で解ける問題」的な感じでちょっと面白そうな記事を書こうと考えているので次回分もぜひ読んで頂きたいなと思っております。