7.2 クラスの主要なメンバー（フィールド、メソッド、コンストラクタ）～Java Basic編

### はじめに

#### 自己紹介

皆さん、こんにちは、Udemy講師の斉藤賢哉です。私はこれまで、25年以上に渡って企業システムの開発に携わってきました。特にアーキテクトとして、ミッションクリティカルなシステムの技術設計や、Javaフレームワーク開発などの豊富な経験を有しています。
様々なセミナーでの登壇や雑誌への技術記事寄稿の実績があり、また以下のような書籍も執筆しています。
* [「マスタリング Java EE 5」（2007年）](https://amzn.asia/d/j0txqK5)
* [「アプリケーションアーキテクチャ設計パターン」（2017年）](https://amzn.asia/d/9avaCyF)

いずれも**Java EE**（**Jakarta EE**）を中心にした企業システム開発のための書籍です。中でも [「アプリケーションアーキテクチャ設計パターン」](https://amzn.asia/d/9avaCyF)は、（Javaに限定されない）比較的普遍的なテーマを扱っており、内容的にはまだまだ陳腐化していないため、興味のある方は是非手に取っていただけると幸いです（中級者向け）。

#### Udemy講座のご紹介

この記事の内容は、私が講師を務めるUdemy講座『**Java Basic編**』の一部の範囲をカバーしたものです。『**Java Basic編**』はこちらの[**リンク**](https://www.udemy.com/course/learn-java-se-basic/?referralCode=594C958456356851C97C)から購入できます（セールス対象外のためいつも同じ価格）。また**定価の約30%OFFで購入可能なクーポン**をQiita内で定期的に発行していますので、興味のある方は、ぜひ私の他の記事をチェックしてみてください。

この講座は、以下のような皆様に強くお薦めします。
* Javaの言語仕様や文法を正しく理解すると同時に、現場での実践的なスキル習得を目指している方
* 新卒でIT企業に入社、またはIT部門に配属になった、新米システムエンジニアの方
* 長年IT部門で活躍されてきた中堅層の方で、学び直し（リスキル）に挑戦しようとしている方
* 今後、フリーランスエンジニアとしてのキャリアを検討している方
* 「**Chat GPT**」のエンジニアリングへの活用に興味のある方
* 「**Oracle認定Javaプログラマ**」の資格取得を目指している方
* IT企業やIT部門の教育研修部門において、新人研修やリスキルのためのオンライン教材をお探しの方

#### この記事を含むシリーズ全体像

この記事はJava SEの一部の機能・仕様を取り上げたものですが、一連のシリーズになっており、**シリーズ全体でJava SEを網羅**しています。また認定資格である「**Oracle認定Javaプログラマ**」（Silver、Gold）の範囲もカバーしています。シリーズの全体像および「Oracle認定Javaプログラマ」の範囲との対応関係については、以下を参照ください。

https://qiita.com/KenyaSaitoh/items/4711a078a851510bc4da

## 7.2 クラスの主要なメンバー

### チャプターの概要

このチャプターでは、クラスの主要なメンバーであるフィールド、メソッド、コンストラクタについて学びます。

### 7.2.1 フィールド

#### フィールドとは

フィールドとは、クラスが持つ属性や状態を表すためのメンバーで、一種の変数です。ローカル変数と対比して、メンバー変数と呼ばれることもあります。
フィールドは、これまで出てきた通常の変数と同じように、以下のように宣言します。

```java:【構文】フィールド宣言
データ型 フィールド名;
```

また以下のように、宣言と同時に初期値を設定することも可能です。

```java:【構文】フィールド宣言
データ型 フィールド名 = 値;
```

ただしフィールドの初期値は、このようにクラス内に埋め込んでしまうよりも、後述するコンストラクタによって設定するケースの方が大半でしょう。
なお1つのクラスの中で、同一の名前を持った複数のフィールドを宣言することはできません。

### フィールドへのアクセス

前述したようにクラスのインスタンスはnew演算子によって生成しますが、フィールドには以下の構文のようにクラス型変数（生成されたインスタンス）を起点にアクセスします。

```java:【構文】フィールドへのアクセス
クラス型変数名.フィールド
```

このようにクラス型変数の後ろに`.`を記述して、アクセス対象のフィールドを指定します。なお存在しないフィールドを指定すると、コンパイルエラーになります。
それでは先に取り上げた「人物」を題材に、フィールドのみを持つPerson2クラスを作成してみましょう。

```java:Person2
class Person2 {
    String name;
    int age;
}
```

次にこのクラスの外部でインタンスを生成し、変数p2を起点に、2つのフィールド、nameとageに値を代入します。

```java:snippet_1 (Main_7_2)
Person2 p2 = new Person2();
p2.name = "Alice";
p2.age = 25;
```

フィールドには通常の変数と同じように、代入演算子`=`を使って値を代入します。

次にこのインスタンスの2つのフィールドを、コンソールに表示してみましょう。

```java:snippet_2 (Main_7_2)
System.out.println("name => " + p2.name);
System.out.println("age => " + p2.age);
```

このコードを実行すると、nameフィールドの値として"Alice"が、ageフィールドの値として25が、それぞれコンソールに表示されます。

#### フィールドの修飾子

フィールドにもクラスと同様に、その性質を表すために特定の修飾子を付与することがあります。修飾子はフィールド宣言の前に記述します。
フィールドに付与可能な修飾子には以下の種類がありますが、詳細は別チャプターで取り上げます。

* public    … すべてのクラスからアクセス可能であることを表す（チャプター10.1参照）
* protected … 自クラスおよび同一パッケージのクラスと、 自身の子クラスからアクセス可能であることを表す（チャプター10.1参照）
* private   … 自クラスのみからアクセス可能であることを表す（チャプター10.1参照）
* static    … スタティックフィールドであることを表す（チャプター8.1参照）
* final     … 再代入を禁止することを表す（チャプター8.2参照）
* transient … シリアライズ対象外であることを表す（本コース対象外）
* volatile  … スレッドがフィールド値を個別にキャッシュすることを抑制する（本コース対象外）

#### フィールドの命名

フィールド名は一種の識別子のため、「レッスン2.1.5 識別子とキーワード」で触れたルールに則ってさえいれば、任意の名前を付けることができます。ただし可読性確保の観点から、フィールドの命名には「Lower Camel Case」（チャプター3.1参照）を採用するのが、一般的なコーディング上の規約です。例えば「顧客種別」であれば「customerType」となるでしょうし、「前月の最初の日」であれば「prevMonth1stDay」などになるでしょう。

### 7.2.2 メソッド

#### メソッドとは

メソッドとは、クラスの振る舞いを表すメンバーで、任意の処理を実装するためのものです。Java SEなどのクラスライブラリによって外部公開されたメソッドは、APIとも呼ばれています。メソッドに実装された処理は、別の場所から呼び出される[^1]ことによって実行されます。
メソッドは、以下のように宣言します。

```java:【構文】メソッド宣言
戻り値型 メソッド名(型1 引数名1, 型2 引数名2, 型3 引数名3, ....) {
    ....メソッド本体の処理....
}
```

メソッド宣言の先頭には、戻り値のデータ型を指定します。戻り値とは、メソッドの処理結果を返すための値で、メソッド内の特定の位置でreturn文によって指定します。
メソッドには、戻り値を返すものもあれば戻り値がないものもありますが、戻り値の詳細は次のレッスンで取り上げるため、ここではまず戻り値がないメソッドで説明を進めます。
戻り値がないメソッドでは、戻り値型にはvoidを指定します。voidは「戻り値がない」ことを意味するもので、キーワードの一種です。
次にメソッド名を記述しますが、戻り値型とメソッド名の間には1つ以上のスペースが必要です。メソッド名の後ろには`( )`を記述し、`( )`の中に引数を指定します。引数とは、メソッドに外部から与えられる変数です。メソッド宣言では、1つの引数はデータ型と引数名の組み合わせによって指定します。引数は`,`で区切って任意の個数を指定することができますが、0個でも問題ありません。

#### メソッド呼び出し（戻り値なし）

ここでは、戻り値がないメソッドを呼び出す方法を説明します。メソッドは、別クラスから呼び出すこともあれば、同一クラスの他メソッドから呼び出すこともあります。
別クラスから呼び出す場合は、以下の構文のように、クラス型変数を起点に呼び出します。

```java:【構文】メソッド呼び出し元（別クラスから）
クラス型変数名.メソッド名(引数1, 引数2, 引数3, ....);
```

また同一クラスから呼び出す場合は、以下の構文のように、直接メソッドを呼び出します。

```java:【構文】メソッド呼び出し元（同一クラス内）
メソッド名(引数1, 引数2, 引数3, ....);
```

メソッドの呼び出し元と、呼び出し先（メソッド宣言した側）との対応関係を図に示すと、以下のようになります。

【図7-2-1】メソッド呼び出しの対応関係（戻り値なし）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/59630b4f-db8f-c058-8f2b-37b176e22dbd.png)

このように呼び出し元における引数と、呼び出し先における引数とは、指定された順番通りに対応します。このとき型の不一致があると、コンパイルエラーになります。

#### メソッド呼び出し（戻り値なし）の具体例

それではメソッドを宣言し、それを別クラスから呼び出す方法を具体的に見ていきましょう。
任意の文字列を複数回、コンソールに表示するという処理を行うPrinterクラスを作成します。

```java:Printer
public class Printer {
    void printMessage(String message, int count) {
        for (int i = 0; i < count; i++) {
            System.out.println(message);
        }
    }
}
```

このクラスは、任意の文字列を複数回、コンソールに表示する処理を行うためのメソッドとして、printMessage()メソッドを保持しています。printMessage()メソッドは戻り値を持たないため、戻り値型にはvoidキーワードを指定します。
このメソッドには引数が2つあります。第一引数はString型の引数messageで、第二引数はint型の引数countです。メソッドが受け取った引数は、メソッド内の処理ではローカル変数として扱われます。このメソッドのブロック内を見ていくと、for文のループによってcount変数の数だけ、message変数に格納された文字列をコンソールに表示しています。

次にこのメソッドを呼び出すためのコードです。

```java:snippet_3 (Main_7_2)
Printer printer = new Printer();
printer.printMessage("Hello, Alice!", 5);
```

このようにPrinterクラスのインスタンスを生成し、そのprintMessage()メソッドを呼び出しています。第一引数には"Hello, Alice!"という文字列を、第二引数にはint型として5を指定しています。このコードを実行すると、printMessage()メソッドに文字列"Hello, Alice!"と整数5が引き渡され、コンソールに"Hello, Alice!"が5回表示されます。

#### メソッドによる処理の共通化

メソッドはクラスの振る舞いを表すためのものですが、共通的な処理を一か所にまとめるために定義する、という目的があります。先に登場したPrinterクラスのprintMessage()メソッドは、「指定された回数だけ、指定された文字列を、コンソールに表示する」というものでした。従って例えばあるアプリケーションにおいて、"Hello, Alice!"という文字列を5回表示したり、"Goodbye, Bob!"という文字列を10回表示したりする、という仕様があった場合、このメソッドを利用すると処理を共通化することができます。
具体的には、以下のように引数を変えてprintMessage()メソッドを呼び出すだけで、このような仕様を実現することができます。

```java:snippet_4 (Main_7_2)
Printer printer = new Printer();
printer.printMessage("Hello, Alice!", 5);
printer.printMessage("Goodbye, Bob!", 10);
```

【図7-2-2】メソッドによる処理の共通化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/0ba1f4a1-f80e-0af7-90b3-3c4457b1b17a.png)

もしこのメソッドがなかったら、アプリケーション内の様々な場所で、同じようなコードを何か所も記述しなければなりません。このように共通的な処理をメソッドとして抽出し、引数によって振る舞いを切り替えるようにすることで、開発効率を大きく向上させることができます。

:::note info
メソッドによって処理の共通化を図ることができます。
:::

#### メソッドの修飾子

メソッドにもクラスやフィールドと同様に、その性質を表すために特定の修飾子を付与することがあります。修飾子はメソッド宣言の前に記述します。
メソッドに付与可能な修飾子には以下の種類がありますが、詳細は別チャプターで取り上げます。

* public       … すべてのクラスからアクセス可能であることを表す（チャプター10.1参照）
* protected    … 自クラスおよび同一パッケージのクラスと、 自身の子クラスからアクセス可能であることを表す（チャプター10.1参照）
* private      … 自クラスのみからアクセス可能であることを表す（チャプター10.1参照）
* static       … スタティックメソッドであることを表す（チャプター8.1参照）
* final        … オーバーライドを禁止することを表す（チャプター11.1参照）
* abstract     … 抽象メソッドであることを表す（チャプター11.1参照）
* synchronized … マルチスレッド環境において同期化することを表す（『Java Advanced編』参照）
* strictfp     … 浮動小数点の演算が実行環境に依存しないことを表す（本コースでは対象外）
* native       … Java以外の言語で記述されたメソッドであることを表す（本コースでは対象外）

#### メソッドの命名

メソッド名も一種の識別子のため、「レッスン2.1.5 識別子とキーワード」で触れたルールに則ってさえいれば、任意の名前を付けることができます。ただし可読性確保の観点から、メソッドもフィールドと同様に「Lower Camel Case」（チャプター3.1参照）を採用し、動詞のみまたは動詞＋名詞と命名するのが、一般的なコーディング上の規約です。例えば「挨拶のメッセージを生成するためのメソッド」であれば、`createGreetMessage()`などになるでしょう。
またメソッドが何らかのリソースに対して、取得、作成、削除、更新といった操作を行う場合は、取得（get、read）、作成（create、write）、削除（remove、delete）、更新（update、write、replace）といった単語が良く使われます。
メソッドで何らかの判定処理を行い、その結果を論理値（boolean型変数）で返却する場合は、is〇〇（～であるか）や、can〇〇（～ができるか）、has〇〇（～を持っているか）といった命名が一般的です。

:::note info
メソッド名には、get＋フィールド名や、set＋フィールド名という名前も非常に多く使われますが、これはフィールド値を参照したり設定したりするためのメソッドで、アクセサメソッドとも呼ばれます。アクセサメソッドについては、チャプター10.1で取り上げます。
:::

#### メソッドと関数

メソッドに近い概念に「関数」があります。C言語などの手続き型言語では、関数はJavaのメソッドと同じように手続きを表すためのものです。
一方Javaでは、メソッドと関数は文脈によっては同じように扱われることもありますが、厳密には異なる概念です。Javaにおける関数は関数型インタフェースのオブジェクトであり、ラムダ式によって実装されます。関数はいわゆる「第一級オブジェクト」の一種であり、直接生成したり、変数に代入したり、メソッドの引数や戻り値に指定したりすることが可能です。
Javaにおける関数について詳細は『Java Advanced編』での説明に譲りますが、ここではまず「Javaでは、厳密にはメソッドと関数は異なるものだ」と理解してもらえれば問題ありません。

:::note info
Javaではメソッドと関数は異なるものであり、関数はラムダ式によって実装される「第一級オブジェクト」の一種です。
:::

### 7.2.3 メソッドと戻り値

#### メソッドの戻り値

戻り値とはメソッドの処理結果を返すための値で、メソッド内の特定の位置でreturn文によって指定します。

```java:【構文】return文
return 戻り値;
```

return文には、returnキーワードによってメソッドが実際に返す値を指定します。returnキーワードと戻り値の間には、1つ以上のスペースが必要です。returnキーワードによって指定された戻り値のデータ型が、メソッド宣言において指定された戻り値型と異なる場合は、コンパイルエラーになります。
メソッドの処理はreturn文に到達すると、指定された値を返してその処理は終了になります。従ってreturn文よりも後ろで、条件分岐などを加味しても到達しえない位置に何らかの命令文を記述すると、コンパイラによってエラーが検知されます。

#### メソッド呼び出し（戻り値あり）

ここでは、戻り値があるメソッドを呼び出す方法を説明します。
別クラスから戻り値のあるメソッドを呼び出す場合は、以下の構文のようになります。

```java:【構文】メソッド呼び出し元（戻り値あり）
戻り値型 変数 = クラス型変数名.メソッド名(引数1, 引数2, 引数3 …);
```

一つ前のレッスンでは、メソッドが戻り値を持たない前提で、メソッドの呼び出し元と呼び出し先との対応関係を図（図7-2-1）に示しました。メソッドが戻り値を持つ場合は、メソッドの呼び出し元と呼び出し先との対応関係は、以下のようになります。

【図7-2-3】メソッド呼び出しの対応関係（戻り値あり）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/eb382636-4c36-c1c9-0753-e0c8ae140c72.png)

このとき、呼び出したメソッドが返した値と、呼び出し元で受け取った変数の間で型の不一致があると、コンパイルエラーが発生します。

#### 戻り値のあるメソッド呼び出しの具体例

それでは、戻り値のあるメソッドを宣言し、それを別クラスから呼び出す方法を具体的に見ていきましょう。
ここでは足し算と引き算の機能を持つ計算機を、Calculatorクラスとして作成します。
以下のコードを見てください。

```java:Calculator
class Calculator {
    int add(int x, int y) {
        int result = x + y;
        return result;
    }
    int subtract(int x, int y) {
        int result = x - y;
        return result;
    }
}
```

このCalculatorクラスには、足し算を行うためのadd()メソッドと、引き算を行うためのsubtract()メソッドが宣言されています。
戻り値の型には、メソッド内で行った計算結果をint型で返す仕様のため、intを指定します。
これらのメソッドは、2つの引数xとyを取り、それらの値をもとにメソッド内で計算を行い、その結果をreturn文で返却します。
add()メソッドのreturn文を見ると、計算結果が格納された変数resultを指定しています。このようにreturn文には戻り値を指定しますが、戻り値の型さえ一致していれば、何らかの式を指定したり、別のメソッド呼び出しを直接指定することも可能です。例えば、`return x + y;`と一文で記述することができます。変数resultを何度も参照する必要がないのであれば、このように一文で済ましてしまうのも1つの方法です。

次にadd()メソッドを呼び出して、足し算を実行するための処理を見ていきましょう。以下のコードを見てください。

```java:snippet_5 (Main_7_2)
Calculator calc = new Calculator();
int answer = calc.add(30, 10);
System.out.println(answer);
```

このコードを実行すると、Calculatorクラスのadd()メソッド呼び出しによって40が返され、その値がコンソールに表示されます。

#### return文とvoid型

これまで説明してきたとおり、return文はメソッドの戻り値を指定するために使用します。
ただし戻り値がvoid型であっても、return文を使用することがあります。条件分岐の結果、もうそれ以上処理を行う必要がなくなり、メソッドの処理を終了させたい場合は、戻り値はvoid型であってもreturn文を使用します。

```java:snippet
    void doSomething() {
        if(....) {
            return; // メソッドの処理を終える
        }
    }
```

このとき、return文に戻り値は指定しません。

### 7.2.4 変数のスコープとメソッド・フィールド

#### フィールドのスコープ

「レッスン6.1.2 ローカル変数のスコープ」にて、ローカル変数のブロックスコープについては取り上げました。ここでは視野をクラス全体に広げて、フィールドおよびローカル変数のスコープ全体像を整理します。
すでに説明したように、各ローカル変数のスコープは、宣言された位置から当該ブロックの最後までになります。それに対してフィールドのスコープは、クラス全体になるため、クラス内のあらゆるメンバーからアクセス可能です。
以下は、典型的なクラスの構成を表したものです。

【図7-2-4】典型的なクラスの構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/d4ecb2e9-4477-7809-6ed7-4bcc9abd9276.png)

