【Java】ネストクラスに付与できる修飾子まとめ【Gold】

みなさんこんにちは！

Java Gold 取得に向けて勉強中の ひろき ppoi ( @HrkPPOI ) です。

[先日 1 度目の受験で Fail してしまい](http://www.arute.me/entry/2018/11/25/214708)，細かいところまで丁寧に学習する必要性を痛感しました。

…… と思いつつもやる気が起きず，勉強をズルズルと後回しにしていました。

 Qiita に投稿する（＝他人を理解させられるレベルで理解する）ことで「細かいところまで丁寧に学習する」モチベーションになるでしょうし，今後 Java Gold を学習するみなさんのお役にも立てると思い，記事を書きます。

※ 説明に誤りや過不足がありましたらぜひコメントにてご指摘ください。学習の目的で読ませていただいた上で，この記事の本旨にかなう範囲で記事を修正します！

## 対象読者

- Java Gold に向けて勉強中で，一通りは勉強したので試験対策的な内容が読みたい

- `高度な Java クラスの設計 -> ネストクラス` の項目で情報の多さに戸惑い「整理してくれよ！」と憤っている

- ~~紫本の記載の簡素さに苛立っている~~

## 解説に登場するクラス一覧

`『オラクル認定資格教科書 Javaプログラマ Gold SE 8』` の p.63 表を参考に，ネストクラスにまつわるクラスをまとめました。概念同士の包含関係を表すためになんちゃってクラス図も描きました。

<img width="817" alt="スクリーンショット 2019-02-09 10.27.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/356995/5203bcea-1180-1653-add7-8745dcb5566e.png">

- ネストクラス
  - クラス定義の中で定義されたクラス一般をそう呼ぶ
  - `static` 修飾子の有無で static クラス / インナークラス に分かれる
- static クラス
  - ネストクラスのうち，クラス定義部に `static` 修飾子の付されて **いる** もの
  - 外側のクラスの関連に対して関連を持つ（※）
- インナークラス
  - ネストクラスのうち，クラス定義部に `static` 修飾子の付されて **いない** もの
  - 外側のクラスのインスタンスの関連に対して関連を持つ（※）
- ローカルクラス
  - インナークラスのうち，特に，外側のクラスのメソッド内で定義されたもの
  - 外側のクラスのメソッドに対して関連を持つ（※）
- 匿名クラス
  - ローカルクラスのうち，特に，クラス名を指定せずに，クラス定義とインスタンス化を 1 つの式として記述したもの

※ は，[こちら](https://qiita.com/liguofeng29/items/6cafca5bf92e0381ee42) の記事の記述を参考にしました。簡にして要を得た言い回しだと思います😍

## 修飾子の付与可否まとめ

 Java には様々な修飾子があり，クラスの種類が増えてくると「この修飾子はこのクラスに付与できるんだっけ…？」と混乱しがちです。

理想論を言うならば，**理解していれば混乱するわけがなく，問題は理解していないことであり，表にまとめて整理することは不要** です。

「まとめ」というのはいかにも試験対策的で，茶番感があるかもしれません。

しかし `各クラスの意味を理解していれば当然に修飾子の付与可否を判断できる` というのはいささか強者の理論に過ぎると思いますし，まとめてみる（比較する）ことで理解が進むこともあるでしょう。

というわけで表にまとめてみました。

<img width="829" alt="スクリーンショット 2019-02-09 10.23.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/356995/5ccdd26f-eb9e-b604-fbcf-dc65573ab32a.png">

なんだかイケそうな気がしてきましたね…！

テキストではネストクラスの種類ごとに記載されていますから，ここでは `ふつうのクラス`  ( = ネストクラスでないクラス)  との比較しながら， **修飾子ごと** に考えていこうと思います。

## `abstract` 修飾子

`abstract` 修飾子は，クラスに付与した場合，そのクラスが抽象クラスであることを示します。

ネストクラスのうち，匿名クラスは `abstract` 修飾子を付与することができません。

そもそも匿名クラスにはクラス定義部分が存在しないため， `abstract` に限らず修飾子を付与できません。

また，匿名クラスはクラス定義とインスタンス化を 1 つの式として記述しており，そのインスタンスが代入された参照変数を通してのみクラス情報を参照することを予定しています。抽象クラスは継承によってそのサブクラスから参照されることを予定していますから，`abstract` 修飾子は匿名クラスの性質になじまず，匿名クラスに対して `abstract` 修飾子を付与することができないのでしょう。

## `static` 修飾子

static 修飾子は，付与された属性や操作が，インスタンスに属するものではなくクラスに属することを示す修飾子です。通常はメンバ変数（→ static が付与された結果，スタティック変数）やメソッドに付与されるものであって，クラスに付与されることはありません。

これに対してネストクラスの場合， **`static クラス` に限っては，クラス定義に対して static 修飾子を付与することができます**。

この点は， **static 修飾子の付与されたネストクラスを static クラスと言う** のですから，言葉の定義から考えて当然でしょう，という感じですね。

`protected` / `private` 修飾子の項目でも言及していますが，ぼくは， static クラスは **外側のクラスの属性（ statice 変数）のようなもの** だと理解しています。

##  `final` 修飾子

`final` 修飾子は，クラス定義に付与された場合，そのクラスを継承することができないことを示します。

ネストクラスのうち，匿名クラスは `final` 修飾子を付与することができません。これは `abstract` 修飾子と同様に考えることができます。

## `public` 修飾子

`public` 修飾子は，クラス定義に付与された場合，そのクラスがすべてのクラスから参照できることを示します。また，属性や操作に付与された場合，その属性や操作がすべてのクラスから参照できることを示します。

ネストクラスのうち，ローカルクラス / 匿名クラスでは `public` 修飾子を付与することができません。

ローカルクラス / 匿名クラスは，外側のクラスの，とあるメソッドの中でのみ利用されることを予定しているためです。

これは，メソッドの内部で宣言された変数が，最大でもそのメソッドの内部でのみ参照できることと同じように考えることができます。

## `protected` / `private` 修飾子

`protected` / `private` 修飾子は，付与された属性 / 操作を参照できるクラスが限定されていることを示す修飾子です。あくまでも属性 / 操作に付与する修飾子であり，ふつうのクラスに付与することはできません。

これに対して， `static クラス` ・ `インナークラス` に対しては `protected` / `private` 修飾子を付与することができます。

この点について，ぼくは以下のように理解しています。

- static クラス / インナークラスは，クラスを，**あたかも外側のクラスの属性であるかのように扱う** ものである
  - そのため，属性に付与できる修飾子はすべて付与することができる
  - static 修飾子を付与するともできるが，付与の有無によってそのネストクラスの呼びかた自体が変わる
- ローカルクラス・匿名クラスは，クラスを， **あたかも外側のクラスのローカル変数であるかのように扱う** ものである
  - ローカル変数なので，アクセス修飾子は付与できない

## おわり

というわけで，ネストクラスの種類ごとに，付与できる修飾子をまとめてみました。

インスタンス化やメソッド呼び出しなどもこんがらがりがち＆出題されがちなので，別な投稿にまとめたいと思います！