内部クラス
日本語 | 内部種類 |
英語 | inner class |
ふりがな | ないぶくらす |
フリガナ | ナイブクラス |
クラス内クラス。
「インナークラス」とも言う。
特定のクラス(外部クラス)内に存在するクラスを「内部クラス」という。
文法的には、外部クラスの定義内で定義されたクラスが、内部クラスとなる。
外部クラスの中からは自由に内部クラスを使用できる。外部クラスから、内部クラス型変数の宣言、インスタンスの作成、privateフィールド及びprivateメソッドへのアクセスが可能である。
また同様に、内部クラスは外部クラスを自由に使用できる。
内部クラスは、そのインスタンスを外部クラスのインスタンス内に持つ、という特殊なクラスである。
まず外部クラスのインスタンスを作り、次にそのインスタンスの参照経由で内部クラスのインスタンスを作ることで、外部クラスのインスタンスと結びついた内部クラスのインスタンスを作ることができる。
そうすることで、内部クラスは外部クラスのフィールド及びメソッドにアクセスできる。
つまり、外部クラスのインスタンス内に内部クラスが含まれているため、内部クラスは外部クラスにアクセスできる、ということである。
この時、内部クラスのインスタンスにとっての「外部クラスのインスタンス」を「エンクロージングインスタンス」と呼ぶ。
内部クラスは外部クラスのフィールド及びメソッドへとアクセスすることができる。内部クラスのインスタンスがあるということは、必ずそのインスタンスを含む外部クラスのインスタンスが存在するからである。
ただし、外部クラスのインスタンスから内部クラスのインスタンスは見えない。外部クラスのインスタンス内に内部クラスのインスタンスがいくつ作られているか知る術はなく、アクセスする方法も存在しない。
そのため、基本的には「あるインスタンスを複数のインスタンスが共有する」という場合に内部クラスを使用するのがいいだろう。
内部クラスについて解説している文の多くは、「あるクラスを特定のクラス内でのみ使用する」場合に内部クラスを使用する、とあるが、間違いである。
その目的で使用する場合には、内部クラスでかつprivateクラスとする必要がある。それであれば、目的を達成できる。
しかし、それは内部クラスの本来の目的ではない。内部クラスは「外部クラスのインスタンスの中」にインスタンスが作られる、ということにこそ本来の意味がある。
ローカルクラス、匿名クラスも内部クラスのひとつである。
「インナークラス」とも言う。
特定のクラス(外部クラス)内に存在するクラスを「内部クラス」という。
文法的には、外部クラスの定義内で定義されたクラスが、内部クラスとなる。
外部クラスの中からは自由に内部クラスを使用できる。外部クラスから、内部クラス型変数の宣言、インスタンスの作成、privateフィールド及びprivateメソッドへのアクセスが可能である。
また同様に、内部クラスは外部クラスを自由に使用できる。
内部クラスは、そのインスタンスを外部クラスのインスタンス内に持つ、という特殊なクラスである。
まず外部クラスのインスタンスを作り、次にそのインスタンスの参照経由で内部クラスのインスタンスを作ることで、外部クラスのインスタンスと結びついた内部クラスのインスタンスを作ることができる。
そうすることで、内部クラスは外部クラスのフィールド及びメソッドにアクセスできる。
つまり、外部クラスのインスタンス内に内部クラスが含まれているため、内部クラスは外部クラスにアクセスできる、ということである。
この時、内部クラスのインスタンスにとっての「外部クラスのインスタンス」を「エンクロージングインスタンス」と呼ぶ。
内部クラスは外部クラスのフィールド及びメソッドへとアクセスすることができる。内部クラスのインスタンスがあるということは、必ずそのインスタンスを含む外部クラスのインスタンスが存在するからである。
ただし、外部クラスのインスタンスから内部クラスのインスタンスは見えない。外部クラスのインスタンス内に内部クラスのインスタンスがいくつ作られているか知る術はなく、アクセスする方法も存在しない。
そのため、基本的には「あるインスタンスを複数のインスタンスが共有する」という場合に内部クラスを使用するのがいいだろう。
内部クラスについて解説している文の多くは、「あるクラスを特定のクラス内でのみ使用する」場合に内部クラスを使用する、とあるが、間違いである。
その目的で使用する場合には、内部クラスでかつprivateクラスとする必要がある。それであれば、目的を達成できる。
しかし、それは内部クラスの本来の目的ではない。内部クラスは「外部クラスのインスタンスの中」にインスタンスが作られる、ということにこそ本来の意味がある。
ローカルクラス、匿名クラスも内部クラスのひとつである。
参考サイト
- (参考サイトはありません)
// Sample.java
public class Sample
{
public static void main( String[] args )
{
// まず外部クラスのインスタンスを作ります。
OuterClass outerClass = new OuterClass();
// そのインスタンス経由で内部クラスを作ります。
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
// すると、内部クラス経由で外部クラスのフィールドにアクセスできます。
innerClass.outputOuter();
// 100
// また、外部クラスのメソッドなら内部クラスのprivateフィールドに
// アクセスできます。ただしその際、内部クラスの参照が必要です。
outerClass.outputInner( innerClass );
// 200
}
}
// 外部クラス。
class OuterClass
{
// privateフィールド。
private int outerValue = 100;
// 内部クラス。
public class InnerClass
{
// privateフィールド
private int innerValue = 200;
// メソッド。
public void outputOuter()
{
// ここから、外部クラスのフィールドにアクセスできます。
System.out.println( outerValue );
}
// 内部クラス内にstaticフィールドを作ることはできません。
// public static int data = 100;
// コンパイルエラー:
// フィールド data は static を宣言することはできません。; static フィールドは、static またはトップレベル型においてのみ宣言できます。
}
// 外部クラスのメソッドから内部クラスのprivateフィールドに
// アクセスできます。
public void outputInner( InnerClass innerClass )
{
// ここから、内部クラスのprivateフィールドにアクセスできます。
System.out.println( innerClass.innerValue );
// ただし、このようにして引数等で渡してもらう必要があります。
// なぜなら、外部クラスのインスタンスが作られても、内部クラスの
// インスタンスが作られるとは限りませんし、内部クラスのインスタンスが
// 複数作られる場合もあるからです。
// あくまで「インスタンスで結びついている」という点に注意してください。
}
// 内部クラスのインスタンスをstaticメソッド内で作ることはできません。
public static void staticMethod()
{
// 内部クラスのインスタンスをstaticメソッド内で
// 作ることはできません。
// new InnerClass();
// コンパイルエラー:
// 型 OuterClass のエンクロージング・インスタンスを持つ割り振りを明示的に指定する必要があります。(例 x.new A() で、x が OuterClass のインスタンス)
// Sample.main()の例を見れば分かるとおり、内部クラスは
// 外部クラスのインスタンスを元にインスタンスを作る必要が
// あります。そのため、このように内部クラス単独で
// インスタンスを作ることはできません。
}
// 内部クラスのインスタンスは、非staticメソッド内で作ることはできます。
public void notStaticMethod()
{
// 非staticメソッドなら、内部くらすのインスタンスを作ることができます。
InnerClass innerClass = new InnerClass();
// これは、外部クラスのインスタンス、つまりこのメソッドの
// thisが参照するインスタンスの中に、内部クラスのインスタンスが
// 作られることになります。
// つまり、これは以下と同じです。
InnerClass innerClass2 = this.new InnerClass();
// このように、内部クラスはあくまで「外部クラスのインスタンスの中」
// にインスタンスが作られる、というわけです。
}
}
public class Sample
{
public static void main( String[] args )
{
// まず外部クラスのインスタンスを作ります。
OuterClass outerClass = new OuterClass();
// そのインスタンス経由で内部クラスを作ります。
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
// すると、内部クラス経由で外部クラスのフィールドにアクセスできます。
innerClass.outputOuter();
// 100
// また、外部クラスのメソッドなら内部クラスのprivateフィールドに
// アクセスできます。ただしその際、内部クラスの参照が必要です。
outerClass.outputInner( innerClass );
// 200
}
}
// 外部クラス。
class OuterClass
{
// privateフィールド。
private int outerValue = 100;
// 内部クラス。
public class InnerClass
{
// privateフィールド
private int innerValue = 200;
// メソッド。
public void outputOuter()
{
// ここから、外部クラスのフィールドにアクセスできます。
System.out.println( outerValue );
}
// 内部クラス内にstaticフィールドを作ることはできません。
// public static int data = 100;
// コンパイルエラー:
// フィールド data は static を宣言することはできません。; static フィールドは、static またはトップレベル型においてのみ宣言できます。
}
// 外部クラスのメソッドから内部クラスのprivateフィールドに
// アクセスできます。
public void outputInner( InnerClass innerClass )
{
// ここから、内部クラスのprivateフィールドにアクセスできます。
System.out.println( innerClass.innerValue );
// ただし、このようにして引数等で渡してもらう必要があります。
// なぜなら、外部クラスのインスタンスが作られても、内部クラスの
// インスタンスが作られるとは限りませんし、内部クラスのインスタンスが
// 複数作られる場合もあるからです。
// あくまで「インスタンスで結びついている」という点に注意してください。
}
// 内部クラスのインスタンスをstaticメソッド内で作ることはできません。
public static void staticMethod()
{
// 内部クラスのインスタンスをstaticメソッド内で
// 作ることはできません。
// new InnerClass();
// コンパイルエラー:
// 型 OuterClass のエンクロージング・インスタンスを持つ割り振りを明示的に指定する必要があります。(例 x.new A() で、x が OuterClass のインスタンス)
// Sample.main()の例を見れば分かるとおり、内部クラスは
// 外部クラスのインスタンスを元にインスタンスを作る必要が
// あります。そのため、このように内部クラス単独で
// インスタンスを作ることはできません。
}
// 内部クラスのインスタンスは、非staticメソッド内で作ることはできます。
public void notStaticMethod()
{
// 非staticメソッドなら、内部くらすのインスタンスを作ることができます。
InnerClass innerClass = new InnerClass();
// これは、外部クラスのインスタンス、つまりこのメソッドの
// thisが参照するインスタンスの中に、内部クラスのインスタンスが
// 作られることになります。
// つまり、これは以下と同じです。
InnerClass innerClass2 = this.new InnerClass();
// このように、内部クラスはあくまで「外部クラスのインスタンスの中」
// にインスタンスが作られる、というわけです。
}
}
// Sample.java public class Sample { public static void main( String[] args ) { // まず外部クラスのインスタンスを作ります。 OuterClass outerClass = new OuterClass(); // そのインスタンス経由で内部クラスを作ります。 OuterClass.InnerClass innerClass = outerClass.new InnerClass(); // すると、内部クラス経由で外部クラスのフィールドにアクセスできます。 innerClass.outputOuter(); // 100 // また、外部クラスのメソッドなら内部クラスのprivateフィールドに // アクセスできます。ただしその際、内部クラスの参照が必要です。 outerClass.outputInner( innerClass ); // 200 } } // 外部クラス。 class OuterClass { // privateフィールド。 private int outerValue = 100; // 内部クラス。 public class InnerClass { // privateフィールド private int innerValue = 200; // メソッド。 public void outputOuter() { // ここから、外部クラスのフィールドにアクセスできます。 System.out.println( outerValue ); } // 内部クラス内にstaticフィールドを作ることはできません。 // public static int data = 100; // コンパイルエラー: // フィールド data は static を宣言することはできません。; static フィールドは、static またはトップレベル型においてのみ宣言できます。 } // 外部クラスのメソッドから内部クラスのprivateフィールドに // アクセスできます。 public void outputInner( InnerClass innerClass ) { // ここから、内部クラスのprivateフィールドにアクセスできます。 System.out.println( innerClass.innerValue ); // ただし、このようにして引数等で渡してもらう必要があります。 // なぜなら、外部クラスのインスタンスが作られても、内部クラスの // インスタンスが作られるとは限りませんし、内部クラスのインスタンスが // 複数作られる場合もあるからです。 // あくまで「インスタンスで結びついている」という点に注意してください。 } // 内部クラスのインスタンスをstaticメソッド内で作ることはできません。 public static void staticMethod() { // 内部クラスのインスタンスをstaticメソッド内で // 作ることはできません。 // new InnerClass(); // コンパイルエラー: // 型 OuterClass のエンクロージング・インスタンスを持つ割り振りを明示的に指定する必要があります。(例 x.new A() で、x が OuterClass のインスタンス) // Sample.main()の例を見れば分かるとおり、内部クラスは // 外部クラスのインスタンスを元にインスタンスを作る必要が // あります。そのため、このように内部クラス単独で // インスタンスを作ることはできません。 } // 内部クラスのインスタンスは、非staticメソッド内で作ることはできます。 public void notStaticMethod() { // 非staticメソッドなら、内部くらすのインスタンスを作ることができます。 InnerClass innerClass = new InnerClass(); // これは、外部クラスのインスタンス、つまりこのメソッドの // thisが参照するインスタンスの中に、内部クラスのインスタンスが // 作られることになります。 // つまり、これは以下と同じです。 InnerClass innerClass2 = this.new InnerClass(); // このように、内部クラスはあくまで「外部クラスのインスタンスの中」 // にインスタンスが作られる、というわけです。 } }