この図では、フィールドaのスコープはこのクラス全体になるため、メソッドb()の中など、あらゆる位置からアクセスが可能です。一方、ローカル変数cのスコープはメソッドb()内に、また、ローカル変数dのスコープはif文の中に、それぞれ閉じられます。
またフィールドとローカル変数は、名前が競合しても問題はありませんが、どちらにもアクセス可能な場合はローカル変数が優先されます。例えばあるクラスにフィールドfooがあり、そのクラスのメソッド内でローカル変数fooを宣言した場合、そのメソッド内でfooという変数名を指定すると、ローカル変数が優先されます。

#### thisキーワードによるメンバーアクセス

thisキーワードとは、クラス内において、自分自身のインスタンスへの参照を表すための特殊な変数です。thisキーワードには様々な用途がありますが、その中の1つが自身のメンバーへのアクセスです。以下の構文を見てください。

```java:【構文】thisキーワードによるフィールドへのアクセス
this.フィールド
```

このようにthisキーワードの後ろに`.`を記述して、アクセス対象のフィールドを指定します。例えばPersonクラス内で、自クラス内のnameフィールドには`this.name`とアクセスします。ただし自クラスの中からであっても、`name`とフィールド名を指定するだけで、nameフィールドへのアクセスは可能です。

では敢えてthisキーワードを用いるケースとは、どういうものでしょうか。それは、ローカル変数との識別が必要なケースです。前述したように、フィールドとローカル変数は名前の競合が認められており、その場合はローカル変数が優先されます。このようなケースにおいて、フィールドにアクセスするためには、thisキーワードを使用して、フィールドであることを明示する必要があります。
なおthisキーワードのその他の用途については、次のレッスン以降で順次取り上げます。

