source:http://www.cnblogs.com/sgsoft/archive/2004/09/11/42148.html
關(guān)于JAVA匿名內(nèi)部類的一點(diǎn)討論.
基本理論:
-----------------------------------------------------
關(guān)于JAVA內(nèi)部類:一個(gè)內(nèi)部類的定義是定義在另一個(gè)類內(nèi)部的類。
存在它的原因是:
1.一個(gè)內(nèi)部類的對(duì)象能夠訪問創(chuàng)建它的對(duì)象的實(shí)現(xiàn),包括私有數(shù)據(jù)。即內(nèi)部類實(shí)例對(duì)包含它的哪個(gè)類的實(shí)例來說,是特權(quán)的。
2.對(duì)于同一個(gè)包中的其他類來說,內(nèi)部類能夠隱藏起來,換句話說,內(nèi)部類不管方法的可見性如何,那怕是public,除了包容類,其他類都無法使用它。
3.匿名內(nèi)部類可以很方便的定義回調(diào)。
4.使用內(nèi)部類可以非常方便的編寫事件驅(qū)動(dòng)程序。
其實(shí)它真正的目的僅僅為了定義回調(diào)--進(jìn)一步就是事件驅(qū)動(dòng)。
接口和回調(diào):編程一個(gè)常用的模式是回調(diào)模式,在這種模式中你可以指定當(dāng)一個(gè)特定時(shí)間發(fā)生時(shí)回調(diào)對(duì)象上的方法。
--------------------------------------------------
?注意事項(xiàng):
?
?匿名類和內(nèi)部類中的中的this :
?有時(shí)候,我們會(huì)用到一些內(nèi)部類和匿名類。當(dāng)在匿名類中用this時(shí),這個(gè)this則指的是匿名類或內(nèi)部類本身。
?這時(shí)如果我們要使用外部類的方法和變量的話,則應(yīng)該加上外部類的類名。如下面這個(gè)例子:
?
public?class?A?{
??
int
?i?
=
?
1
;

??public?A()?{
????Thread?thread?
=
?
new
?Thread()?{
??????public?
void
?run()?{
????????
for
(;;)?{
??????????A.
this
.run();
??????????
try
?{
????????????sleep(
1000
);
??????????}?
catch
(InterruptedException?ie)?{
??????????}
????????}
??????}
????};
????thread.start();
??}??

??public?
void
?run()?{
????System.out.println(
"
i?=?
"
?
+
?i);
????i
++
;
??}

??public?static?
void
?main(String[]?args)?throws?Exception?{
????
new
?A();
??}

}

