Code Fix

上級

super() と this() の呼び出しルール

必ず先頭に置く必要があります。親に引数なしコンストラクタがない場合の対処を扱います。

エラーメッセージの読み方

Main.java:5: error: constructor Base in class Base cannot be applied to given types;
Main.java
ファイル名
5
行番号 — javacが異常に気づいた位置。原因の行とは限りません
error
種別 — コンパイルエラー。実行まで到達しません
constructor Base in class Base cannot be applied to given types;
内容 — javacが期待していたもの、または見つけられなかったもの

このエラーが出る典型パターン

パターン1

 1  class Base {
 2      Base(int n) {}
 3  }
 4  public class Main extends Base {
 5      Main() {           }
                     ^
 6      public static void main(String[] args) {
 7          new Main();
 8          System.out.println("ok");
 9      }
10  }
Main.java:5: error: constructor Base in class Base cannot be applied to given types; required: int found: no arguments

親に引数なしコンストラクタがないと、子は明示的にsuper(...)を呼ぶ必要があります。

直し方: (空) を super(1); にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  class Base {
 2      Base() { System.out.println("base"); }
 3  }
 4  public class Main extends Base {
 5      Main() {
 6          System.out.println("main");
 7          super();
                ^
 8      }
 9      public static void main(String[] args) { new Main(); }
10  }
Main.java:7: error: call to super must be first statement in constructor

super()はコンストラクタの先頭にしか置けません。省略すると自動で先頭に挿入されます。

直し方: super(); を (空) にします。

この問題を解いてみる →

パターン3

 1  public class Main {
 2      int a, b;
 3      Main(int a) { super   (a, 0); }
                          ^
 4      Main(int a, int b) { this.a = a; this.b = b; }
 5      public static void main(String[] args) {
 6          System.out.println(new Main(1).b);
 7      }
 8  }
Main.java:3: error: constructor Object in class Object cannot be applied to given types

同じクラスの別のコンストラクタを呼ぶのはthis(...)です。super(...)は親を指します。

直し方: super を this にします。

この問題を解いてみる →

パターン4

 1  class Base {
 2      Base(int n) {}
 3  }
 4  public class Main extends Base {
 5      int x = 5;
 6      Main() { super(x     ); }
                          ^
 7      public static void main(String[] args) { new Main(); }
 8  }
Main.java:6: error: cannot reference x before supertype constructor has been called

super()の引数の中では、まだ自分自身のフィールドは初期化されていません。親のコンストラクタが終わるまでインスタンスは存在しない扱いです。

直し方: x を 5 にします。

この問題を解いてみる →

パターン5

 1  class Base {
 2      Base(int a, int b) {}
 3  }
 4  public class Main extends Base {
 5      Main() { super(1     ); }
                          ^
 6      public static void main(String[] args) { new Main(); }
 7  }
Main.java:5: error: constructor Base in class Base cannot be applied to given types; required: int,int

super()の引数の数と型は、親クラスのコンストラクタと完全に一致させる必要があります。

直し方: 1 を 1, 2 にします。

この問題を解いてみる →

よくある誤解

super()は書かなくても自動で挿入されます。書く場合は必ず先頭でなければなりません。

実務での勘所

super()を先頭に置かなければならないのは、スタイルの都合ではなくJVMレベルの制約です。オブジェクトは親クラスの初期化が完全に終わってから子クラスの初期化に進むという順序が厳格に決まっており、これを破ると親クラスが期待する前提が崩れた状態で子クラスのコードが動いてしまいます。この制約の帰結として、super()に渡す引数の中でthisやまだ初期化されていないインスタンスフィールド・メソッドを使うことはできません。オブジェクトがまだ存在していない段階だからです。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)