【Java】コンストラクタとは - 意味や使い方を解説
- 作成日:2022/02/02
new演算子でインスタンスを生成するときに呼び出されるコンストラクタについて解説します。
コンストラクタとは
コンストラクタとはnew演算子でインスタンスを生成するときに呼び出されるメソッドです。 メソッド名はクラスメイト同じ名前です。
例をご紹介します。
class TestClass {
TestClass(){
System.out.println("initialization");
}
}
public class App {
public static void main(String[] args) {
TestClass test = new TestClass();
}
}
3~8行目のTestClassはコンストラクタだけをもつクラスです。 上述した通り、クラス名と同じメソッドはコンストラクタとなります。
13行目でTestClass型のインスタンス(test)をnewして生成しますが、このタイミングでTestClassのコンストラクタが呼ばれます。
initialization
コンストラクタには引数を設定することはできますが、戻り値を設定する必要はありません。 戻り値は生成するクラスの型(上記の例だとTestClass型)なので明記する必要はないのです。
省略とデフォルトコンストラクタ
コンストラクタは省略することができますが、省略すると自動でデフォルトコンストラクタというメソッドが作成されます。 中身は次のようになります。
class TestClass {
TestClass(){
super();
}
}
super()を呼び出すだけのコンストラクタです。 super()は親クラスのコンストラクタを呼ぶ構文です。 これについては後述するスーパークラスのコンストラクタで詳しく解説しますが、クラス継承をしなければ何もしないメソッドです。
よって、コンストラクタを明示的に記述しなくても勝手にデフォルトコンストラクタが呼ばれるのでエラーにはなりません。 インスタンス生成時に処理が必要なければ、コンストラクタは省略しても良いのです。
引数を設定する
コンストラクタには引数を設定することもできます。
class TestClass {
TestClass(String tmp){
System.out.println(tmp);
}
}
public class App {
public static void main(String[] args) {
TestClass test = new TestClass("sample");
}
}
12行目でnewするときにコンストラクタに文字列を渡しています。 4~7行目のコンストラクタで文字列を受け取り、それを出力しています。
sample
通常のメソッドと同様に、コンストラクタの引数は複数設定することが可能です。
複数のコンストラクタ
コンストラクタは複数用意(オーバーロード)することが可能ですが、呼び出されるコンストラクタは1つだけです。 どのコンストラクタを呼ぶのかは引数で判断します。
例として2つのコンストラクタを用意して、その中の1つを呼び出す処理を紹介します。
class TestClass {
//1つ目のコンストラクタ
TestClass(){
System.out.println("initialization");
}
//2つ目のコンストラクタ
TestClass(String tmp){
System.out.println(tmp);
}
}
public class App {
public static void main(String[] args) {
TestClass test = new TestClass("sample");
}
}
5行目には引数がないコンストラクタを、9行目には引数があるコンストラクタを用意しました。
18行目のnewでコンストラクタを呼び出すとき、引数に文字列を渡しています。 なので、9行目のコンストラクタが呼び出されます。
sample
このように、引数を変えることで、コンストラクタを複数用意することができます。 ただし、引数の型と数が全く同じコンストラクタは定義できません。どちらのコンストラクタを呼び出すのかわからくなりますからね。
thisメソッド
コンストラクタが複数あっても、呼ぶことができるのは1つだけです。 しかし、thisメソッドを使えばコンストラクタからコンストラクタを呼ぶことができます。
これを利用して複数のコンストラクタの内容を実行できます。例を見てみましょう。
class TestClass {
//1つ目のコンストラクタ
TestClass(){
System.out.println("initialization");
}
//2つ目のコンストラクタ
TestClass(String tmp){
this();
System.out.println(tmp);
}
}
public class App {
public static void main(String[] args) {
TestClass test = new TestClass("sample");
}
}
18行目でnewをしてコンストラクタを呼び出すとき、引数に文字列を指定しています。なので10行目のコンストラクタが呼ばれますが、 その中にthis()という構文があります。
thisメソッドは自身のコンストラクタを呼ぶときに指定するものなので、5行目のコンストラクタを呼び出します。
initialization
sample
もしも、thisメソッドで呼び出すコンストラクタに引数がある場合は、this(引数)となります。 また、thisメソッドはコンストラクタの先頭に記述しなければ構文エラーになります。
スーパークラスのコンストラクタ
クラス継承をしたクラスをnew演算子で生成した場合、 継承元のクラス(スーパークラス)のコンストラクタは必ず実行しなければなりません。その時に使うのが「super()」という構文です。
具体的に解説します。下記のように、親クラスと、それを継承した子クラスがあるとします。
//親クラスの宣言
class Parent{
Parent(){
System.out.println("Parent_initialization");
}
}
//子クラスの宣言
class Child extends Parent{
Child(){
super();
System.out.println("Child_initialization");
}
}
public class App {
public static void main(String[] args) {
Child test = new Child();
}
}
19行目でクラスのインスタンを生成するときに、Childクラスのコンストラクタが実行されます。 ChildクラスはParentクラスを継承しているので、Parentクラスのコンストラクタを実行しなければなりません。 Parentクラスのコンストラクタは「super()」で呼び出します(11行目)。
superメソッドはサブクラスのコンストラクタの先頭に記述します。
Parentクラスのコンストラクタが呼ばれた後に、Childクラスのコンストラクタが実行されます。
Parent_initialization
Child_initialization
このように、クラス継承をしてインスタンスを生成した場合、継承元となるスーパークラスのコンストラクタが実行された後に、 継承先となるサブクラスのコンストラクタが実行されます。
super()の省略
スーパークラスのコンストラクタを記述していない場合、または引数がないコンストラクタの場合は super()を省略できます。
//親クラスの宣言
class Parent{
Parent(){
System.out.println("Parent_initialization");
}
}
//子クラスの宣言
class Child extends Parent{
Child(){
System.out.println("Child_initialization");
}
}
public class App {
public static void main(String[] args) {
Child test = new Child();
}
}
Parentクラスを継承したChildクラスのコンストラクタ内には、親クラスのコンストラクタを呼び出すsuperメソッドがありません。 しかし、これでも親クラスのコンストラクタは呼び出されます。
Parent_initialization
Child_initialization
仮に親クラスにコンストラクタがなかったとしたら、デフォルトコンストラクタが自動生成されるので、 やはり親クラスのコンストラクタは呼ばれます。
引数を設定する
スーパークラスのコンストラクタに引数がある場合、superメソッドにも引数を書かなければなりません。なので、引数がある場合はsuper()を省略できないのです。
//親クラスの宣言
class Parent{
Parent(String tmp){
System.out.println(tmp);
}
}
//子クラスの宣言
class Child extends Parent{
Child(){
super("arg");
System.out.println("Child_initialization");
}
}
public class App {
public static void main(String[] args) {
Child test = new Child();
}
}
11行目で継承したParentクラスのコンストラクタを呼び出していますが引数に文字列を渡しています。 4行目のParentクラスのコンストラクタを見ると、String型の文字列を受け取る仕様になっているためです。
arg
Child_initialization
このように、継承元となるスーパークラスにコンストラクタがあり、かつそれが引数をもつメソッドだとしたら、superメソッドは省略できず、必ず記載しないといけません。
また、スーパークラスに複数のコンストラクタがある場合、super()に引数を指定することで、それに対応したコンストラクタが呼ばれます。