?
??? 在上面這個(gè)例子中, thread 是一個(gè)匿名類對(duì)象,在它的定義中,它的 run 函數(shù)里用到了外部類的 run 函數(shù)。
??? 這時(shí)由于函數(shù)同名,直接調(diào)用就不行了。這時(shí)有兩種辦法,一種就是把外部的 run 函數(shù)換一個(gè)名字,但這種辦法對(duì)于一個(gè)開發(fā)到中途的應(yīng)用來說是不可取的
??? 。那么就可以用這個(gè)例子中的辦法用外部類的類名加上 this 引用來說明要調(diào)用的是外部類的方法 run。
??? --------------------------------------------------
???
???
??? 對(duì)于這個(gè)例子:
this
.test(
new
?Inner(){
?????????????public?
void
?method1(){
?????????????????System.out.print(
"
1111
"
);
???????????}
????????????
?????????????public?
void
?method2(){
?????????????????System.out.print(
"
22222
"
);
???????????}
});
這個(gè)時(shí)候調(diào)用test()方法,那Inner類的method1和method2是什么時(shí)候被調(diào)用的?難道也是this對(duì)象向他們發(fā)消息(比如傳入一個(gè)參數(shù))嗎?還是直接顯式的調(diào)用??
?
對(duì)于Inner類,除了this這個(gè)類,就是this.test(...那句中的this,它能夠調(diào)用Inner類的方法,其他地方都不行,然而,這也需要你在類中有個(gè)地方保存有對(duì)這個(gè)內(nèi)部類實(shí)例的引用才可以。再說明一次,內(nèi)部類是用來在某個(gè)時(shí)刻調(diào)用外面的方法而存在的--這就是回調(diào)。
為了說明內(nèi)部類實(shí)例的方法只能在包容類的實(shí)例中調(diào)用,其他地方無法調(diào)用,給個(gè)例子如下:
JAVA2實(shí)用教程源碼:
?
?
/*
*?一個(gè)應(yīng)用程序,用來演示內(nèi)部類的使用?
*/
/*
*?類Outer?
*/
class?Outer{?
private?static?
int
?size;

/*
*?內(nèi)部類Inner的聲明?
*/
public?class?Inner{?
private?
int
?size;

/*
*?方法doStuff()?
*/
public?
void
?doStuff(
int
?size){?
size
++
;?
//
存取局部變量
this
.size
++
;??
//
存取其內(nèi)部類的成員變量
Outer.
this
.size
++
;?
//
存取其外部類的成員變量
System.out.println(size
+
"
?
"
+
this
.size
+
"
?
"
+
Outer.
this
.size);
}
}
//
內(nèi)部類Inner結(jié)束
/*
*?類Outer中定義的實(shí)例方法testInner()方法?
*/
public?
void
?testInner(){
Inner?i
=
new
?Inner();
i.doStuff(
5
);?
}?

/*
*?main()方法?
*/
public?static?
void
?main(String[]?a){?
Outer?o
=
new
?Outer();
o.testInner();
}
}
//
類Outer結(jié)束
?
------------------------------------------------
那么,如何使用內(nèi)部類,匿名類實(shí)現(xiàn)事件處理呢?
JAVA---事件適配器
?1.事件適配器--EventAdapter
下例中采用了鼠標(biāo)適配器:
import?java.awt.
*
;
import?java.awt.event.
*
;
public?class?MouseClickHandler?extends?MouseAdaper{
public?
void
?mouseClicked(MouseEvent?e)?
//
只實(shí)現(xiàn)需要的方法
{?……}
}?
?
java.awt.event包中定義的事件適配器類包括以下幾個(gè):
1.ComponentAdapter( 組件適配器)
2.ContainerAdapter( 容器適配器)
3.FocusAdapter( 焦點(diǎn)適配器)
4.KeyAdapter( 鍵盤適配器)
5.MouseAdapter( 鼠標(biāo)適配器)
6.MouseMotionAdapter( 鼠標(biāo)運(yùn)動(dòng)適配器)
7.WindowAdapter( 窗口適配器)
2. 用內(nèi)部類實(shí)現(xiàn)事件處理
內(nèi)部類(inner class)是被定義于另一個(gè)類中的類,使用內(nèi)部類的主要原因是由于:
◇ 一個(gè)內(nèi)部類的對(duì)象可訪問外部類的成員方法和變量,包括私有的成員。
◇ 實(shí)現(xiàn)事件監(jiān)聽器時(shí),采用內(nèi)部類、匿名類編程非常容易實(shí)現(xiàn)其功能。
◇ 編寫事件驅(qū)動(dòng)程序,內(nèi)部類很方便。
因此內(nèi)部類所能夠應(yīng)用的地方往往是在AWT的事件處理機(jī)制中。
例5.11
import?java.awt.
*
?;
import?java.awt.event.
*
;
public?class?InnerClass{
private?Frame?f;
private?TextField?tf;
public?InnerClass(){
f
=
new
?Frame(
"
Inner?classes?example
"
);
tf
=
new
?TextField(
30
);
}

public?voidi?launchFrame(){
Label?label
=
new
?Label(
"
Click?and?drag?the?mouse
"
);
f.add(label,BorderLayout.NORTH);
f.add(tf,BorderLayout.SOUTH);
f.addMouseMotionListener(
new
?MyMouseMotionListener());
/*
參數(shù)為內(nèi)部類對(duì)象
*/
f.setSize(
300
,
200
);
f.setVisible(
true
);?
}

class?MyMouseMotionListener?extends?MouseMotionAdapter{?
/*
內(nèi)部類開始
*/
public?
void
?mouseDragged(MouseEvent?e)?{
String?s
=
"
Mouse?dragging:?x=
"
+
e.getX()
+
"
Y=
"
+
e.getY();
tf.setText(s);?}
}?;

public?static?
void
?main(String?args[])?{
InnerClass?obj
=
new
?InnerClass();
obj.launchFrame();
}
}
//
內(nèi)部類結(jié)束
}

?
3.匿名類(Anonymous Class)
當(dāng)一個(gè)內(nèi)部類的類聲名只是在創(chuàng)建此類對(duì)象時(shí)用了一次,而且要產(chǎn)生的新類需繼承于一個(gè)已有的父類或?qū)崿F(xiàn)一個(gè)接口,才能考慮用匿名類,由于匿名類本身無名,因此它也就不存在構(gòu)造方法,它需要顯示地調(diào)用一個(gè)無參的父
類的構(gòu)造方法,并且重寫父類的方法。所謂的匿名就是該類連名字都沒有,只是顯示地調(diào)用一個(gè)無參的父類的構(gòu)造方法。
例5.12
import?java.awt.
*
?;
import?java.awt.event.
*
;
public?class?AnonymousClass{
private?Frame?f;
private?TextField?tf;
public?AnonymousClass(){
f
=
new
?Frame(
"
Inner?classes?example
"
);
tf
=
new
?TextField(
30
);
}
public?
void
?launchFrame(){
Label?label
=
new
?Label(
"
Click?and?drag?the?mouse
"
);
f.add(label,BorderLayout.NORTH);
f.add(tf,BorderLayout.SOUTH);
f.addMouseMotionListener(
new
?MouseMotionAdapter(){?
//
匿名類開始
public?
void
?mouseDragged(MouseEvent?e){
String?s
=
"
Mouse?dragging:?x=
"
+
e.getX()
+
"
Y=
"
+
e.getY();
tf.setText(s);?}
}?);?
//
匿名類結(jié)束?
f.setSize(
300
,
200
);
f.setVisible(
true
);
}
public?static?
void
?main(String?args[])?{
AnonymousClass?obj
=
new
?AnonymousClass();
obj.launchFrame();
}
}
?
其實(shí)仔細(xì)分析,例5.11和5.12實(shí)現(xiàn)的都是完全一樣的功能,只不過采取的方式不同。5.11中的事件處理類是一個(gè)內(nèi)部類,而5.12的事件處理類是匿名類,可以說從類的關(guān)系來說是越來越不清楚,但
是程序也越來越簡(jiǎn)練。熟悉這兩種方式也十分有助于編寫圖形界面的程序。
親自在IDE中實(shí)踐一下,會(huì)理解的更深切一點(diǎn)