変数の初期値（Java言語仕様4.12.5）

[Java8の言語仕様4.12.5 Initial Values of Variables](http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.5)に変数の初期値について定義されてます。この記事はこの節と関連する用語をまとめたものです。

#変数の初期化

プログラム中の各変数はその値が使用する前にある値を持たなければならない:

##初期値

クラス変数、インスタンス変数、または配列要素は生成されるときに**初期値**（*default value*）で初期化される:

|  型           |  初期値   |
|:--------------|:----------|
| byte          | 0         |
| short         | 0         |
| int           | 0         |
| long          | 0L        |
| float         | 0.0f      |
| double        | 0.0d      |
| char          | '\u0000'  |
| boolean       | false     |
| 参照型        | null      |

以下、注意です。

+ 「0.0f」、「0.0d」はそれぞれfloat型、double型に対する浮動小数点型リテラルです。
+ 「0L」はlong型に対する整数値リテラルです。
+ 「'\u0000'」は文字リテラルです。文字リテラルは開始「'」と終了「'」で囲みます。
+ boolean型の値は「true」または「false」です。これらはbooleanリテラルです。
+ 「null」はNULLリテラルです。

リテラルについては「3.10 Literals」に載ってます。

参照型（*reference types*）は以下の4つです。

+ クラス型（class types）
+ インターフェース型（interface types）
+ 型変数（type variables）
+ 配列型（array types）

次の例は仕様書のExample 4.12.5-1にコメントを追加したものです。この例ではクラス変数、インスタンス変数が初期化されます。

```java:例
class Point {
    static int npoints; // プリミティブ型のクラス変数
    int x, y;           // プリミティブ型のインスタンス変数
    Point root;         // 参照型のインスタンス変数
}

class Test {
    public static void main(String[] args) {
        System.out.println("npoints=" + Point.npoints);
        Point p = new Point();
        System.out.println("p.x=" + p.x + ", p.y=" + p.y);
        System.out.println("p.root=" + p.root);
    }
}
```

```java:Test#main()の結果
npoints=0
p.x=0, p.y=0
p.root=null
```

以下はインターフェース型、型変数、配列型の例です。

```java:例
class MyClass<T> {

    public List<String> list; // インターフェース型
    public T t;               // 型変数
    public String[] strs;     // 配列型

}
```

上記の変数はインスタンス生成時にnullで初期化されます。

##メソッドのパラメータ

メソッドのパラメータはメソッドの呼び出しによって与えられる対応する引数の値によって初期化される。

```java:例
public class Test {

    public static void main(String[] args) {

        print(1, 2); // メソッドの呼び出し

    }

    private static void print(int x, int y) { // メソッドのパラメータ

        System.out.println("x: " + x);
        System.out.println("y: " + y);

    }

}
```

```java:実行結果
x: 1
y: 2
```


##コンストラクタのパラメータ

コンストラクタのパラメータはクラスのインスタンス生成の式または明示的なコンストラクタ呼び出しで与えられる対応した引数の値によって初期化される。

以下はExample 8.8.7-1にコメントを追加したプログラムです。

```java:例
class Point {
    int x, y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

class ColoredPoint extends Point {
    static final int WHITE = 0, BLACK = 1;
    int color;

    ColoredPoint(int x, int y) { // コンストラクタのパラメータ
        this(x, y, WHITE);       // 明示的なコンストラクタ呼び出し
    }

    ColoredPoint(int x, int y, int color) {
        super(x, y); // 明示的なコンストラクタ呼び出し
        this.color = color;
    }
}
```

##例外のパラメータ

例外のパラメータはスローされた例外を表しているオブジェクトで初期化される。

```java:例
package exceptionParameter;

public class Test {

    public static void main(String[] args) {

        try {
            throw new RuntimeException();
        } catch (Exception e) { // 例外のパラメータ
            e.printStackTrace();
        }

    }

}
```

```java:結果
java.lang.RuntimeException
	at exceptionParameter.Test.main(Test.java:8)
```

##ローカル変数

ローカル変数は使用される前に以下の方法で明示的に初期化されなくてはならない。

1. 初期化
2. 代入
3. 確定的代入（definite assignment）規則を使用した（コンパイラが）確認可能な方法

3番については「CHAPTER16 Definite Assignment」の内容です。その章に載っているExample 16-1の一部が以下です。

```java:例
        {
            int k;
            if (v > 0 && (k = System.in.read()) >= 0)
                System.out.println(k);
        }
```

「v > 0」がtrueのとき、kの入力待ちになります。InputStream#read()メソッドの返却値は0 - 255の範囲のintですので、if文の条件式がtrueになります。入力後にkが出力されます。

最後に、ローカル変数が初期化されてない例を挙げます。

```java:例
public class Test {

    public void test() {

        int x;

        System.out.println(x);

    }

}
```

初期化指定な状態で出力しようとしています。Eclipseだと「ローカル変数 x が初期化されていない可能性があります」というエラーが出ます。

![error.png](https://qiita-image-store.s3.amazonaws.com/0/133921/7c7a5280-7922-3a68-7978-03a175bc85be.png)

#参考サイト

http://www.y-adagio.com/public/standards/tr_javalang2/jTOC.doc.html