ネストしたクラスを対策する
黒本の第1章は『クラスとインタフェース』、この中にあるネストしたクラスについて対策を進めていく。
そもそもネストしたクラスとは、クラス定義の中にさらに定義されたクラスのことを指す。コードで書くと下記のようなものだ。
見ただけで直感的に分かりやすいのではないだろうか。
※黒本の解説では入れ子状態の一番外側にあるクラスのことをエンクロージングクラスと呼んでいる。この記事でも多用するので頭に入れておこう。
class outer { // エンクロージングクラス class inner { } // インナークラス static class staticInner { } // staticインナークラス }
そんなネストしたクラスには4種類あり、定義は下記表の通り。それぞれに「①付与できるアクセス修飾子」「②インスタンス生成方法」を理解する必要がありそうだ。
名称 | 定義 |
---|---|
インナークラス | クラスの中で定義されたクラス |
staticインナークラス | クラスの中で定義されたstaticクラス |
ローカルクラス | クラスの中のメソッドの中で定義されたクラス |
匿名クラス | クラスの中のメソッドの中でサブクラスまたはインタフェースを実装したクラス |
ネストしたクラスをさらに区分するならば、クラスの中で定義されたクラスとして「インナークラス」と「staticインナークラス」、クラスの中のメソッドで定義されたクラスとして「ローカルクラス」と「匿名クラス」の2種類に分類できる。理解するにはこの辺りの違いを明確化(③それぞれのクラスの違い)する必要があるだろう。その辺りを意識しながらまとめていきたい。
4つのネストしたクラスを見ていこう
インナークラス
項目 | 内容 |
---|---|
付与できるアクセス修飾子 | 使用できる |
インスタンス生成方法 | エンクロージングクラス名. インナークラス名 変数名 = new エンクロージングクラス名(). new インナークラス名(); |
staticインナークラスとの違い | staticメンバを持つことができない 外側のクラスで定義したインスタンス変数、static変数にアクセスできる |
class outer { class inner { } // インナークラス } class test { public static void main(String[] args) { // インナークラスのインスタンス outer.inner testInner = new outer(). new inner(); } }
staticインナークラスとインナークラスの違いは、staticクラスと非staticクラスの違いと同じである。それについては、また別の記事でまとめたい(これについてはJava Silverで必須)。
staticインナークラス
項目 | 内容 |
---|---|
付与できるアクセス修飾子 | 使用できる |
インスタンス生成方法 | エンクロージングクラス名. staticインナークラス名 変数名 = new エンクロージングクラス名(). new staticインナークラス名(); |
staticインナークラスとの違い | staticメンバを持つことができない 外側のクラスで定義したインスタンス変数、static変数にアクセスできる |
class outer { static class staticInner { } // staticインナークラス } class test { public static void main(String[] args) { // インナークラスのインスタンス outer.staticInner testStaticInner = new outer(). new staticInner(); } }
staticの有無で大きく変わるのは、変数やメソッドの扱い方である。これについてはやはり文字数を割いて別個で切り出して覚えるべき内容であるように思う。
ローカルクラス
項目 | 内容 |
---|---|
付与できるアクセス修飾子 | abstract final |
インスタンス生成方法 | クラス名. ローカルクラス名 変数名 = new ローカルクラス名(); |
匿名クラスとの違い | メソッド内に定義する名前のあるクラス |
class outer { public static void method(){ class local {} // ローカルクラス } }
ローカルクラスと匿名クラスは、同じメソッド内で定義されたクラスではあるものの、その実体は全く異なるものである。強いて差分を挙げるならば、「クラス名の有無」であるが、この覚え方は混乱を招くように思う。というわけで「ローカルクラス」と「匿名クラス」それぞれで記事にまとめようと思う。
匿名クラス
項目 | 内容 |
---|---|
付与できるアクセス修飾子 | 使用できない |
インスタンス生成方法 | インタフェース名 変数名 = new インタフェース名(){メソッドの実装}; |
匿名クラスとの違い | メソッド内に定義する名前のないクラス |
interface inter { //インタフェース void test() } class outer { new inter(){ // 匿名クラス public void test(){ System.out.println("これは匿名クラスです"); } }.test(); }
インタフェースのメソッドの実装を、メソッドごとに変えたいという時に利用するのが匿名クラス。インタフェースにない新規メソッドを実装するような特殊ケースについては、絶対に問題として出ると思う(出しやすそう)。
まとめ
備忘録として次に勉強してまとめたい内容をまとめておく。
- staticクラスと非staticクラスの違い
- ローカルクラス
- 匿名クラス(特に特殊ケースについて!!!)