1、內(nèi)部類的優(yōu)點(diǎn):
優(yōu)點(diǎn)一:在需要的地方定義類,可以直接使用外部類里的變量,代碼比較簡(jiǎn)潔。
優(yōu)點(diǎn)二:可以實(shí)現(xiàn)多繼承。
優(yōu)點(diǎn)三:解決命名空間的一種途徑。
優(yōu)點(diǎn)四:實(shí)現(xiàn)callback。
優(yōu)點(diǎn)五:控制類的可見問題。
2、描述:內(nèi)部類(Inner class)也叫嵌套類(Nested class),允許一個(gè)類的定義被放到另外一個(gè)類的定義中,這樣的一組類在邏輯上是一個(gè)整體。內(nèi)部類和其外層類存在邏輯上的從屬關(guān)系,內(nèi)部類對(duì)其外層類的成員有完全的訪問權(quán)限。
3、分類:靜態(tài)內(nèi)部類(Static Inner Class)、成員內(nèi)部類(Member Inner Class)、局部?jī)?nèi)部類(Local Inner Class)、匿名內(nèi)部類(Anonymous Inner Class)
成員內(nèi)部類實(shí)例:
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("外部類靜態(tài)方法調(diào)用"+ic.str3);
}
public void method2()
{
InnerClass ic=new InnerClass();
System.out.println("外部類非靜態(tài)方法調(diào)用"+ic.str3);
}
public class InnerClass
{
private String str1="同名變量之內(nèi)部類。";
public String str3="內(nèi)部類成員變量。";
public void print()
{
String str1="同名變量之局部。";
System.out.println("內(nèi)部類調(diào)用外部類變量"+str2);
System.out.println(str1);
System.out.println(this.str1);
System.out.println(OuterClass.this.str1);//若str1為靜態(tài),此處可省this,其實(shí)這不此處要討論的問題
}
}
}
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("天涯之類調(diào)用"+ic.str3);
ic.print();
}
}
運(yùn)行結(jié)果: 
注意:
所有內(nèi)部類名稱不可與其外層類名稱相同,內(nèi)部類不可定義靜態(tài)方法
內(nèi)部類的完整名稱:外部類.內(nèi)部類
內(nèi)部類.class文件名稱:外部?jī)?nèi)$內(nèi)部類.class
其外層類的非靜態(tài)方法使用內(nèi)部類,同使用普通類完全一樣
在其外層類的非靜態(tài)方法之外的任何地方定義生成內(nèi)部類的一個(gè)對(duì)象,必用使用內(nèi)部類的完整名稱,語法格式:外部類對(duì)象.new內(nèi)部類名稱(參數(shù))
成員內(nèi)部類可以使用任意的訪問修飾符:public、protected、default、private
內(nèi)部類中引用外部類成員,格式:外部類名.this.成員名稱
靜態(tài)內(nèi)部類實(shí)例:
class OuterClass
{
private static String str1="外部類靜態(tài)變量。";
private String str2="外部類非靜態(tài)變量。";
public void method1()
{
System.out.println("內(nèi)部類引用"+InnerClass.str3);
InnerClass ic=new InnerClass();
System.out.println("內(nèi)部類引用"+ic.str4);
}
public static void method2()
{
System.out.println("內(nèi)部類引用"+InnerClass.str3);
InnerClass ic=new InnerClass();
System.out.println("內(nèi)部類引用"+ic.str4);
}
public static class InnerClass
{
private static String str3="內(nèi)部類靜態(tài)變量。";
private String str4="內(nèi)部類非靜態(tài)變量。";
public void print()
{
System.out.println("內(nèi)部類引用其外部類靜態(tài)方法:");
OuterClass.method2();
System.out.println("內(nèi)部類引用其外部類靜態(tài)方法:\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();
}
}
運(yùn)行結(jié)果:
注意:
內(nèi)部類可以直接引用外部類中定義的靜態(tài)成員,但不可以引用外部實(shí)例成員
static不妨礙創(chuàng)建靜態(tài)/非靜態(tài)的成員及方法
局部?jī)?nèi)部類實(shí)例:
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();
}
}
運(yùn)行結(jié)果:
注意:
局部?jī)?nèi)部類在局部塊中可見,超過作用域?qū)⒉豢梢姡豢捎胊bstract 或final修飾符
可以訪問其外部類的字段和局部變量(要被聲明為final,不被訪問的不用聲明)
在靜態(tài)代碼塊(如靜態(tài)方法與靜態(tài)初始化塊)中定義時(shí),將只能引用靜態(tài)變量
匿名內(nèi)部類實(shí)例:
interface Interest
{
void letter();
void computer();
}
class Student
{
public void school()
{
System.out.println("吉林農(nóng)業(yè)大學(xué)發(fā)展學(xué)院");
}
public void specialty()
{
System.out.println("計(jì)算機(jī)科學(xué)與技術(shù)");
}
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");
}
});
}
}
運(yùn)行結(jié)果:
注意:
不能用任何修飾符,無構(gòu)造函數(shù),匿名成員的初始化只能通過非靜態(tài)初始化塊進(jìn)行
實(shí)例中的匿名類是作為方法形參類形的接口實(shí)現(xiàn)類,也可作為形參類型的派生類(這樣就實(shí)現(xiàn)了類的多繼承)
定義對(duì)象時(shí)不能帶有參數(shù)
附一本教材上的匿名類實(shí)例:
class a
{
void ShowA()
{
System.out.println("我是a類的方法.");
}
}
class b
{
a One=new a(){
void ShowA()
{
System.out.println("我是匿名內(nèi)部類(類A的子類)的方法.");
}
};
void ShowB()
{
One.ShowA();
}
}
public class Test
{
public static void main(String args[])
{
b Two=new b();
Two.ShowB();
}
}
運(yùn)行結(jié)果:打印出:我是匿名內(nèi)部類(類A的子類)的方法.
4、接口中的嵌套類:當(dāng)一個(gè)類的對(duì)象與接口有很強(qiáng)的邏輯關(guān)聯(lián)時(shí),可將此類定義為對(duì)應(yīng)接口的嵌套類
例如:
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();
}
}
一個(gè)接口定義的嵌套類只能是public和static的,默認(rèn)情況下也是,接口的實(shí)現(xiàn)類與接口的嵌套類無多大聯(lián)系,前者在實(shí)現(xiàn)接口時(shí)無需關(guān)心后者,當(dāng)然可能用到后者。
5、總結(jié):
內(nèi)部類的嵌套可以多層,目的是使代碼簡(jiǎn)潔,下面舉一個(gè)外部類要返回一個(gè)對(duì)象的例子:
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();
}
}
這是在一個(gè)方法中,也可以一個(gè)語句塊中,比如說在if內(nèi)。當(dāng)想需要?jiǎng)?chuàng)建一個(gè)對(duì)象,而又用不上他的名字時(shí),可以創(chuàng)建匿名類對(duì)象,他的語法:new interfacename(){......}; 或 new superclassname(){......}; 這在JAVA事件處理中大量使用,例如:
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
如果這個(gè)匿名內(nèi)部類繼承了一個(gè)只含有帶參數(shù)構(gòu)造函數(shù)的父類,創(chuàng)建它的時(shí)候必須帶上這些參數(shù),并在實(shí)現(xiàn)的過程中使用super關(guān)鍵字調(diào)用相應(yīng)的內(nèi)容。