#### メソッド内からフィールドへのアクセス

メソッドは、与えられた引数に応じて処理を行いますが、フィールド値を参照して、それに基づいて何らかの処理を行う場合もあります。またメソッド内の処理において、フィールド値を更新する場合もあります。メソッド内からは、フィールド名を直接指定することによって、フィールドにアクセスすることができます。
それではここで、既出のPersonクラスのsayHello()メソッドを改めて見てみましょう。

```java:snippet_1 (Person)
void sayHello() {
    String message = "こんにちは！私は" + name +  "、" + age + "歳です。";
    System.out.println(message);
}
```

このメソッドは、nameフィールドやageフィールドの値を参照して挨拶のメッセージを生成し、それをコンソールに表示します。このときフィールド名の前にthisキーワードは必要ありません（ローカル変数との識別が不要なため）。

次にこのPersonクラスと同内容のPerson3クラスをベースに、「成人かどうか」を判定するためのisAdult()メソッドを追加します。

``` java:snippet_1 (Person3)
boolean isAdult() {
    return 20 <= age;
}
```

このようにageフィールドを参照して「成人かどうか」を判定し、その結果を論理値で返却します。論理値を返すメソッドには、is〇〇、can〇〇、has〇〇といった名前を付けるのが一般的です。

最後にPerson3クラスに、「年を1つ取る」ためのincreaseAge()メソッドを追加します。

