はじめに
インフラの分野でも、Iac化が進んで行くと考えています。そこで、ノウハウが体系だっているものが学び易いと考えて、Javaを学びはじめました。
今回は、コンストラクタ にフォーカスしました。
コンストラクタの特徴
Javaにおけるコンストラクタは、クラスのインスタンス(オブジェクト)を生成するときに呼ばれる特別なメソッド。コンストラクタは、オブジェクトの初期化を行うために使用される。
- コンストラクタは、オブジェクトを初期化するための特別なメソッド。
- 引数なしと引数付きのコンストラクタをオーバーロードして使うことができる。
-
this
キーワードを使って、インスタンス変数と引数を区別できる。
- クラス名と同じ名前を持つ。
- 戻り値の型(
void
も含む)を持たない。 - オブジェクトが生成される際に、自動的に呼ばれる。
- 引数を持たないコンストラクタを「デフォルトコンストラクタ」と呼び、引数を持つコンストラクタを「引数付きコンストラクタ」と呼ぶ。
コンストラクタの基本的な例
class Car {
String model;
int year;
// 引数なしのコンストラクタ
public Car() {
model = "Unknown";
year = 2020;
}
// 引数付きのコンストラクタ
public Car(String model, int year) {
this.model = model;
this.year = year;
}
// メソッドで情報を表示
public void displayInfo() {
System.out.println("Model: " + model);
System.out.println("Year: " + year);
}
public static void main(String[] args) {
// 引数なしコンストラクタを使ってオブジェクトを生成
Car car1 = new Car();
car1.displayInfo();
// 引数付きコンストラクタを使ってオブジェクトを生成
Car car2 = new Car("Tesla", 2023);
car2.displayInfo();
}
}
コンストラクタの種類
-
デフォルトコンストラクタ(引数なしコンストラクタ)
- 明示的に定義しない場合でも、Javaが自動的に提供。
- クラス内で引数付きのコンストラクタを定義すると、デフォルトコンストラクタは提供されない。
-
引数付きコンストラクタ
- インスタンスを生成するときに、必要な初期値を設定するために使用される。
コンストラクタのオーバーロード
複数のコンストラクタを定義することを「コンストラクタのオーバーロード」と呼ぶ。同じクラス内に引数の数や型が異なる複数のコンストラクタを定義することができる。
class Rectangle {
int width, height;
// 引数なしのコンストラクタ
public Rectangle() {
width = 1;
height = 1;
}
// 引数付きのコンストラクタ
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
// 面積を計算するメソッド
public int getArea() {
return width * height;
}
public static void main(String[] args) {
// 引数なしのコンストラクタ
Rectangle rect1 = new Rectangle();
System.out.println("Area: " + rect1.getArea());
// 引数付きのコンストラクタ
Rectangle rect2 = new Rectangle(5, 7);
System.out.println("Area: " + rect2.getArea());
}
}
this
キーワード
コンストラクタ内で、this
キーワードを使って現在のインスタンスを指すことができる。例えば、引数名とインスタンス変数名が同じ場合、this
を使って区別することができる。
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name; // 引数のnameをインスタンス変数nameに代入
this.age = age; // 引数のageをインスタンス変数ageに代入
}
public void displayInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
public static void main(String[] args) {
Person person = new Person("Alice", 30);
person.displayInfo();
}
}
this
キーワードを使ってインスタンス変数と引数を区別できる理由
背景
Javaでは、メソッドやコンストラクタ内で変数を使う際に、インスタンス変数(クラスのフィールド)と引数(ローカル変数)が同じ名前であると、名前の衝突が発生します。その場合、ローカル変数(引数)が優先され、インスタンス変数にはアクセスできません。
このような場合に、this
キーワードを使うことで、インスタンス変数を明示的に参照することができます。
-
this
キーワードは、現在のインスタンスを参照。 - 引数とインスタンス変数の名前が同じ場合、
this
を使ってインスタンス変数にアクセス。 -
this
はインスタンス変数を明示的に指すため、引数の名前と区別しやすくなる。
class Person {
String name; // インスタンス変数
int age; // インスタンス変数
// コンストラクタの引数とインスタンス変数が同じ名前
public Person(String name, int age) {
// 引数のnameとインスタンス変数nameが同じ名前
this.name = name; // 引数nameをインスタンス変数nameに代入
this.age = age; // 引数ageをインスタンス変数ageに代入
}
public void displayInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
public static void main(String[] args) {
Person person = new Person("Alice", 30);
person.displayInfo(); // 出力: Name: Alice, Age: 30
}
}
-
インスタンス変数
クラスのフィールドとして定義されている変数。ここではname
とage
がインスタンス変数。 -
引数
メソッドやコンストラクタに渡される値。コンストラクタPerson(String name, int age)
の引数としてname
とage
。
this
キーワードの役割
this
は、現在のオブジェクトを指す参照。これを使うことで、コンストラクタやメソッド内でインスタンス変数を明示的に参照できる。
this.name = name; // 引数nameをインスタンス変数nameに代入
- 左辺の
this.name
は、インスタンス変数name
を指しています。 - 右辺の
name
は、コンストラクタの引数name
を指しています。
this
を使わなければ、name
だけではローカル変数(引数)を指すことになり、インスタンス変数を変更することができません。
this
を使わないとどうなるか?
this
を使わない場合、コンストラクタ内で引数の名前とインスタンス変数の名前が同じだと、コンパイラは引数を優先し、インスタンス変数にはアクセスできません。例えば次のようになります。
class Person {
String name; // インスタンス変数
int age; // インスタンス変数
// コンストラクタの引数とインスタンス変数が同じ名前
public Person(String name, int age) {
name = name; // これは引数nameを自身に代入しているだけ
age = age; // 同様に、引数ageを自身に代入しているだけ
}
public void displayInfo() {
System.out.println("Name: " + name + ", Age: " + age);
}
public static void main(String[] args) {
Person person = new Person("Alice", 30);
person.displayInfo(); // 出力: Name: null, Age: 0
}
}
この場合、name = name;
や age = age;
は、自分自身に代入しているだけで、インスタンス変数の値を更新していません。結果的に、インスタンス変数 name
と age
は初期値(null
と 0
)のままです。