コンストラクタの罠

このレッスンでは、デフォルトコンストラクタが消える条件と this() の使い方を判定できるようになります。

まず予測してください

次のコードはコンパイルできるでしょうか。

class Box { int size; Box(int size) { this.size = size; } } Box b = new Box(); // ここは通る?

答えはコンパイルエラーです。Box() という引数なしのコンストラクタが存在しないからです。

デフォルトコンストラクタは「1つも書かなかったとき」だけ生まれる

Java のコンパイラは、クラスにコンストラクタが1つも書かれていないときに限って、引数なしのコンストラクタを自動で足します。これがデフォルトコンストラクタです。

つまり Box(int size) を1つでも自分で書いた瞬間、自動生成は行われません。引数なしで作りたければ、自分で Box() を書き足す必要があります。試験ではこの一点だけを突いてくる問題が繰り返し出ます。

this() は先頭にしか置けない

同じクラスの別のコンストラクタを呼ぶときは this(...) を使います。ここにも決まりがあります。

class Box { int size; Box() { this(10); // 必ず1行目 } Box(int size) { this.size = size; } }

覚えることは次の3つです。

  1. this(...) はコンストラクタの先頭行でなければならない。2行目に書くとコンパイルエラー
  2. this(...)super(...) は同じコンストラクタに同時に書けない。どちらも先頭を要求するため
  3. this(...) で自分自身を呼ぶと再帰的な呼び出しとみなされ、コンパイルエラーになる

コンストラクタは戻り値の型を書かない

もう1つの定番の引っ掛けが、戻り値の型を付けてしまう形です。

class Box { void Box() { } // これはコンストラクタではなく、ただのメソッド }

void が付いた時点でこれは Box という名前のメソッドです。コンストラクタは1つも書かれていないと判断されるので、デフォルトコンストラクタが生成され new Box() は通ります。読み飛ばすと必ず間違えるので、選択肢に void が混ざっていないかを毎回確かめてください。

演習で確かめます

引数なしで作ったときの既定値と、引数ありで作ったときの値の両方を返して、this() の連鎖が実際に効いていることを目で確かめます。

要件

  1. Box に引数なしのコンストラクタを追加し、その中で this(10) を呼ぶこと
  2. Box(int size) は書き換えないこと
  3. build は new Box() と new Box(n) の 2 つを作り、size をカンマ区切りでつないだ文字列を返すこと

入出力例

build(3)"10,3" build(7)"10,7" build(0)"10,0"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.java
学習モード

メモ

コンストラクタの罠

⌘S で保存