内部クラスとは
内部クラスとは、クラスの中に定義されたクラスのことを指します。
内部クラスを利用することで、クラス間の関係がわかりやすくなり、ソースコードがシンプルになり、可読性が増します。
また、使用場所を限定し、その存在を外部から隠したい場合にも使用します。
内部クラスの必要性
ここでMyObj クラスがMain以外のクラスからは使われないとします。
すると、少し不便なことが出てきます。
もし他にMyObjというクラスを作りたい場合、クラス名がすでに使われているため作成することが出来ません。
それは片方のMyObj.classによってもう片方のMyObj.classファイルが上書きされてしまうからです。
そのため、毎回名前を変えなければいけません。
これは不便なのでJDK1.1からは内部クラスというものが導入されました。
これは単純に、クラスの中にクラスを書くことができるというものです。
内部クラスは定義された場所によって、呼び出し方や動作が変わってきます。
ポイント!内部クラスの種類
ネストクラス
staticで定義されたクラスインナークラス
static以外で定義されたクラス
- メンバーインナークラス
クラスのメンバとして定義されたクラス- ローカルインナークラス
メソッド内で定義されたクラス- 無名インナークラス
ローカルインナークラスの中で名前をつけないもの
内部クラスの中でもstaticなものを「ネストクラス」、それ以外を「インナークラス」と呼びます。
ネストクラス
ネストクラスはstaticというキーワードをつけて定義したクラスです。
外側のクラスの1つ内側に記述します。
【ネストクラスの作成】
public class NestSample{ static class MyObj{ public void foo( ){ System.out.println("ネストクラスの機能が呼び出されました!"); } } public static void main(String[ ] args){ MyObj obj = new MyObj( ); obj.foo( ); } }
実行結果
ネストクラスの機能が呼び出されました!
NestSampleクラスの内部でMyObjクラスが定義されておりNestSampleクラスから、MyObjクラスをインスタンス化してMyObjクラスのfoo()メソッドを呼び出しています。
staticとは
前までの記事で見てきたHumanクラスはstaticキーワードがついていないクラスです。
Humanクラスに所属するフィールドやメソッドを利用するには、mainメソッドからHumanクラスのインスタンスを作成し、そのインスタンスからアクセスしました。
一方、staticキーワードがついたクラス、フィールド、メソッドはインスタンス内ではなく、クラスに1つだけ存在しますので、これらにアクセスするには、「クラス名.メソッド名」 「クラス名.フィールド名」と記述をします。
外部クラスからstaticなネストクラスを利用するには、左辺に宣言の型として
外側クラス名.ネストクラス名
と記述します。
ネストクラスのメンバにアクセスするには、ネストクラスのインスタンスを作成し、そのインスタンスからフィールドやメソッドといったメンバを呼び出します。
new 外側クラス名.ネストクラス名 ネストクラスのインスタンス名.ネストクラスのフィールド名(メソッド名)
【ネストクラスの利用】
class Outer{ static void foo(){ System.out.println("Outerクラスのfoo()が呼び出されました"); } static class Nest{ Nest(){ System.out.println("Nestクラスがインスタンス化されました"); } } } public class NestSample2{ public static void main(String[ ] args){ Outer.foo(); Outer.Nest nest = new Outer.Nest(); } }
実行結果
Outerクラスのfoo()が呼び出されました Nestクラスがインスタンス化されました
NestSample2.javaファイル内にmainメソッドのある「NestSample2」クラス、staticなネストクラス「Nest」を内部クラスとして持つ「Outer」クラスが定義されています。
main()メソッドの14行目でOuterクラスのfoo()メソッドを呼び出しています。
foo()メソッドはstaticキーワードがついているため、インスタンスを生成する必要はなく、「クラス名.メソッド名」で呼び出します。
したがってOuter.foo()
と呼び出すことができます。
次に15行目では、Outerクラス内に定義されている「Nest」クラスを利用しています。
左辺の宣言の型では、Nestクラスがstaticであるため、「外側のクラス名.内側のクラス名」と指定するため、Outer.Nestと記述します。
staticなインナークラスは静的メンバであるためアウタークラスのインスタンスがなくてもアクセスができます。
したがって右辺ではOuterクラスはインスタンス化せず、Nestクラスのみをインスタンス化するため、new Outer.Nest()
と指定をしています。
これによりNestクラスがインスタンス化され、6行目のコンストラクタが呼び出されることになります。
「メンバーインナークラス」「ローカルインナークラス」「無名インナークラス」については、次回の記事で解説します!
「内部クラス Part2」へ続きます
参考図書
独学で挫折しそうになったら、オンラインプログラミングスクール