桔子園
歡迎大家訪問我的個人網站
萌萌的IT人
BlogJava
首頁
新隨筆
聯系
聚合
管理
隨筆-128 評論-55 文章-5 trackbacks-0
[轉]內部類詳解
內部類詳解
1、定義
? 一個類的定義放在另一個類的內部,這個類就叫做內部類。
Java代碼
public
?
class
?First?{ ??
public
?
class
?Contents{ ??
????
public
?
void
?f(){ ??
????System.out.println(
"In?Class?First's?inner?Class?Contents?method?f()"
); ??
????} ??
} ??
?}??
?
像這樣的,Contents就叫做內部類
內部類了解外圍類,并能與之通信(后面詳細講)
2、鏈接到外圍類
? 創建了內部類對象時,它會與創造它的外圍對象有了某種聯系,于是能訪問外圍類的所有成員,不需任何特殊條件。?
?
Java代碼
???
public
?
class
?First?{ ??
public
?
class
?Contents{ ??
?????????
public
?
void
?getStr(){ ??
????????System.out.println(
"First.str="
+str); ??
?????} ??
} ??
private
?String?str; ??
????} ??
???
? 在內部類Contents中,可以使用外圍類First的字段str。
? 那么,它是如何實現的呢?
? 是這樣的,用外圍類創建內部類對象時,此內部類對象會秘密的捕獲一個指向外圍類的引用,于是,可以通過這個引用來訪問外圍類的成員。
? 通常,這些都是編譯器來處理,我們看不到,也不用關心這個。
? 正是因為如此,我們創建內部類對象時,必須與外圍類對象相關聯。
? 注:嵌套類(后面會講到)除外。
3、使用關鍵字.this與.new
? 內部類中得到當前外圍類對象的引用,可以使用.this關鍵字,注意與new的區別
?
Java代碼
????
private
?
int
?num?; ??
public
?Test2(){ ??
???? ??
} ??
??
public
?Test2(
int
?num){ ??
????
this
.num?=?num; ??
} ??
??
private
?
class
?Inner{ ??
????
public
?Test2?getTest2(){ ??
????????
return
?Test2.
this
; ??
????} ??
???? ??
????
public
?Test2?newTest2(){ ??
????????
return
?
new
?Test2(); ??
????} ??
} ??
??
public
?
static
?
void
?main(String?[]?args){ ??
????Test2?test?=?
new
?Test2(
5
); ??
????Test2.Inner?inner?=?test.
new
?Inner(); ??
????Test2?test2?=?inner.getTest2(); ??
????Test2?test3?=?inner.newTest2(); ??
????System.out.println(test2.num); ??
????System.out.println(test3.num); ??
} ??
???
? 輸出結果為5 0
? 使用.this后,得到時創建該內部類時使用的外圍類對象的引用,new則是創建了一個新的引用。
? .new關鍵字
? 如果想直接創建一個內部類對象,而不是通過外圍類對象的方法來得到,可以使用.new關鍵字
? 形式是這樣的:
?
Java代碼
OutClass.InnerClass?obj?=?outClassInstance.
new
?InnerClass(); ??
? 必須是外圍類對象.new,而不能是外圍類.new
?
Java代碼
???
public
?
class
?First?{ ??
public
?
class
?Contents{ ??
????
public
?
void
?f(){ ??
????????System.out.println(
"In?Class?First's?inner?Class?Contents?method?f()"
); ??
????} ??
????
public
?
void
?getStr(){ ??
????????System.out.println(
"First.str="
+str); ??
????} ??
} ??
??
public
?
static
?
void
?main(String?[]?args){ ??
????First?first?=?
new
?First(); ??
????First.Contents?contents?=?first.
new
?Contents(); ??
????contents.f(); ??
} ??
????} ??
???
? 必須通過外圍類First的對象first來創建一個內部類的對象
? 而且需要注意的是,在創建外圍類對象之前,不可能創建內部類的對象(嵌套類除外)。
4、內部類與向上轉型
? 將內部類向上轉型為基類型,尤其是接口時,內部類就有了用武之地。?
?
Java代碼
????
public
?
interface
?Shape?{ ??
public
?
void
?paint(); ??
????} ??
????
public
?
class
?Painter?{ ??
???? ??
???????
private
?
class
?InnerShape?
implements
?Shape{ ??
????
public
?
void
?paint(){ ??
????????System.out.println(
"painter?paint()?method"
); ??
????} ??
} ??
??
public
?Shape?getShape(){ ??
????
return
?
new
?InnerShape(); ??
}??? ??
???? ??
???????
public
?
static
?
void
?main(String?[]args){ ??
????Painter?painter?=?
new
?Painter(); ??
????Shape?shape?=?painter.?getShape(); ??
????shape.paint(); ??
} ??
????} ??
???
? 此時,內部類是private的,可以它的外圍類Painter以外,沒人能訪問。
? 這樣,private內部類給累的設計者提供了一種途徑,通過這種方式可以完全阻止任何依賴于類型的編碼,并完全隱藏實現的細節。
5、方法內的類
? 可以在方法內創建一個類。
?
Java代碼
public
?
void
?test(){ ??
ass?Inner{ ??
?
public
?
void
?method(){ ??
ystem.out.println(
"在方法內創建的類"
); ??
?} ??
??
} ??
? 值得注意的是:方法內創建的類,不能加訪問修飾符。
? 另外,方法內部的類也不是在調用方法時才會創建的,它們一樣也被編譯了(怎么知道的?后面會有講解)。
6、匿名內部類?
?
Java代碼
??
public
?
class
?Painter?{ ??
ublic?Shape?getShape(){ ??
return
?
new
?Shape(){ ??
????
public
?
void
?paint(){ ??
????????System.out.println(
"painter?paint()?method"
); ??
????} ??
}; ??
??
??????
public
?
static
?
void
?main(String?[]?args){ ??
????????????Painter?painter?=?
new
?Painter(); ??
????????????Shape?shape?=?painter.getShape(); ??
????????????shape.paint(); ??
??????} ??
??} ??
??
public
?
interface
?Shape?{ ??
ublic?
void
?paint(); ??
??} ??
? 注意,匿名內部類后面的分號不可缺少!
?? 匿名類,顧名思義,就是沒有名稱。
? getShape()方法里,就使用了匿名內部類。
? 看上去很奇怪,不符合傳統的寫法?
? 第一眼看上去確實是這樣的。
? 這樣寫,意思是創建了一個實現了Shape的匿名類的對象。
? 匿名類可以創建,接口,抽象類,與普通類的對象。創建接口時,必須實現接口中所有方法。
?
? 這是無參的,如果需要參數呢?
? 可以直接傳。?
?
Java代碼
???
public
?
class
?B?{ ??
public
?A?getA(
int
?num){ ??
????
return
?
new
?A(num){ ??
???????? ??
????}; ??
} ??
???} ??
???
public
?
class
?A?{ ??
private
?
int
?num; ??
public
?A(
int
?num){ ??
????
this
.num?=?num; ??
} ??
public
?A(){ ??
???? ??
} ??
???} ??
???
? Ok,在這個例子中,可以為A的構造方法傳入一個參數。在匿名內部類中,并沒有使用到這個參數。
? 如果使用到了這個參數,那么這個參數就必須是final的。
?
Java代碼
???
public
?
class
?B?{ ??
public
?A?getA(
final
?
int
?num){ ??
????
return
?
new
?A(num){ ??
???????
public
?
int
?getNum(){ ??
?????????????????????
return
?num; ??
??????????????????} ??
????}; ??
} ??
???} ??
???
public
?
class
?A?{ ??
private
?
int
?num; ??
public
?A(
int
?num){ ??
????
this
.num?=?num; ??
} ??
public
?A(){ ??
???? ??
} ??
???} ??
???
? 如果不是final的,編譯器就會提示出錯。
? 另外,還可以在匿名內部類里定義屬性
? 由于類是匿名的,自然沒有構造器,如果想模仿構造器,可以采用實例初始化({})
?
Java代碼
???
public
?A?getA(){ ??
return
?
new
?A(){ ??
????
int
?num?=?
0
; ??
????String?str; ??
????{ ??
????????str?=?
"javaeye"
; ??
????????System.out.println(
"hello?robbin"
); ??
????} ??
}; ??
???} ??
???
? 匿名內部類通過實例初始化,可以達到類似構造器的效果~
另外可以通過匿名內部類來改造工廠方法。
Java代碼
??
public
?
interface
?Service?{ ??
public
?
void
?method1(); ??
??} ??
??
public
?
interface
?ServiceFactory?{ ??
Service?getService(); ??
??} ??
??
public
?
class
?Implemention1?
implements
?Service{ ??
public
?
void
?method1(){ ??
????System.out.println(
"In?Implemention1?method?method1()"
); ??
} ??
??
public
?
static
?ServiceFactory?factory?=?
new
?ServiceFactory(){ ??
????
public
?Service?getService(){ ??
????????
return
?
new
?Implemention1(); ??
????} ??
}; ??
??} ??
??
public
?
class
?Implemention2?
implements
?Service?{ ??
public
?
void
?method1(){ ??
????System.out.println(
"in?Implemention2?method?method1()"
); ??
} ??
??
public
?
static
?ServiceFactory?factory?=?
new
?ServiceFactory(){ ??
????
public
?Service?getService(){ ??
????????
return
?
new
?Implemention2(); ??
????} ??
}; ??
??
??} ??
??
public
?
class
?Test?{ ??
public
?
static
?
void
?main(String?[]args){ ??
????service(Implemention1.factory); ??
????service(Implemention2.factory); ??
???? ??
????ServiceFactory?factory1?=?Implemention1.factory; ??
????Service?service1?=?factory1.getService(); ??
????service1.method1(); ??
???? ??
????ServiceFactory?factory2?=?Implemention1.factory; ??
????Service?service2?=?factory2.getService(); ??
????service2.method1(); ??
} ??
??} ??
在Implemention1和2中匿名內部類用在字段初始化地方。
這樣定義的工廠方法,代碼上看起來是不是優雅一些?
7、嵌套類
static的內部類就叫做嵌套類
前面提到了很多次,嵌套類是個例外
使用嵌套類時有兩點需要注意:
?? a、創建嵌套類對象時,不需要外圍類
?? b、在嵌套類中,不能像普通內部類一樣訪問外圍類的非static成員
Java代碼
??
public
?
class
?StaticClass?{ ??
private
?
int
?num; ??
private
?
static
?
int
?sum?=?
2
; ??
private
?
static
?
class
?StaticInnerClass{ ??
????
public
?
int
?getNum(){ ??
????
//只能訪問sum,不能訪問num
??
???????????????
return
?sum; ??
????} ??
} ??
??} ??
??
public
?
class
?Test?{ ??
public
?
static
?
void
?main(String?[]?args){ ??
???????????????
//可以直接通過new來創建嵌套類對象
??
????StaticClass.StaticInnerClass?inner?=?
new
?StaticClass.StaticInnerClass(); ??
????inner.getNum(); ??
} ??
??} ??
? 另外,嵌套類還有特殊之處,就是嵌套類中可以有static方法,static字段與嵌套類,而普通內部類中不能有這些。
? 8、內部類標識符
? 我們知道每個類會產生一個.class文件,文件名即為類名
? 同樣,內部類也會產生這么一個.class文件,但是它的名稱卻不是內部類的類名,而是有著嚴格的限制:外圍類的名字,加上$,再加上內部類名字。
? 前面說到得定義在方法內的內部類,不是在調用方法時生成,而是與外圍類一同編譯,就可以通過查看.class文件的方式來證明。
? 9、為何要內部類?
??? a、內部類提供了某種進入外圍類的窗戶。
??? b、也是最吸引人的原因,每個內部類都能獨立地繼承一個接口,而無論外圍類是否已經繼承了某個接口。
? 因此,內部類使多重繼承的解決方案變得更加完整。
? 在項目中,需要多重繼承,如果是兩個接口,那么好辦,接口支持多重繼承。
? 如果是兩個類呢?這時只有使用內部類了。
?
Java代碼
???
public
?
interface
?One?{ ??
public
?
void
?inOne(); ??
???} ??
???
public
?
interface
?Two?{ ??
public
?
void
?inTwo(); ??
???} ??
???
//兩個接口,用普通類就可實現多重繼承
??
???
public
?
class
?CommonClass?
implements
?One,Two?{ ??
public
?
void
?inOne(){ ??
????System.out.println(
"CommonClass?inOne()?method"
); ??
} ??
??
public
?
void
?inTwo(){ ??
????System.out.println(
"CommonClass?inTwo()?method"
); ??
} ??
???} ??
???
public
?
abstract
?
class
?Three?{ ??
public
?
abstract
?
void
?inThree(); ??
???} ??
???
public
?
abstract
?
class
?Four?{ ??
public
?
abstract
?
void
?inFour(); ??
???} ??
???
//兩個抽象類,使用普通類無法實現多重繼承
??
??? ??
???
//使用內部類可以實現
??
???
public
?
class
?Contents?
extends
?Three?{ ??
public
?
void
?inThree(){ ??
????System.out.println(
"In?Contents?inThress()?method"
); ??
} ??
??
public
?
class
?InnerFour?
extends
?Four{ ??
????
public
?
void
?inFour(){ ??
????????System.out.println(
"In?Contents"
); ??
????} ??
???? ??
} ??
???} ??
???
? 另外,還有好多地方可以使用內部類。讀過hibernate源代碼的同學,應該可以發現,里面有好多內部類。
? 最常見的內部類,應該是Map.Entry了,可以看看源代碼~?
總結:
? 內部類的特性大致就是上述了,特性很直觀,了解了之后,使用也很簡單。
? 但是,何時使用我說的并不是很明確,因為本人知識有限,使用內部類也不是很多。項目中很少用,好像就是ActiveMQ那里用了一些。
? 不過,相信大家在了解了內部類的特性之后,再隨著時間的推移,慢慢積累經驗,應該會做出自己的判斷,會在何時使用內部類,怎樣應用了。
Author
: orangelizq
email: orangelizq@163.com
歡迎大家訪問我的個人網站
萌萌的IT人
posted on 2010-04-21 15:03
桔子汁
閱讀(496)
評論(0)
編輯
收藏
所屬分類:
J2SE
新用戶注冊
刷新評論列表
只有注冊用戶
登錄
后才能發表評論。
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
相關文章:
[轉]處理線程泄露
[轉]內部類詳解
[轉]領略內部類的“內部”
[轉]Java中的內部類
[轉]一個計算機專業學生幾年的Java編程經驗匯總
[轉]共享內存在java中的實現
[轉]Find a way out of the ClassLoader maze
[轉]走出ClassLoader迷宮
對象初始化全過程
[轉]Java泛型編程指南
<
2010年4月
>
日
一
二
三
四
五
六
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
常用鏈接
我的隨筆
我的評論
我的參與
最新評論
留言簿
(9)
給我留言
查看公開留言
查看私人留言
隨筆分類
(124)
Flex
J2EE(25)
J2SE(23)
OSGI
other(19)
SOA(11)
Web Service(33)
開源軟件(3)
讀后感(2)
隨想(8)
隨筆檔案
(127)
2013年5月 (1)
2012年8月 (1)
2010年11月 (3)
2010年8月 (1)
2010年4月 (3)
2009年12月 (4)
2009年10月 (1)
2009年9月 (1)
2009年8月 (5)
2009年7月 (10)
2009年6月 (1)
2009年5月 (5)
2009年4月 (1)
2009年3月 (2)
2008年12月 (6)
2008年11月 (1)
2008年9月 (4)
2008年7月 (3)
2008年5月 (1)
2008年4月 (4)
2008年3月 (2)
2008年2月 (1)
2008年1月 (7)
2007年12月 (6)
2007年11月 (2)
2007年10月 (3)
2007年9月 (9)
2007年8月 (4)
2007年7月 (33)
2007年6月 (2)
文章分類
(5)
Java技術(2)
other
SOA
WebService 技術(3)
中間件相關
文章檔案
(5)
2007年9月 (3)
2007年7月 (1)
2007年6月 (1)
Good Blog
beansoft
dreamstone
周愛民
周筠老師
江南白衣
技術網站
IBM DevelopWork
搜索
積分與排名
積分 - 266932
排名 - 214
最新評論
1.?re: XML解析技術研究(一)[未登錄]
我有份XML,我需要解開明碼,用什么格式轉換都可以,有償價格。你看下能做不,報個價格我。我QQ;200879086 麻煩看見跟我聯系
--小林
2.?re: JNDI 學習
評論內容較長,點擊標題查看
--didafor
3.?re: 用Java實現基于SOAP的XML文檔網絡傳輸及遠程過程調用(RPC)[未登錄]
接受SOAP端代碼中,Enumeration e = bodyEntries.elements();
//如果當前情況下,向量中有更多條目,怎么選擇想要的條目
--Michael
4.?re: [轉]java中byte轉換int時為何與0xff進行與運算
lz你是在害人阿~
“1000 0000代表的就是-1 ”
--javachow
5.?re: XML解析技術研究(一)[未登錄]
文章不錯,收藏了。
--chchpd
閱讀排行榜
1.?[轉]java中byte轉換int時為何與0xff進行與運算(56476)
2.?消息中間件原理及JMS簡介(2) (21412)
3.?WSDL樣式詳解(17451)
4.?XML解析技術研究(一)(17111)
5.?消息中間件原理及JMS簡介(1)(13776)
Powered by:
博客園
模板提供:
滬江博客
Copyright ©2025 桔子汁
主站蜘蛛池模板:
99热在线观看免费
|
曰批视频免费40分钟试看天天
|
日韩精品无码免费一区二区三区
|
久久综合AV免费观看
|
亚洲精品高清在线
|
亚洲视屏在线观看
|
一级毛片正片免费视频手机看
|
亚洲精品国产第一综合99久久
|
国产VA免费精品高清在线
|
最近在线2018视频免费观看
|
免费少妇a级毛片人成网
|
精品亚洲成a人片在线观看少妇
|
在线亚洲午夜片AV大片
|
香蕉免费在线视频
|
好吊妞在线新免费视频
|
亚洲va久久久噜噜噜久久
|
亚洲国产成人久久综合
|
99re这里有免费视频精品
|
亚洲国产成人精品91久久久
|
亚洲六月丁香六月婷婷色伊人
|
无码AV动漫精品一区二区免费
|
久久久久久精品免费看SSS
|
日日摸日日碰夜夜爽亚洲
|
久久精品人成免费
|
亚洲精品尤物yw在线影院
|
一本色道久久88—综合亚洲精品
|
精品国产免费一区二区三区香蕉
|
国产不卡免费视频
|
ass亚洲**毛茸茸pics
|
国产日韩一区二区三免费高清
|
免费在线观看亚洲
|
色偷偷亚洲女人天堂观看欧
|
日本免费久久久久久久网站
|
免费在线观看毛片
|
亚洲视频无码高清在线
|
99热在线免费播放
|
亚洲精品国产成人片
|
大片免费观看92在线视频线视频
|
四虎成人免费大片在线
|
亚洲码一区二区三区
|
久久九九AV免费精品
|