``` java:snippet_2 (Person3)
void increaseAge() {
    age += 1;
}
```

このメソッドでは、ageフィールドを更新しています（1を加算）。このようにメソッド呼び出しによって、クラスのフィールド（すなわち状態）が変化することを「副作用」と呼びます。

### 7.2.5 コンストラクタ

#### コンストラクタとは

コンストラクタとは、new演算子によってインスタンスを生成する時に自動的に呼び出される、特殊なメソッドのようなものです。
クラスからインスタンスを生成するために、1つかまたは複数個のコンストラクタが必要です。コンストラクタはインスタンス生成時に呼び出されるため、その目的はクラスそのものの初期化にあります。通常はフィールドに対する初期値を設定したり、何らかの外部リソースを読み込んで定義情報をセットアップしたりするために実装します。
コンストラクタは、以下の構文のように宣言します。

```java:【構文】コンストラクタ宣言
コンストラクタ名(型1 引数名1, 型2 引数名2, 型3 引数名3, ....) {
    ....コンストラクタ本体の処理....
}
```

コンストラクタ名は、必ずクラス名と一致させるように宣言します。コンストラクタ名の後ろには`( )`を記述し、`( )`の中に引数を指定します。引数はメソッドと同様に、データ型と引数名の組み合わせを`,`で区切って指定します。

