コンストラクタ周りの覚え書き

じぶんめも。

列挙型のコンストラク

  • privateのみ
  • 明示的親コンストラクタ起動(super();)を書けない
  • チェック例外をスローできない*1
    • throws RuntimeException と書く分にはOKなので、構文自体はクラスのコンストラクタと同様

デフォルトコンストラク

  • クラス(列挙型でない)がコンストラクタ宣言を保持していない場合、デフォルトコンストラクタが自動的に提供される
    • パラメータを受け取らない
    • チェック例外をスローできない
    • 親クラスの引数をとらないコンストラクタを起動するだけ
    • デフォルトコンストラクタの可視性(public, protected, ...)はクラスの可視性と一致する
  • 列挙型がコンストラクタ宣言を保持していない場合、デフォルトコンストラクタが自動的に提供される
    • パラメータを受け取らない
    • java.lang.Enumの引数をとらないコンストラクタを起動するだけ
    • デフォルトコンストラクタの可視性は常にprivate
  • インターフェース、注釈型にはそもそもコンストラクタがない

インスタンス初期化子

  • インスタンスフィールドの初期化式は、インスタンス初期化子内で実行されるものと思うのがよさそう
  • インスタンス初期化子の内容は、それぞれのコンストラクタ内に織り込まれると思うのがよさそう
  • インスタンス初期化子でチェック例外がスローされる可能性がある場合、すべてのコンストラクタのthrows節にその例外を書けばコンパイルエラーにならない。下のような感じ。
public class InstanceInit {
    {
        raise();
    }
    static int raise() throws IOException {
        throw new IOException();
    }
    InstanceInit() throws IOException {}
}
  • インスタンス初期化子に直接throw文やreturn文を書くとエラーになる
  • 匿名クラスのインスタンス初期化子は盛大にチェック例外をスローしてよい
try {
    new Object() {
        {
            raise();
        }
        void raise() throws IOException {
            throw new IOException();
        }
    };
}
catch (IOException e) {
    e.printStackTrace();
}

静的初期化子

  • クラス変数の初期化子は、静的初期化子内で実行されるものと思うのがよさそう
    • コンパイル時定数となる初期化子は実行するまでもなく値が分かるので、少しだけ別扱いになる模様
  • 静的初期化子のが複数ある場合、上から順に実行される
  • 静的初期化子はローカルクラス、匿名クラス、staticでないメンバクラス内では宣言できない
    • 同様に、コンパイル時定数とならないフィールド初期化子を持つクラス変数もこれらの中で宣言できない
  • 静的初期化子よりテキスト的にあとに出現するクラス変数を利用できない
    • 完全にできないわけではないが、規則がいろいろと面倒

いろいろと癖がある。

*1:なんかコンパイラのエラーメッセージが変?