本記事は、Javaを一から学んでいく際の学習メモとして書かれています。
主にインプレスから出版されている「スッキリわかるJava入門 第2版 (スッキリシリーズ)」の内容に沿ったかたちで学習していきます。
コンストラクタとは
コンストラクタ(constructor)とは、クラスからインスタンスを生成する際に1度だけ呼び出されるメソッドの一種になります。
主にフィールドを初期化するために利用されます。
コンストラクタの使い方
まずはコンストラクタを利用してみます。
前回作成したBookクラスにコンストラクタを追加します。
// Book.java public class Book{ String title; String author; int price; // コンストラクタ public Book(String title, String author, int price){ this.title = title; this.author = author; this.price = price; } @Override public String toString(){ return "title:" + title + " author:" + author + " price:" + price; } }
// Main.java public class Main { public static void main(String[] args) { Book book = new Book("スッキリわかるJava入門", "中山清喬/国本大悟", 2600); System.out.println(book.toString()); // title:スッキリわかるJava入門 author:中山清喬/国本大悟 price:2600 } }
コンストラクタは、上記のように「アクセス修飾子 クラス名(){}」のように宣言します。
その為、インスタンス化をする際はそのクラス名が固定化されるため、インスタンス化時の挙動を変えたりする場合は、ファクトリーメソッド(factory method)というデザインパターンを利用することにより、インスタンス化する際の名称を変更することが可能になります。
なお、コンストラクタを記述しなかった場合はデフォルトコンストラクタ(後述)というものが呼ばれますが、記述した場合、引数のセットなど、それに従ってインスタンス化をしなければいけません(正しい引数を渡してあげなければコンパイルエラーとなります)。
また、アクセス修飾子をprivateにすることで、サブクラスからのインスタンス化を防止することもできます。
コンストラクタのオーバーロード
コンストラクタもメソッドの一種になるので、オーバーロードが可能です。
また、クラス内で定義しているコンストラクタを他のコンストラクタ内で呼び出す場合は「this(...);」のようにして呼び出すことができます。
ちなみに、このthis
はJVM(Java VM)が用意した変数の1つで、インスタンス自身の参照が入っています。
以下では、引数なしのコンストラクタから上記で定義したコンストラクタを呼び出しています。
// Book.java public class Book{ String title; String author; int price; public Book(String title, String author, int price){ this.title = title; this.author = author; this.price = price; } public Book(){ this("none", "none", 0); } @Override public String toString(){ return "title:" + title + " author:" + author + " price:" + price; } }
// Main.java public class Main { public static void main(String[] args) { Book book = new Book(); System.out.println(book.toString()); // title:none author:none price:0 } }
デフォルトコンストラクタ
クラス内でコンストラクタを定義しなかった場合、デフォルトコンストラクタ(default constructor)というものが呼び出されます。
これは、コンパイル時にコンパイラがこっそりと追加しくれるものです。
前回作成したコンストラクタ無しのBookクラスをコンパイルし、javap
コマンドでクラスファイルの中身を確認してみます。
> javac Book.java > javap -c Book.class Compiled from "Book.java" public class Book { java.lang.String title; java.lang.String author; int price; public Book(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return ...
上記の11行目で「public Book()」がこっそり追加されていることが確認できます。
継承とコンストラクタ
クラスはextendsをすることで、スーパークラス(親クラス)のフィールドとメソッドをサブクラス(子クラス)が継承することができますが、コンストラクタは継承することができません(フィールドやメソッドでもprivateなものは同様に引き継ぐことができません)。
スーパークラス側でコンストラクタの記述がなかったり、引数なしのコンストラクタが定義されていた場合は、サブクラス側でコンストラクタの記述がなくてもコンパイラが自動でスーパークラスのコンストラクタを追加してくれます。
以下では上記で作成したBookクラスを継承したBookSubクラスを作成し、javap
コマンドでクラスファイルの中身を確認してみます。
// BookSub.java public class BookSub extends Book {}
> javac BookSub.java > javap -c BookSub.class Compiled from "BookSub.java" public class BookSub extends Book { public BookSub(); Code: 0: aload_0 1: invokespecial #1 // Method Book."<init>":()V 4: return }
8行目でBookクラスのデフォルトコンストラクタが追加されていることが確認できます。
最後に
今回はJavaのコンストラクタについての基本的なルールを学びました。
次回は、Javaの列挙型(enum型)について学んでいきます。
参考書籍