#### new演算子とコンストラクタ呼び出し

ここでは、new演算子によってコンストラクタがどのように呼び出されるのかを説明します。new演算子の構文はレッスン7.1.2で説明済みですが、実はnew演算子によってクラス名を指定するときに、メソッドのように引数を渡すことができます。
以下の構文を見てください。

```java:【構文】インスタンス生成
データ型 変数名 = new クラス名(引数1, 引数2, 引数3, ....);
```

ここで指定した引数と、コンストラクタにおける引数とは、メソッド同様に指定された順番通りに対応します。このとき型の不一致があると、コンパイルエラーになります。

#### コンストラクタの具体例

それではクラス内にコンストラクタを宣言し、そのコンストラクタがnew演算子によってどのように呼び出されるのか、具体的に見ていきましょう。
ここでは例として、既出のPersonクラスを用います。Personクラスのコンストラクタは、以下のようになっています。

```java:snippet_2 (Person)
Person(String name, int age) {
    this.name = name;
    this.age = age;
}
```

このようにコンストラクタの名前は、必ずクラス名と一致させるように宣言します。このコンストラクタは、2つの引数、String型のnameと、int型のageを取りますが、受け取った引数は、コンストラクタ内の処理ではローカル変数として扱われます。コンストラクタの目的は、前述したようにクラスの初期化にありますが、ここではnameフィールドとageフィールドに、受け取った引数を代入することで初期化しています。
これはコンストラクタの典型的な実装例です。この例のように、コンストラクタでフィールドを初期化するにあたり、受け取る引数名をフィールド名と同じにし、thisキーワードを付けることによってフィールドを識別するケースが一般的です。

