Posted on 2008-08-01 11:25
夢與橋 閱讀(240)
評論(0) 編輯 收藏 所屬分類:
java基礎
1、內部類的優點:
優點一:在需要的地方定義類,可以直接使用外部類里的變量,代碼比較簡潔。
優點二:可以實現多繼承。
優點三:解決命名空間的一種途徑。
優點四:實現callback。
優點五:控制類的可見問題。
2、描述:內部類(Inner class)也叫嵌套類(Nested class),允許一個類的定義被放到另外一個類的定義中,這樣的一組類在邏輯上是一個整體。內部類和其外層類存在邏輯上的從屬關系,內部類對其外層類的成員有完全的訪問權限。
3、分類:靜態內部類(Static Inner Class)、成員內部類(Member Inner Class)、局部內部類(Local Inner Class)、匿名內部類(Anonymous Inner Class)
成員內部類實例:
class OuterClass
{
private String str1="同名變量之外部類。";
private String str2="外部類變量。";
public static void method1()
{
//OuterClass.InnerClass ic=new OuterClass().new InnerClass();//方式一
OuterClass oc=new OuterClass();//方式二
OuterClass.InnerClass ic=oc.new InnerClass();
System.out.println("外部類靜態方法調用"+ic.str3);
}
public void method2()
{
InnerClass ic=new InnerClass();
System.out.println("外部類非靜態方法調用"+ic.str3);
}
public class InnerClass
{
private String str1="同名變量之內部類。";
public String str3="內部類成員變量。";
public void print()
{
String str1="同名變量之局部。";
System.out.println("內部類調用外部類變量"+str2);
System.out.println(str1);
System.out.println(this.str1);
System.out.println(OuterClass.this.str1);//若str1為靜態,此處可省this,其實這不此處要討論的問題
}
}
}
public class Test
{
public static void main(String[] args)
{
OuterClass.method1();
OuterClass oc=new OuterClass();
oc.method2();
OuterClass.InnerClass ic=new OuterClass().new InnerClass();
System.out.println("天涯之類調用"+ic.str3);
ic.print();
}
}
運行結果: 
注意:
所有內部類名稱不可與其外層類名稱相同,內部類不可定義靜態方法
內部類的完整名稱:外部類.內部類
內部類.class文件名稱:外部內$內部類.class
其外層類的非靜態方法使用內部類,同使用普通類完全一樣
在其外層類的非靜態方法之外的任何地方定義生成內部類的一個對象,必用使用內部類的完整名稱,語法格式:外部類對象.new內部類名稱(參數)
成員內部類可以使用任意的訪問修飾符:public、protected、default、private
內部類中引用外部類成員,格式:外部類名.this.成員名稱
靜態內部類實例:
class OuterClass
{
private static String str1="外部類靜態變量。";
private String str2="外部類非靜態變量。";
public void method1()
{
System.out.println("內部類引用"+InnerClass.str3);
InnerClass ic=new InnerClass();
System.out.println("內部類引用"+ic.str4);
}
public static void method2()
{
System.out.println("內部類引用"+InnerClass.str3);
InnerClass ic=new InnerClass();
System.out.println("內部類引用"+ic.str4);
}
public static class InnerClass
{
private static String str3="內部類靜態變量。";
private String str4="內部類非靜態變量。";
public void print()
{
System.out.println("內部類引用其外部類靜態方法:");
OuterClass.method2();
System.out.println("內部類引用其外部類靜態方法:\n"+OuterClass.str1);
}
}
}
public class Test
{
public static void main(String[] args)
{
OuterClass oc=new OuterClass();
OuterClass.InnerClass ic=new OuterClass.InnerClass();
ic.print();
oc.method1();
}
}
運行結果:
注意:
內部類可以直接引用外部類中定義的靜態成員,但不可以引用外部實例成員
static不妨礙創建靜態/非靜態的成員及方法
局部內部類實例:
class OuterClass
{
private String str1="外部類變量";
public void method()
{
final String str3="final類型的局部變量。";
class InnerClass
{
public void print()
{
System.out.println(str1);
System.out.println(str3);
}
}
InnerClass ic=new InnerClass();
ic.print();
}
}
public class Test
{
public static void main(String[] args)
{
OuterClass oc=new OuterClass();
oc.method();
}
}
運行結果:
注意:
局部內部類在局部塊中可見,超過作用域將不可見,只可用abstract 或final修飾符
可以訪問其外部類的字段和局部變量(要被聲明為final,不被訪問的不用聲明)
在靜態代碼塊(如靜態方法與靜態初始化塊)中定義時,將只能引用靜態變量
匿名內部類實例:
interface Interest
{
void letter();
void computer();
}
class Student
{
public void school()
{
System.out.println("吉林農業大學發展學院");
}
public void specialty()
{
System.out.println("計算機科學與技術");
}
public void intersets(Interest interest )
{
interest.letter();
interest.computer();
}
}
public class Test
{
public static void main(String[] args)
{
Student stu=new Student();
stu.school();
stu.specialty();
stu.intersets(new Interest(){
public void letter()
{
System.out.println("My first interest is letter.");
}
public void computer()
{
System.out.println("My second interest is computer");
}
});
}
}
運行結果:
注意:
不能用任何修飾符,無構造函數,匿名成員的初始化只能通過非靜態初始化塊進行
實例中的匿名類是作為方法形參類形的接口實現類,也可作為形參類型的派生類(這樣就實現了類的多繼承)
定義對象時不能帶有參數
附一本教材上的匿名類實例:
class a
{
void ShowA()
{
System.out.println("我是a類的方法.");
}
}
class b
{
a One=new a(){
void ShowA()
{
System.out.println("我是匿名內部類(類A的子類)的方法.");
}
};
void ShowB()
{
One.ShowA();
}
}
public class Test
{
public static void main(String args[])
{
b Two=new b();
Two.ShowB();
}
}
運行結果:打印出:我是匿名內部類(類A的子類)的方法.
4、接口中的嵌套類:當一個類的對象與接口有很強的邏輯關聯時,可將此類定義為對應接口的嵌套類
例如:
interface Ia
{
int var1=0;
class NestedClass
{
public void display()
{
System.out.println(var1);
}
}
}
public class Test
{
public static void main(String args[])
{
Ia.NestedClass inc=new Ia.NestedClass();
inc.display();
}
}
一個接口定義的嵌套類只能是public和static的,默認情況下也是,接口的實現類與接口的嵌套類無多大聯系,前者在實現接口時無需關心后者,當然可能用到后者。
5、總結:
內部類的嵌套可以多層,目的是使代碼簡潔,下面舉一個外部類要返回一個對象的例子:
interface Ia
{
void show1();
}
class OuterClass
{
public Ia method()
{
class InnterClass implements Ia
{
public void show1()
{
System.out.println("Hello");
}
}
return new InnterClass();
}
public void show2()
{
Ia iu=method();
iu.show1();
}
}
public class Test
{
public static void main(String args[])
{
final String str="world!";
OuterClass oc=new OuterClass();
oc.show2();
}
}
這是在一個方法中,也可以一個語句塊中,比如說在if內。當想需要創建一個對象,而又用不上他的名字時,可以創建匿名類對象,他的語法:new interfacename(){......}; 或 new superclassname(){......}; 這在JAVA事件處理中大量使用,例如:
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
如果這個匿名內部類繼承了一個只含有帶參數構造函數的父類,創建它的時候必須帶上這些參數,并在實現的過程中使用super關鍵字調用相應的內容。