Javaのコンストラクタを基本から解説します

- SE
- Javaではコンストラクタとはどのようなものなのでしょうか。
- PM
- クラスのインスタンスを生成した時に最初に実行される、初期化用メソッドのことです。
この記事でわかること
Javaのコンストラクタとは?
Javaのコンストラクタとは、クラスのインスタンスを生成した時に最初に実行される、初期化用メソッドのことです。以下のTestClassと同名のメソッドがコンストラクタです。
class TestClass {
public TestClass() {
System.out.println(“”TestClassのインスタンスが生成されました。””);
}
}
以下のようにクラスを生成すると、
TestClass c = new TestClass();
以下のようにコンソールに表示されます。newで生成すればコンストラクタが実行されることがわかります。
TestClassのインスタンスが生成されました。
パラメータ付きのコンストラクタ
上のJavaサンプルを見ると、public TestClass()に戻り値の型がありません。コンストラクタが返すものは常にそのクラスのインタンスのため、省略するというルールになっているのです。なおコンストラクタが不要であれば、コンストラクタ自体を省略もできます。
コンストラクタには以下のようにパラメータを持たせることができます。
class TestClass {
private int val;
public TestClass(int val) {
this.val = val;
System.out.println(this.val+””に初期化しました。””);
}
}
thisで同名のフィールドを区別できる
上のJavaサンプルで、this.というワードが出て来ています。これは「自分のクラスの」という意味になります。クラスのフィールドのvalとパラメータのvalが同じ名前なので、thisを付けて区別しているのです。
以下のようにnewすると、
TestClass c = new TestClass(3);
以下のように表示されます。
3に初期化しました。
コンストラクタのオーバーロード
Javaにはオーバーロードという、パラメータを変えることで同名のメソッドを複数持てる機能があります。以下のようにコンストラクタもこのオーバーロードを利用できます。
class TestClass {
private int val;
public TestClass() {
val = 0; // パラメータがない場合は0で初期化する
}
public TestClass(int val) {
this.val = val; // パラメータがある場合はその値で初期化する
}
}
コンストラクタが複数あることによる弊害
コンストラクタのオーバーロードができるのは良いのですが、コンストラクタで行う処理が多い場合、以下のようになります。
class TestClass {
private int val;
public TestClass() {
val = 0;
コンストラクタの長い処理が続く・・・
}
public TestClass(int val) {
this.val = val;
コンストラクタの長い処理が続く・・・
}
}
ほとんど同じ内容を複数の箇所に記述することになり、変更の時は間違いも発生しやすくなります。これを回避するにはどうしたらいいでしょうか。
this()を使えば問題は解決
上のような問題は、以下のようにthis()を使うと解決します。
class TestClass {
private int val;
public TestClass() {
this(0);
}
public TestClass(int val) {
this.val = val;
コンストラクタの長い処理が続く・・・
}
}
this()はコンストラクタ内から別のコンストラクタを呼ぶ機能です。これでコンストラクタの処理の記述を一か所にまとめられます。なお、this()はコンストラクタ内の先頭に1回だけ記述できるというルールがあります。
コンストラクタをprivateにする意味
Javaのコンストラクタは、public以外のアクセス修飾子も使えます。protectedにすれば、同じパッケージか子クラスだけしか呼び出せなくなります。そしてコンストラクタをprivateにするとnewができなくなります。意味がないように思うかもしれませんが、意味はあります。
class Sum {
private Sum() {
}
static int add(int a, int b) {
return a+b;
}
}
このSumクラスはSum.add(2, 3);のようにnewをせずに使うことを意図しています。このようなクラスはnewされるべきではありません。そういう時にコンストラクタをprivateにすることで、newされることを防げるのです。
継承の時のコンストラクタの動作
クラスを継承した場合、コンストラクタはどのように呼ばれるのでしょうか。以下のJavaサンプルをご覧ください。
class ClassA {
public ClassA() {
System.out.println(“”ClassAのコンストラクタ””);
}
}
class ClassB extends ClassA {
public ClassB() {
System.out.println(“”ClassBのコンストラクタ””);
}
}
以下のようにClassBのインスタンスを生成すると、
ClassB b = new ClassB();
以下のように表示されます。親のクラスのコンストラクタが先に実行されるということです。
ClassAのコンストラクタ
ClassBのコンストラクタ
親クラスのオーバーロードされたコンストラクタを呼ぶには?
上のJavaサンプルのClassAが以下のように複数あって、ClassBをnewした時に、ClassAのパラメータのある方のコンストラクタを呼びたい場合はどうしたらよいのでしょうか。
class ClassA {
public ClassA() {
System.out.println(“”ClassAのコンストラクタ””);
}
public ClassA(String str) {
System.out.println(str);
}
}
super()で呼び出す親のコンストラクタを選べる
その場合は以下のようにsuper()を使用します。
class ClassB extends ClassA {
public ClassB() {
super(“”ClassAのコンストラクタをsuperでコール””);
System.out.println(“”ClassBのコンストラクタ””);
}
}
ClassBをnewすると、以下のように表示されます。ClassAのString型のパラメータのある方のコンストラクタが呼ばれていることがわかります。
ClassAのコンストラクタをsuperでコール
ClassBのコンストラクタ
なおsuper()もthis()のように、コンストラクタの先頭で1度しか呼べないという決まりがあります。また1つのコンストラクタの中でthis()とsuper()の両方を使うことはできません。
コンストラクタ参照について
Java 8からはメソッドをパラメータ無しで呼べるメソッド参照という機能が追加されました。そしてコンストラクタもコンストラクタ参照というやり方で呼ぶことが出来ます。以下の例は関数型インターフェイスのSupplierにDate型をnewして渡しています。
なおソースの先頭には、
import java.util.*;
import java.util.function.*;
を追加してください。
Supplier<Date> supp = Date::new;
Date d = supp.get();
System.out.println(d.toString());
あまり実用的な例ではないですが、コンストラクタ参照というものもある、というくらいは知っておいてよいでしょう。
- SE
- Javaでのコンストラクタの使い方やルールがわかりました。
- PM
- コンストラクタのコード例を参考にして、ぜひご自身で試してみてください。
Javaのコンストラクタはクラス生成の基本
Javaのコンストラクタについて解説しましたが、ご理解頂けたでしょうか。コンストラクタについて知ることはJavaのクラス生成の基本中の基本なので、しっかりおさえておきましょう。