次にこのクラスのインスタンスを、コンストラクタによって生成するコードを見ていきましょう。

```java:snippet_6 (Main_7_2)
Person p1 = new Person("Alice", 25); //【1】
Person p2 = new Person("Bob", 35); //【2】
```

このようにnew演算子に続けてクラス名を記述し、メソッドのように引数を渡すことでコンストラクタを呼び出します。ここでは2つのPersonインスタンスを生成しています。
まず【1】では第一引数に文字列"Alice"、第二引数にint型25を指定していますので、nameフィールドに"Alice"、ageフィールドに25が設定されたPersonインスタンスが生成され、変数p1に代入されます。また同じように【2】では第一引数に文字列"Bob"、第二引数にint型35を指定していますので、nameフィールドに"Bob"、ageフィールドに35が設定されたPersonインスタンスが生成され、変数p2に代入されます。

【図7-2-5】コンストラクタ呼び出しによるインスタンス生成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/3d1137d5-48df-4cc9-77d4-96e9b8244bb2.png)

#### 引数を1つも取らないコンストラクタ

インスタンスを生成するためにはコンストラクタが必要ですが、「引数を1つも取らないコンストラクタ」に限っては開発者が明示的に宣言する必要はありません。「引数を1つも取らないコンストラクタ」とは、具体的には以下のようなコンストラクタです。

