アットウィキロゴ
Javaプログラミング入門
掲示板 掲示板 ページ検索 ページ検索 メニュー メニュー

Javaプログラミング入門

15. コンストラクタ

最終更新:

javatutorial

- view
管理者のみ編集可

これまでのやり方の不便な点

前回は、クラスから new を使ってインスタンス(実体)を作り、そのあとにフィールド(変数)へデータを一つずつ代入する方法を学びました。
例えば、生徒を作るプログラムでは以下のように書いていましたね。

Student s1 = new Student();
s1.name = "山田";
s1.score = 80;
しかし、この方法には2つの大きな不便な点があります。

① 手間がかかること
生徒が100人いたら、名前と点数を代入する処理を200行も書かなければなりません。書くコードが長くなり、プログラムが見づらくなってしまいます。

② 設定し忘れる危険があること
名前だけ代入して、点数を代入し忘れてしまうとどうなるでしょうか?データとして不完全な「点数が空っぽの生徒」ができてしまい、後で計算をするときにエラーの原因になってしまいます。

インスタンスが作られた時点で、最初から名前や点数がセットされていれば、手間も省けて設定忘れも防げますよね。
それを実現する便利な仕組みが「コンストラクタ」です。

コンストラクタとは?

コンストラクタとは、インスタンスが作られるのと同時に、自動的に実行される特別な処理のことです。

変数を作るときに、宣言と同時に最初の値を入れる「初期化」という作業がありましたね。
コンストラクタは、いわば「インスタンスの初期化」を行うためのものです。

例えば、お店で新しくスマートフォンを買ったとき、店員さんがその場で初期設定(言語の設定やアカウントの作成など)をしてから渡してくれますよね。
それと同じように、インスタンスが生まれた瞬間に、必要なデータを準備して完成された状態で渡してくれるのがコンストラクタの役割です。

コンストラクタの作り方

コンストラクタは、クラスの中に書いていきます。
メソッドの書き方とよく似ていますが、絶対に守らなければならない特別なルールがあります。

public クラス名(受け取るデータ) {
    // インスタンスが作られたときの初期化処理
} 

コンストラクタの3つのルール
① 名前は必ずクラス名と完全に同じにする
② メソッドのように戻り値の型(voidやintなど)を絶対に書かない
③ newを使ってインスタンスを作るときに、一度だけ自動で呼び出される

それでは、コンストラクタと今まで学んだメソッドの違いを表で確認しておきましょう。
メソッドとコンストラクタの違い
特徴 メソッド コンストラクタ
名前 どんな名前でも自由につけられる クラス名と完全に同じにする
戻り値の型 void や int などを必ず書く 絶対に何も書かない
呼ばれるタイミング プログラムの中で自分で呼び出したとき new でインスタンスを作った瞬間

実際にコンストラクタを使ってみよう

では、前回の Student クラスにコンストラクタを追加してみましょう。
新しく生徒を作るときに、名前と点数を受け取って、自分のフィールドに代入する処理を書きます。

サンプル:Student.java
  1. public class Student {
  2. String name; // 名前
  3. int score; // 点数
  4.  
  5. // コンストラクタ
  6. public Student(String studentName, int studentScore) {
  7. name = studentName;
  8. score = studentScore;
  9. }
  10. }

次に、このコンストラクタを使ってインスタンスを作ってみます。
new を使うときの丸括弧 () の中に、渡したいデータを直接入れます。

サンプル:Main.java
  1. public class Main {
  2. public static void main(String[] args) {
  3. // インスタンスを作成すると同時にデータを渡す
  4. Student s1 = new Student("山田", 80);
  5. Student s2 = new Student("佐藤", 95);
  6.  
  7. // データの表示
  8. System.out.println(s1.name + "さんの点数は" + s1.score + "点です。");
  9. System.out.println(s2.name + "さんの点数は" + s2.score + "点です。");
  10. }
  11. }
