Read Sean
Read me, read Sean.
posts - 508, comments - 655, trackbacks - 9, articles - 4
導(dǎo)航
BlogJava
首頁
新隨筆
聯(lián)系
聚合
管理
公告
關(guān)于我
人生是一場對話
我的譯作
聲明
所有文章和代碼在這里以"現(xiàn)狀"提供,作者不提供任何形式的擔(dān)保,也沒有授予除閱讀和有條件共享之外的任何權(quán)利。除非特別說明,所有文章均為本blog作者原創(chuàng),如需轉(zhuǎn)載請注明出處和原作者,如用于商業(yè)目的,需作者本人書面許可。
推薦文章
Pylons起步
常用鏈接
我的隨筆
我的評論
我的參與
最新評論
留言簿
(29)
給我留言
查看公開留言
查看私人留言
隨筆分類
(842)
Computer Usage(72)
Database(9)
GNU/Linux(30)
On Eclipse(52)
On Java(131)
On Python(11)
Operating Systems(70)
Other Languages(28)
Programming in General(41)
Project Management(25)
Reading(189)
The Other Side(129)
Web Clips(55)
隨筆檔案
(507)
2014年5月 (1)
2014年4月 (1)
2014年3月 (1)
2014年1月 (1)
2012年11月 (1)
2011年8月 (2)
2011年7月 (1)
2011年3月 (1)
2011年2月 (2)
2011年1月 (5)
2010年12月 (2)
2010年1月 (1)
2009年12月 (1)
2009年11月 (1)
2009年10月 (1)
2009年9月 (1)
2009年8月 (1)
2009年7月 (1)
2009年6月 (2)
2009年5月 (1)
2009年4月 (1)
2009年3月 (2)
2009年2月 (2)
2009年1月 (15)
2008年12月 (10)
2008年11月 (1)
2008年10月 (4)
2008年9月 (1)
2008年8月 (3)
2008年7月 (3)
2008年6月 (2)
2008年5月 (2)
2008年4月 (1)
2008年3月 (4)
2008年2月 (5)
2008年1月 (4)
2007年12月 (2)
2007年11月 (2)
2007年10月 (1)
2007年9月 (1)
2007年8月 (2)
2007年7月 (2)
2007年6月 (4)
2007年5月 (3)
2007年4月 (5)
2007年3月 (4)
2007年2月 (23)
2007年1月 (26)
2006年12月 (30)
2006年11月 (14)
2006年10月 (6)
2006年9月 (2)
2006年8月 (3)
2006年7月 (3)
2006年6月 (5)
2006年5月 (3)
2006年4月 (17)
2006年3月 (9)
2006年2月 (28)
2006年1月 (17)
2005年12月 (8)
2005年11月 (23)
2005年10月 (43)
2005年9月 (19)
2005年8月 (30)
2005年7月 (13)
2005年6月 (7)
2005年5月 (5)
2005年4月 (12)
2005年3月 (20)
2005年2月 (19)
2005年1月 (8)
文章檔案
(4)
2010年12月 (1)
2009年1月 (1)
2005年8月 (1)
2005年1月 (1)
Friends' blogs
emu in blogjava
jackei
kukoo's blog
搜索
積分與排名
積分 - 783388
排名 - 54
最新評論
1.?re: [Tips] <abbr>: 一個有趣的HTML標(biāo)簽
dqwdqwdqw
--額范圍啊
2.?re: [Tips] <abbr>: 一個有趣的HTML標(biāo)簽
<scrtpt>alert("fwefwargvaerg");</script>
--額范圍啊
3.?re: iText vs FOP - Java動態(tài)生成PDF的兩個選擇
用0.95報錯的大概意思是還不支持。。。。。
本地字庫的字體embet不進去。。。。
--fop
4.?re: iText vs FOP - Java動態(tài)生成PDF的兩個選擇
代碼拷貝運行報錯啊
--fop
5.?11[未登錄]
404
--00
6.?re: [Tips] Spring 2.5.6新特性之packagesToScan
101
--11
7.?re: Mac安裝tsocks
評論內(nèi)容較長,點擊標(biāo)題查看
--mzj
8.?re: [Jakarta Commons筆記] org.apache.commons.lang.time
哈哈,什么情況,10年前的文章,今天來讀一讀
--宇飛
9.?re: Mac安裝tsocks
有一個proxychains-ng項目,還在更新,可以試試的
--ayanamist
10.?re: SourceForge.net上的文件下載頁面無法打開的一種解決方法
評論內(nèi)容較長,點擊標(biāo)題查看
--Douglas
11.?re: [Tips] Windows/Linux雙系統(tǒng)重裝Windows后無法進入Linux的最速解決辦法
linux是進去了,windows又進不去了
--ss
12.?re: [RPi] 樹梅派安裝Archlinux和藍(lán)牙
這種便宜dongle有個問題就是藍(lán)牙MAC地址是一樣的,同一環(huán)境下使用多個會有點麻煩,需要找個辦法繞過去。
--laogao
13.?re: [愚公移山] 團隊CVS資源庫從CVSNT遷移到Linux
評論內(nèi)容較長,點擊標(biāo)題查看
--guest
14.?re: [Jakarta 筆記] org.apache.commons.lang.math[未登錄]
評論內(nèi)容較長,點擊標(biāo)題查看
--doctor
15.?re: Jakarta Commons專題 - 隨筆列表
可惜晚了這么多年,才讀到樓主的文章。
--rox
閱讀排行榜
1.?[Tips] 惱人的winmail.dat及解決辦法(36633)
2.?[Eclipse筆記]在Eclipse下做UML設(shè)計(28411)
3.?[Tips] Spring 2.5.6新特性之packagesToScan(22737)
4.?iText vs FOP - Java動態(tài)生成PDF的兩個選擇(13773)
5.?IntelliJ IDEA 常用快捷鍵(12899)
6.?pyPdf - 用Python方便的處理PDF文檔(12659)
7.?[Linux起步]配置Java和Eclipse環(huán)境(9876)
8.?Java命令行實用工具jps和jstat(9497)
9.?你真的理解了繼承和多態(tài)嗎?(7682)
10.?Drip, Transfusion, Perfusion還是Infusion?關(guān)于一個詞的翻譯(7591)
11.?[Eclipse筆記]配置SWT開發(fā)環(huán)境(7541)
12.?[Jakarta Commons筆記] org.apache.commons.lang.time(7369)
13.?如何在Ubuntu下訪問本地NTFS分區(qū)(6504)
14.?[Jakarta Commons筆記] org.apache.commons.lang.builder(6096)
15.?J2SE(TM) 5.0專題 之 語言特性 // 勘誤信息請直接回復(fù)(5747)
評論排行榜
1.?[Tips] 惱人的winmail.dat及解決辦法(48)
2.?6個Gmail邀請,需要的朋友請在這里回復(fù)。(已結(jié)束)(34)
3.?[Eclipse筆記]在Eclipse下做UML設(shè)計(29)
4.?[Eclipse筆記]請對Java、Sun、NetBeans、Eclipse感興趣朋友的看看Eclipse對Sun的心態(tài)吧(19)
5.?令人驚喜的Feisty,讓人失望的Evolution(15)
6.?你真的理解了繼承和多態(tài)嗎?(14)
7.?[Jakarta Commons筆記] org.apache.commons.lang.time(11)
8.?iText vs FOP - Java動態(tài)生成PDF的兩個選擇(11)
9.?[Eclipse筆記]SWT真正的優(yōu)勢不是快這么簡單(9)
10.?[Linux起步]SuSE Linux 10.0正式發(fā)布(9)
11.?Drip, Transfusion, Perfusion還是Infusion?關(guān)于一個詞的翻譯(8)
12.?[Tips] 在Ubuntu Linux 6.06 LTS (Dapper Drake)上安裝CVS服務(wù)(8)
13.?Nikon F80 + AF Nikkor 50mm/1.4 D 的魅力(8)
14.?[Linux起步]配置Java和Eclipse環(huán)境(7)
15.?J2SE(TM) 5.0專題 之 語言特性 // 勘誤信息請直接回復(fù)(7)
你真的理解了繼承和多態(tài)嗎?
Posted on 2005-06-07 15:18
laogao
閱讀(7682)
評論(14)
編輯
收藏
所屬分類:
On Java
、
Programming in General
最近被同事問起一道SCJP的題目,是跟繼承和多態(tài)有關(guān)的。具體的題目我就不重復(fù)了,來看一段我自己敲的代碼:
1
package sean.work.test;
2
3
public
class
DoYouReallyUnderstandPolymorphism
{
4
5
public
static
void
main(String[] args)
{
6
A a
=
new
A();
7
B b
=
new
B();
8
a.s
=
"
[AA]
"
;
9
b.s
=
"
[BB]
"
;
10
System.
out
.println(a.s);
//
prints "[AA]"
11
System.
out
.println(b.s);
//
prints "[BB]"
12
System.
out
.println(a.getS());
//
prints "[AA]"
13
System.
out
.println(b.getS());
//
prints "[BB]"
14
System.
out
.println(
"
====================
"
);
15
a
=
b;
//
a now refers to object b
16
System.
out
.println(a.s);
//
prints "[A]" <<--1-- the class A copy
17
System.
out
.println(b.s);
//
prints "[BB]"
18
System.
out
.println(a.getS());
//
prints "[BB]"
19
System.
out
.println(b.getS());
//
prints "[BB]"
20
System.
out
.println(
"
====================
"
);
21
((A)b).s
=
"
[AA]
"
;
//
<<--2-- changes the class A copy in object b
22
System.
out
.println(a.s);
//
prints "[AA]" <<--3-- class A copy changed
23
System.
out
.println(b.s);
//
prints "[BB]"
24
System.
out
.println(a.getS());
//
prints "[BB]"
25
System.
out
.println(b.getS());
//
prints "[BB]"
26
}
27
28
}
29
30
class
A
{
31
String s
=
"
[A]
"
;
32
String getS()
{
33
return
s;
34
}
35
}
36
37
class
B extends A
{
38
String s
=
"
[B]
"
;
39
String getS()
{
40
return
s;
41
}
42
}
43
這里我們的B類繼承自A類,重寫了getS()方法,于是我們可以利用到多態(tài)。如果你留意15、16、21、22這幾行的話,你也許就會知道我在說什么了。假如你覺得這樣的打印結(jié)果是理所當(dāng)然,那么我想你可以完全忽略這篇隨筆,因為我要講的就集中在這幾行,而你已經(jīng)很清楚的理解背后的含義。
下面跟感興趣的朋友們說說我的理解:
直觀的講,我們很容易輕信當(dāng)"a = b;"以后,變量a指向的對象是B類的b那個對象,自然a.s就應(yīng)該等同于b.s,然而事實并非如此。當(dāng)B繼承A時,父類A的字段s并沒有被B的字段s取代,而是保留了一份拷貝,所謂重寫(Override),那是對方法而言的。于是,當(dāng)我們new B()時,在實際創(chuàng)建的對象中,包含了兩個版本的字段s,一個"[A]"(屬于A類)一個"[B]"(屬于B類)。而方法getS()只有一個版本。這就是在繼承過程中字段和方法的區(qū)別。也就是說,重寫的概念和字段無關(guān)。在第16行,我們通過a.s訪問的是b這個對象中保留的A類的字段s;而在21行,我們改變的正是這個A類版本的s字段。
多態(tài)的精髓在于動態(tài)確定對象的行為,而對象的行為體現(xiàn)在方法而非字段,字段代表的更多的是對象的狀態(tài)。于是只有方法的多態(tài)而沒有字段的多態(tài)。從上面的代碼可以看出,不管你用什么類型的變量存放對象b的引用,最終調(diào)用的方法版本都是b的真實類型那個版本,這就是多態(tài)的威力。
從編譯的角度來看,上面代碼中的s字段和getS()方法的不同在于:s字段是在編譯期靜態(tài)鏈接(你可以改變它的值,但是它在對象中的相對地址已經(jīng)確定好),而getS()方法是在運行期動態(tài)鏈接的。
說了這么多,真的不知道我表達(dá)清楚沒有,畢竟沒有系統(tǒng)研究過OO和編譯原理,說得不當(dāng)?shù)牡胤竭€請多多包涵。最后,請不要學(xué)我這里的編碼風(fēng)格,因為很顯然應(yīng)該對main方法中的代碼段執(zhí)行Extract Method重構(gòu)了,我這里只是為了注釋方便。
// BTW,時不時抽空想想這樣的問題感覺真不錯。
Feedback
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2005-06-07 16:26 by
小毅
謝謝您,學(xué)到很容易忽略的東西,覺得很重要
再謝謝你...
#
原來字段和方法有這樣的區(qū)別哦
回復(fù)
更多評論
2005-06-08 09:02 by
emu
>>只有方法的多態(tài)而沒有字段的多態(tài)
以前都沒有想過這個問題哦。
前兩天遇到一個內(nèi)嵌類的方法重載時候的古怪問題,不知是否與此有關(guān),正好回頭去研究一下。
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2005-06-08 12:16 by
FS
Java的對象模型偶不太清楚,不過通過對Delphi的對象模型的了解,我感覺應(yīng)該和Java沒有太大的區(qū)別。
按照樓主所說的,當(dāng)執(zhí)行了語句“a=b”后,變量a和b的內(nèi)容應(yīng)該是不變的,所變的是a指向的對象實體中的指向類的指針的內(nèi)容,在Delphi中,這個指針叫做vptr,CPP中也是如此叫法。vptr直接指到類的VMT(不知道Java中如何叫法);因此,再次使用a.s訪問實例變量,則要進入b指向的對象實體中進行字段的查找,但由于b里面存在兩個s字段,并且以類型信息為區(qū)分方式,所以找到的是類型A的字段s。至于編譯處理方面,我想應(yīng)該是把類型信息作為字段的前綴或者后綴。
同樣,當(dāng)執(zhí)行了“((A)b).s=“[AA]””后,由于已經(jīng)把b的類型轉(zhuǎn)化為A類型,而且b指針的未改變,所以在b的對象實體中,實際改變的是屬于類型A的字段s的內(nèi)容。個人感覺,其實樓主已經(jīng)說出了,對b中不同類型的同名字段的訪問方式。
最后留下一個問題:這種對象模型中的字段處理方式如果在繼承字段訪問量小的情況下是很浪費空間的。那么,這樣處理的優(yōu)點又是什么?
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2005-06-08 12:18 by
FS
按照OO這種東西在語言設(shè)計上的考慮,對象所涉及到的所有內(nèi)容就是三塊:對象指針,對象實體和對象所屬類型的內(nèi)存布局。而對象實體中只存放狀態(tài)信息,即對象所屬類型的實例字段的內(nèi)容,因此,從這個角度考慮,多態(tài)和實例字段的信息是沒有任何關(guān)系的。但對于類字段,即申明為static的字段就未必了。
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2005-07-20 23:24 by
丑男
System.out.println(a.s); // prints "[A]"
這句確實我沒想到!看來真被難倒了
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2006-05-15 17:30 by
songxu
非常感謝
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2006-07-15 17:22 by
tcpipok
我是想到了,不過就像樓主所說的,這種編碼風(fēng)格不好,子類盡量不要用父類用過的變量名,真的是容易搞混,這種代碼用來考試可以,但用來編程不好.
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2006-08-17 20:34 by
小小
請問:
java中字符串的連接是不是一種多態(tài)的表現(xiàn)?
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2007-03-05 22:52 by
谷鈺
@tcpipok
我不知道你是否理解OO真正的精髓,以上用法展示了面向?qū)ο笤O(shè)計的核心思想,通過虛方法調(diào)用,實現(xiàn)不同子類對同一行為(方法)的不同實現(xiàn)。希望以下例子可以給大家一些啟發(fā):
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2007-03-05 23:05 by
谷鈺
public class Employee {
protected String name = "張三";
private double salary = 1000;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public Employee() {
this("王老五", 1);
}
public String getDetails() {
return "姓名:" + this.name + ", 工資: " + this.salary;
}
public double getSalary() {
return this.salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof Employee) {
Employee te = (Employee) o;
return this.salary == te.getSalary() && this.name.equals(te.getName());
}
return false;
}
public int hashCode() {
if (this.name == null) {
return 0;
}
return this.name.hashCode();
}
public String toString() {
return "$$" + this.getDetails();
// return super.toString();
}
public static void printAll(Employee[] all) {
System.out.println("所有員工:");
for (int i = 0; i < all.length; ++i) {
System.out.println(all[i].getDetails());
}
}
public static void main(String[] args) {
Employee e = new Employee("張三", 2500);
System.out.println(e.getDetails());
Manager m = new Manager("李四", 4500, "軟件開發(fā)部");
System.out.println(m.getDetails());
Employee ee = new Manager("王五", 4500, "軟件銷售部");
System.out.println(ee.getDetails());
if (ee instanceof Manager) {
Manager mmm = (Manager) ee;
System.out.println(mmm.getDepartment());
}
Employee e2 = new Employee("張三", 2500);
System.out.println(e.equals(e2));
System.out.println(e);
System.out.println("##" + e);
Employee[] eAll = {
e, m, ee
};
printAll(eAll);
}
}
class Manager extends Employee {
private String department = "44";
public Manager() {
super();
this.department = "計算機";
}
public Manager(String name, double salary, String department) {
super(name, salary);
this.department = department;
}
public String getDetails() {
return super.getDetails() + ", 管理部門: " + this.department;
}
public String getDepartment() {
return this.department;
}
}
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2007-03-05 23:11 by
谷鈺
核心在
public static void printAll(Employee[] all) {
System.out.println("所有員工:");
for (int i = 0; i < all.length; ++i) {
System.out.println(all[i].getDetails());
}
}
函數(shù)的設(shè)計上,通過Employee隱藏所有雇員子類的細(xì)節(jié),通過getDetails()方法來隱藏不同雇員(Manger,Engineer等)對詳細(xì)信息的函數(shù)細(xì)節(jié)。
只有這樣的函數(shù)才能最大程度上復(fù)用,既當(dāng)設(shè)計有新的Employee子類定義也不許要對此函數(shù)做任何的修改,個人認(rèn)為面向?qū)ο蟮淖畲蠛锰幨翘岣叱绦虻膹?fù)用性,降低維護成本。這些需要多態(tài),繼承才能作到。:)
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2007-03-06 09:38 by
大胃
謝謝 谷鈺 的回復(fù)!
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2008-05-21 17:06 by
tonytang
to 谷鈺,你的代碼也沒有回答tcpipok的疑問啊。子類和父類定義相同的屬性有意義嗎?
#
re: 你真的理解了繼承和多態(tài)嗎?
回復(fù)
更多評論
2008-06-25 11:00 by
shell
寫的太好了。
學(xué)習(xí)了很多。
新用戶注冊
刷新評論列表
只有注冊用戶
登錄
后才能發(fā)表評論。
網(wǎng)站導(dǎo)航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
相關(guān)文章:
IntelliJ IDEA 常用快捷鍵
[Tips] Windows環(huán)境下Apache最基本的調(diào)優(yōu)方法
"上海"是如何變成"涓婃搗"的?
如何讓統(tǒng)一版本的Eclipse RCP應(yīng)用同時支持多個平臺
Java命令行實用工具jps和jstat
用Scala解Hanoi塔
[Tips] Spring+Hibernate之“暴力”update
[Tips] Spring 2.5.6新特性之packagesToScan
easyb - Getting Started
Spring 3.0前瞻
Powered by:
BlogJava
Copyright © laogao
主站蜘蛛池模板:
久久亚洲精品人成综合网
|
午夜影院免费观看
|
国产成人精品亚洲2020
|
国产成A人亚洲精V品无码性色
|
日本特黄特黄刺激大片免费
|
最近中文字幕免费完整
|
99久久免费国产精精品
|
美女露隐私全部免费直播
|
中文日韩亚洲欧美制服
|
久久久久亚洲AV无码永不
|
亚洲色大成网站WWW久久九九
|
国产又粗又猛又爽又黄的免费视频
|
老司机亚洲精品影院无码
|
国产成人99久久亚洲综合精品
|
在线成人a毛片免费播放
|
18禁黄网站禁片免费观看不卡
|
国产免费人人看大香伊
|
免费观看的毛片大全
|
久久国产乱子免费精品
|
中国一级毛片免费看视频
|
人碰人碰人成人免费视频
|
羞羞网站在线免费观看
|
老司机福利在线免费观看
|
99亚洲精品卡2卡三卡4卡2卡
|
亚洲精品永久在线观看
|
亚洲最大的成人网
|
国产亚洲精品AA片在线观看不加载
|
久久久久亚洲AV无码专区桃色
|
免费a级毛片无码a∨性按摩
|
青青草国产免费久久久91
|
全免费a级毛片免费看无码
|
成人黄动漫画免费网站视频
|
亚洲性一级理论片在线观看
|
亚洲影视一区二区
|
亚洲一区无码中文字幕乱码
|
亚洲精品中文字幕乱码
|
亚洲精品**中文毛片
|
亚洲综合色一区二区三区
|
亚洲综合小说另类图片动图
|
久久精品国产亚洲av瑜伽
|
免费精品视频在线
|