```java:snippet
Person() {
}
```

このような「引数を1つも取らないコンストラクタ」がクラス内に宣言されていなくても、実は`Person p = new Person()`といった形でインスタンスは生成可能です。これは、コンパイラによって「引数を1つも取らないコンストラクタ」が暗黙的に生成されるためです。コンパイラによって暗黙的に生成されるコンストラクタを、デフォルトコンストラクタと呼びます。

ただしデフォルトコンストラクタが生成されるのは、あくまでも「コンストラクタが1つも宣言されていない場合」に限定されます。従ってPersonクラスのように、引数を取るコンストラクタを1つでも宣言した場合は、デフォルトコンストラクタは生成されません。もしこのPersonクラスを`Person p = new Person()`といった形でインスタンス化したい場合は、「引数を1つも取らないコンストラクタ」を開発者が明示的に宣言する必要があります。

:::note warn
コンパイラが「引数を1つも取らないコンストラクタ」を暗黙的に生成するのは、「コンストラクタが1つもない場合」に限定されます。
:::

#### コンストラクタの修飾子

コンストラクタにも、特定の修飾子を付与することがあります。修飾子はコンストラクタ宣言の前に記述します。
コンストラクタに付与可能な修飾子には以下の種類がありますが、詳細は別チャプターで取り上げます。

* public    … すべてのクラスからアクセス可能であることを表す（チャプター10.1参照）
* protected … 自クラスおよび同一パッケージのクラスと、 自身の子クラスからアクセス可能であることを表す（チャプター10.1参照）
* private   … 自クラスのみからアクセス可能であることを表す（チャプター10.1参照）

### このチャプターで学んだこと

このチャプターでは、以下のことを学びました。

1. フィールドの宣言や初期化、アクセスするための方法について。
1. フィールドの修飾子について。
1. フィールドは「Lower Camel Case」という規約で命名すること。
1. メソッドの特徴や宣言する方法、引数を渡して呼び出す方法について。
1. メソッドの戻り値やreturn文について。
1. メソッドの修飾子について。
1. メソッドは「Lower Camel Case」という規約で命名すること。
1. メソッドと関数の違いについて。
1. フィールドのスコープや、thisキーワードによるメンバーアクセスついて。
1. コンストラクタの特徴や宣言する方法、引数を渡して呼び出す方法について。
1. デフォルトコンストラクタの特徴について。
1. コンストラクタの修飾子について。

[^1]:メソッドは常にその外側から呼ばれるわけではなく、当該メソッドの中から自身を呼び出すケースもある。これを再帰呼び出し（チャプター7.3）と呼ぶ。