- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
!!!SJC-P クラス、インタフェース、列挙型を宣言
!!インナークラス
!「通常」のインナークラス
以下のようなクラスではない
+静的ネストクラス
+メソッドローカルなインナークラス
+無名インナークラス
*「通常」のインナークラスは、static宣言を持つことはできない(1)
*Outer クラスのメンバーを参照できる(2)
*Outer クラスの参照は クラス名.this で参照できる(3)
*Outer クラスのコード内からは、インナークラスを直接インスタンス化できる(4)
*Outer クラスのコード外から、インナークラスをインスタンス化するには、アウタークラスの参照が必要(5)
package innerclass;
/**
* 「通常」のインナークラス
* 以下のようなクラスではない
* ・静的ネストクラス
* ・メソッドローカルなインナークラス
* ・無名インナークラス
* @author Yagi Hiroto
*/
public class InnerClassTest1 {
private String outerName = "InnerClassTest1";
/**
* 「通常」のインナークラス
*/
class InnerClass {
// (1) 「通常」のインナークラスは、static宣言を持つことはできない
public /* static */ void printName() {
System.out.println("my name : InnerClass");
// (2) Outer クラスのメンバーを参照できる
System.out.println("outer name : " + outerName);
// (3) Outer クラスの参照は クラス名.this で参照できる
System.out.println("outer : " + InnerClassTest1.this);
}
}
/*
* Outer クラスのコード「内」から、インナークラスのインスタンスを生成する
*/
public void printInnerName() {
// (4) インナークラスを直接インスタンス化できる
InnerClass ic = new InnerClass();
ic.printName();
}
public static void main(String[] args) {
InnerClassTest1 me = new InnerClassTest1();
me.printInnerName();
InnerClassTest2 ic2 = new InnerClassTest2();
ic2.printOtherInnerName();
}
}
class InnerClassTest2 {
/*
* Outer クラスのコード「外」から、インナークラスのインスタンスを生成する
*/
public void printOtherInnerName() {
// (5) インナークラスのインスタンス化には、アウタークラスの参照が必要
InnerClassTest1.InnerClass ic
= new InnerClassTest1().new InnerClass();
ic.printName();
}
}
!メソッドローカルなインナークラス
*Outerクラスのメンバにアクセス可能(1)
*ローカル変数にはアクセスできない(2)
**インナークラスはヒープに置かれるため、メソッドから抜けるとスタックにアクセスできなくなる
*final なローカル変数にはアクセスできる(3)
*メソッドを抜けても生存している(4)
package innerclass;
public class InnerClassTest3 {
private int memberInt = 123;
private Object obj;
public void testMethodLocalInnerClass() {
int localInt = 456;
final int finalInt = 789;
class MethodInner {
void printInt() {
// (1) Outerクラスのメンバにアクセス可能
System.out.println("Member :" + memberInt);
// (2) ローカル変数にはアクセスできない
// インナークラスはヒープに置かれるため、メソッドから抜けるとスタックにアクセスできなくなる
// System.out.println("Local :" + localInt);
// (3) final なローカル変数にはアクセスできる
System.out.println("Final :" + finalInt);
}
public String toString() {
return "MethodInner";
}
}
MethodInner mi = new MethodInner();
mi.printInt();
obj = mi;
}
public static void main(String[] args) {
InnerClassTest3 me = new InnerClassTest3();
me.testMethodLocalInnerClass();
// (4) メソッドを抜けても生存している
System.out.println(me.obj.toString());
}
}
!無名インナークラス
*無名インナークラスとしてサブクラス化(1)
*スーパークラスのメソッドをオーバーライド(2)
*末尾はセミコロン(3)
package innerclass;
public class InnerClassTest4 {
public void testAnonymousInner() {
/*
* 無名インナークラス
* (1) 無名インナークラスとしてサブクラス化
*/
BaseClass bc = new BaseClass() {
// (2) スーパークラスのメソッドをオーバーライド
public String getName() {
return "AnonymousDerivClass";
}
}; // (3) 末尾はセミコロン
System.out.println(bc.getName());
}
public static void main(String[] args) {
(new InnerClassTest4()).testAnonymousInner();
}
}
class BaseClass {
public String getName() {
return "BaseClass";
}
}
!無名インナークラス(インターフェース実装クラス)
*無名インナークラスとしてインターフェースを実装(1)
*インターフェースのメソッドを実装(2)
*末尾はセミコロン(3)
package innerclass;
public class InnerClassTest5 {
public void testAnonymousInner() {
/*
* 無名インナークラス
* (1) 無名インナークラスとしてインターフェースを実装
*/
InfBase ib = new InfBase() {
// (2) インターフェースのメソッドを実装
public String getName() {
return "AnonymousDerivClass";
}
}; // (3) 末尾はセミコロン
System.out.println(ib.getName());
}
public static void main(String[] args) {
(new InnerClassTest5()).testAnonymousInner();
}
}
interface InfBase {
String getName();
}
!無名インナークラス(メソッド引数として使用)
*セミコロン不要(1)
*}); で終わる(2)
package innerclass;
public class InnerClassTest6 {
public void testParamAnonymousClass(InfBase2 base) {
System.out.println(base.getName());
}
public static void main(String[] args) {
InnerClassTest6 me = new InnerClassTest6();
me.testParamAnonymousClass(
/* メソッド引数として無名インナークラスを利用する */
new InfBase2() {
public String getName() {
return "Parameter AnonymousClass";
}
} // (1)セミコロン不要
); // (2) }); で終わる
}
}
interface InfBase2 {
String getName();
}