はじめに
コンストラクタについて何度か学習しているのに
出くわすと初めて見た並みに「?」になるので
この記事でコンストラクタのみを再度振り返ります。
コンストラクタって何者?
直訳は構築者という意味。
個人的によく見かける「初期化」というワードがあまり納得がいっていない。
クラスのインスタンスを発行したときに実行されるもの。
変数の初期値を設定しておくもの。
引数の受け方を事前に定義しておくもの。
クラスのインスタンス化、これがわからんのよ。
クラスのインスタンス化ってなんやねん!!!
クラス名 変数名 = new クラス名(引数);
//これがクラスのインスタンス化。
もうすこし具体的な話
設計図が書かれているAクラスがあったとして、
別のBクラスでAクラス 変数名 = new Aクラス(引数);
が他クラスで実施されて
クラスのインスタンス化がなされたときに、その引っ張られてくるクラスの値を設置する方法。
このクラスを使う(インスタンス化)ならば引数の受け皿ははこれだよ~を設定しておくのがコンストラクタ。
コンストラクタの書き方
①コンストラクタは同クラスの中に記述する
②戻り値の情報は不要
③メソッド名(コントラクタ名)はクラス名と同じ
実コード例
//mainメソッドが初めに発火
//その中でConfiguratorクラスをインスタンス化する。
public class App {
public static void main(String[] args) {
//インスタンス生成!ここでConfiguratorクラスのコンストラクタが発火!
Configurator cp = new Configurator();
}
}
class Configurator {
String message = "Hello world!!";
//コンストラクタ
Configurator(){
System.out.println(message);
}
}
大きなポイント
Configurator cp = new Configurator();
がクラスをインスタンス化しているということ。
newしている設計図(クラス)を使うぞ~!ってこと!!!
つまりインスタンス化しないとクラスは機能しない。設計図だけあって使ってないのと同じ。
クラスを記述するだけでは設計図を書いただけ扱い、インスタンス化することでようやく機能する。
オーバーロードも書いてみる
public class App {
public static void main(String[] args) {
//インスタンス生成
Computer cp = new Computer("TRAINOCAMP"); //引数あり!
}
}
class Computer {
//コンストラクタ①
Computer(){
System.out.println("コンピュータ名はデフォルトです");
}
//コンストラクタ②
//引数があるので、引数があるコンストラクトのほうが発火!
Computer(String pcname){
System.out.println("コンピュータ名は" + pcname + "です。");
}
}
コンストラクタをつかって引数をメンバー変数へ代入
public class App {
public static void main(String[] args) {
//インスタンス生成・引数は2つ!順番重要!
Computer cp = new Computer("note",128); //この引数2つをコンストラクタへ代入!!!
cp.dispSpec();
}
}
class Computer {
//メンバー変数
String type;
int storage;
//コンストラクタでメンバー変数へ他クラスのインスタンス化からの引数を代入
Computer(String pctype,int storagesize){ //このString pctype,int storagesizeの順番が大切
type = pctype;
storage = storagesize;
}
public void dispSpec(){
System.out.println("コンピュータのタイプは" + type + "です");
System.out.println("コンピュータのストレージは" + storage + "GBです");
}
}
コンストラクタをつかって引数をメンバー変数へ代入(this編)
上でやってることとほとんど同じ。
public class App {
public static void main(String[] args) {
//インスタンス生成
Computer cp = new Computer("server",512); //変数2個をコンストラクタへ!!
cp.dispSpec();
}
}
//メンバー変数とコンストラクタの引数の同じ文字で定義されている(type,storage)
//そういう時にthisをつかって区別をして定義する
class Computer {
String type;
int storage;
//引数で定義している変数に注目
Computer(String type,int storage){ //ここの引数とメンバー変数の文字が一緒!!!
this.type = type; //this.メンバー変数(type)=コンストラクタ引数(type)を代入!
this.storage = storage; //this.メンバー変数(storage)=コンストラクタ引数(storage)を代入!
}
public void dispSpec(){
System.out.println("コンピュータのタイプは" + type + "です");
System.out.println("コンピュータのストレージは" + storage + "GBです");
}
}
え?でも普通にthis使わんほうがわかりやすくない???
typeやらstorageやら同じの何回も出てきてわかりにくいわ・・・。
確かに僕もそう思ったけれど、
実開発だと変数をいろんな名前で定義するほうがかなり煩雑になるらしい。
なので極力同種の値を扱う場合は同じ変数を使うというのがセオリー!!
(余談)SpringBootではコンストラクタを簡単にできる
SpringBootを使っていく中でコンストラクタの復習をしたくなったのがきっかけ。
実は私はここを一番メモしたくてこの記事を書いている。
Lombokを使うことで使用できるアノテーションでコンストラクトの記述を省略できる。
@NoArgsConstructor
引数無しのコンストラクタを定義
package sample.lombok;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Main {
public Main(String string) {
}
}
package sample.lombok;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Main {
public Main(String string) {
//public Main() {} 引数無しのコンストラクタが生成されている
}
}
@RequiredArgsConstructor
@RequiredArgsConstructor
アノテーションをつけることで
finalで修飾されたフィールドだけを引数に受け取るコンストラクタを自動生成できる。
package sample.lombok;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class Main {
private String optional;
private final int required;
}
package sample.lombok;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class Main {
private String optional;
private final int required; //finalがついているメンバー変数のみ発火
//メンバー変数への代入するコンストラクタが生成されている
//public Main(final int number){
//this.number=number;
//}
}
@AllArgsConstructor
@AllArgsConstructor
アノテーションをつけることで
全てのフィールドを引数に受け取るコンストラクタを自動生成できる。
package sample.lombok;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Main {
private String string;
private int number;
}
package sample.lombok;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Main {
private String string;
private int number;
//メンバー変数への代入するコンストラクタが生成されている
//public Main(final String string,final int number){
//this.string=string;
//this.number=number;
//}
}
合わせ技で引数の数が異なるコンストラクタを複数定義できる
いろいろな引数のコンストラクタを準備することで、
クラスがインスタンス化したときの対応の幅がふえるよね。
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class Person3 {
private long id;
private String name;
private int age;
}
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class Person3 {
private long id;
private String name;
private int age;
//@NoArgsConstructorで引数無しコンストラクタの生成
//public Person3() {
//}
//@AllArgsConstructorでメンバー変数を全部引数として受けるコンストラクターを生成
//public Person3(final long id, final String name, final int age) {
//this.id = id;
//this.name = name;
//this.age = age;
//}
}
コンストラクタを2つ定義したことで
①引数0個Person3 pr = new Person3();
②引数3個Person3 pr = new Person3(1,"yamada",20);
のような2パターンの引数の数に対応になった!!!!
参考にしたサイト