実行結果
山田さんの点数は80点です。
佐藤さんの点数は95点です。
いかがでしょうか。前回はインスタンスを作った後に s1.name = "山田"; のように何度も書いていましたが、コンストラクタを使えばたった1行でスッキリと書くことができます。
さらに、「名前と点数を丸括弧の中に書かないと生徒を作れない」というルールを強制できるため、データの設定忘れを完全に防ぐことができるようになりました。

デフォルトコンストラクタについて

ここで一つ、鋭い方は疑問が浮かぶかもしれません。
「前回のクラスとインスタンスの学習では、コンストラクタを一つも書いていなかったのに、new Student() でエラーにならずにインスタンスを作れたのはなぜ?」

実は、Javaには初心者を助ける親切な機能があります。
プログラマーがクラスにコンストラクタを1つも書かなかった場合、Javaのコンパイラ(翻訳機)が自動的に「中身が空っぽのコンストラクタ」をこっそりと追加してくれるのです。
この自動で作られるコンストラクタのことを「デフォルトコンストラクタ」と呼びます。

ただし、一つだけとても重要な注意点があります。
プログラマーが自分でコンストラクタを1つでも書いた場合は、デフォルトコンストラクタは自動生成されなくなります。
そのため、先ほどコンストラクタを作った Student クラスに対して、データを渡さずに new Student() と丸括弧を空っぽにして実行しようとすると、コンパイルエラーになってしまいます。

💡注意!
初心者が一番よくやってしまうミスが、コンストラクタに間違えて void を書いてしまうことです。
public void Student(String studentName, int studentScore) { ... }  
void を書いてしまうと、Javaはこれを「コンストラクタ」ではなく、「Studentという名前の普通のメソッド」だと勘違いしてしまいます。
その結果、new をしたときに処理が実行されず、エラーの原因になったり、データが空っぽのままになったりします。
コンストラクタには絶対に void などの戻り値を書かないように気をつけてください。

コラム

thisキーワード

コンストラクタの中で、受け取ったデータをフィールドに入れるとき、先ほどは studentName のように少し違う名前をつけました。
しかし、現場のプログラミングでは、フィールド名と受け取るデータ名を「同じ名前」にすることが一般的です。
同じ名前にしたとき、どちらがフィールドの変数なのかをJavaに伝えるために this という特別なキーワードを使います。
this は「自分自身のインスタンス」を意味します。
public class Student {
    String name;
 
    public Student(String name) {
        // this.name は「フィールドのname」、右の name は「丸括弧で受け取ったname」
        this.name = name; 
    }
}
 
最初は少しややこしいですが、とてもよく使われる書き方なので、少しずつ慣れていきましょう。

JVMの視点から見るコンストラクタ(<init>メソッド)

少し高度なお話になりますが、Javaのプログラムが翻訳されてJVM(Java仮想マシン)が動く形式(バイトコード)になるとき、コンストラクタは「<init>」という特別な名前のメソッドに変換されます。
これは「インスタンス初期化メソッド(Instance Initialization Method)」と呼ばれます。
Javaの文法上は「コンストラクタはメソッドではない(戻り値がないなどのルールがあるため)」と習いますが、実はコンピュータの深い部分(JVM)から見ると、すべて <init> という名前の特殊なメソッドとして扱われている、という面白い裏話があります。

デフォルトコンストラクタのアクセス修飾子

プログラマーがコンストラクタを書かなかったときに自動で作られる「デフォルトコンストラクタ」ですが、実は何も考えずに public がつくわけではありません。
Javaの言語仕様では、「デフォルトコンストラクタのアクセス修飾子は、クラスのアクセス修飾子と同じになる」と厳密に決められています。
つまり、 public class Student ならデフォルトコンストラクタも public Student() になりますが、単なる class Student だった場合、デフォルトコンストラクタには public がつかないのです。
プログラムの安全性を守るための、Javaの隠れた賢い仕組みの一つです。

最近更新されたスレッド
人気記事ランキング
ウィキ募集バナー