欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

引用,造型,protected和private的困惑

系統(tǒng) 2012 0
或許大家java的多態(tài)問(wèn)題,對(duì)上溯,下溯造型有了一定的概念,對(duì)protected和private大家想必也很清楚,但是,這幾個(gè)個(gè)結(jié)合在一起,往往令人產(chǎn)生很多困惑,在這里,我舉一個(gè)例子,大家或許會(huì)發(fā)覺這篇文章對(duì)你來(lái)說(shuō)還是很有意義的:
例子一共有兩個(gè)class.可能出現(xiàn)困惑的地方我都會(huì)在后面一一解釋.
A是一個(gè)父類,B繼承A,并且實(shí)現(xiàn)了protectedTest(Objectobj)方法.如下面所示:
B.java的源代碼:
packagecn.org.matrix.test;
importcn.org.matrix.test.A;
/**
*<p>Title:protect,privateandupcasting</p>
*<p>Description:email:chris@matrix.org.cn</p>
*<p>Copyright:MatrixCopyright(c)2003</p>
*<p>Company:Matrix.org.cn</p>
*@authorchris
*@version1.0,whousethisexampleplsremainthedeclare
*/
publicclassBextendsA
{
protectedintprotectedb=0;
protectedintprotectedab=0;


protectedvoidprotectedTest(Objectobj)
{
System.out.println("inB.protectedTest(Object):"+obj);
}
}

A.java的源代碼:
packagecn.org.matrix.test;
importcn.org.matrix.test.B;
/**
*<p>Title:protect,privateandupcasting</p>
*<p>Description:email:chris@matrix.org.cn</p>
*<p>Copyright:MatrixCopyright(c)2003</p>
*<p>Company:Matrix.org.cn</p>
*@authorchris
*@version1.0,whousethisexampleplsremainthedeclare
*/

publicclassA
{
protectedintprotecteda=0;
protectedintprotectedab=0;
privatevoidprivateTest()
{
System.out.println("inA.privateTest()");
}
protectedvoidprotectedTest(Objectobj)
{
System.out.println("inA.protectedTest(Object):"+obj);
}

protectedvoidprotectedTest(Stringstr)
{
System.out.println("inA.protectedTest(String):"+str);
}

publicstaticvoidmain(String[]args)
{
//TestA
Aa1=newA();
a1.privateTest();
//TestB
StringhelloStr="Hello";
ObjecthelloObj=helloStr;
Bb1=newB();
Aa2=b1;//這里發(fā)生了什么?困惑1
b1=a1;//編譯錯(cuò)誤,困惑2
b1.privateTest();//編譯錯(cuò)誤,困惑3
b1.protectedTest(helloObj);//輸出結(jié)果?困惑4
b1.protectedTest(helloStr);//編譯錯(cuò)誤,困惑5
a2.protectedTest(helloObj);//輸出結(jié)果?困惑6
a2.protectedTest(helloStr);//輸出結(jié)果?困惑7?
}
}

下面,我來(lái)逐個(gè)解釋每一處困惑的地方:
困惑1:
這里其實(shí)就是子類自動(dòng)上溯造型到父類A。這里a2其實(shí)是指向了一個(gè)B類型的對(duì)象.我們通常都可以這樣作:Aa2=b1,這樣作的意思實(shí)際上就是讓a2指向了一個(gè)類型B的對(duì)象—在這里就是b1了.
在java里面,關(guān)于跨類引用,有兩條規(guī)則應(yīng)該記住:
1.如果a是類A的一個(gè)引用,那么,a可以指向類A的一個(gè)實(shí)例,或者說(shuō)指向類A的一個(gè)子類.
2.如果a是接口A的一個(gè)引用,那么,a必須指向?qū)崿F(xiàn)了接口A的一個(gè)類的實(shí)例.
所以,根據(jù)這兩個(gè)規(guī)則,我們就不難理解例子中的Aa2=b1是什么意思了.

困惑2:
Aa2=b1是可以的,但是為什么b1=a1卻是不行?在這里,我們依然可以套用上面的兩條規(guī)則,我們可以看到,b1是類B的一個(gè)引用,a1既不是類B的實(shí)例,也不是類B的子類的實(shí)例,所以直接b1=a1就出現(xiàn)了編譯錯(cuò)誤.
如果確實(shí)需要進(jìn)行這樣的轉(zhuǎn)化,我們可以這樣作:b1=(B)a1;進(jìn)行強(qiáng)制轉(zhuǎn)化,也就是下溯造型.在java里面,上溯造型是自動(dòng)進(jìn)行的,但是下溯造型卻不是,需要我們自己定義強(qiáng)制進(jìn)行.

困惑3:
b1.privateTest();編譯不通過(guò)?這是很顯然的,你可以回顧一下private的定義:私有域和方法只能被定義該域或方法的類訪問(wèn).所以,在這里,b1不能訪問(wèn)A的方法privateTest(),即使b1是A的子類的實(shí)例.
請(qǐng)看下面的例子:
publicclassA
{
privateinttwo(inti){returni;}
}
classTestextendsA{
publicstaticvoidmain(String[]args){
System.out.println(A.two(3));
}
}

System.out.println(A.two(3));這行編譯出錯(cuò),顯然,因?yàn)閜rivate方法不能在這個(gè)類之外被訪問(wèn)。

而protected則不同,我們回顧一下protected的定義:被保護(hù)的域或方法只能被類本身、類的子類和同一程序包中的類所訪問(wèn)。
下面是一個(gè)錯(cuò)誤使用protected的例子:
packagecn.org.matrix.test;
publicclassProtectedTest{
protectedvoidshow(){
System.out.println("Iaminprotectedmethod");
}
}

importcn.org.matrix.test.*;
publicclassTest{
publicstaticvoidmain(String[]args){
ProtectedTestobj=newProtectedTest();
obj.show();
}
}
因?yàn)樵L問(wèn)權(quán)限問(wèn)題,你會(huì)得到”show()hasprotectedaccessintest.ProtectedTest”的出錯(cuò)信息.


困惑4:
b1.protectedTest(helloObj);輸出的是”inB.protectedTest(Object):…”這到底是為什么呢?為什么jvm能夠確定是輸出B的方法而不是A的方法?這就和jvm的運(yùn)行機(jī)制有關(guān)系了.我們上面提到了,a1是一個(gè)A類型的引用,但是指向了一個(gè)B類型的實(shí)例.在這里,如果jvm根據(jù)引用的類型-在這里就是A來(lái)定義調(diào)用哪個(gè)方法的話,那么應(yīng)該是調(diào)用A的protectedTest(helloObj).
然后實(shí)際上不是這樣的,因?yàn)閖vm的動(dòng)態(tài)編譯能力,jvm會(huì)在run-time來(lái)決定調(diào)用哪一個(gè)method,而不是在compiletime.也就是所謂的late-binding(run-time)和early-binding(compile-time).

困惑5:
b1.protectedTest(helloStr);這里為什么會(huì)出現(xiàn)編譯錯(cuò)誤?他可以調(diào)用類B的protectedTest(Objectobj)方法啊,把helloStr上溯造型成一個(gè)object就行了啊..或者上溯造型到A然后調(diào)用A的protectedTest(helloStr)方法啊.
呵呵,問(wèn)題的根源就在于此了,既然有兩種選擇,jvm應(yīng)該選擇那一種?這種不確定性如果交給jvm來(lái)動(dòng)態(tài)決定的話,勢(shì)必帶來(lái)程序的不確定性..雖然java在其他的一些地方也有類似的情形出現(xiàn),比如static變量的循環(huán)定義造成的不確定性,但是,在這里,jvm還是在編譯階段就解決了這個(gè)問(wèn)題.
所以,我們會(huì)在這一步遇到編譯錯(cuò)誤:“referencetoprotectedTestisambiguous;bothmethodprotectedTest(java.lang.String)inmytest.AandmethodprotectedTest(java.lang.Object)inmytest.Bmatchatline46.
在這里,我們遇到的是顯式的referenceambiguous錯(cuò)誤,但是,有時(shí)候,隱式的referenceambiguous卻往往是更加的危險(xiǎn).
在這里,我舉個(gè)例子:
父類的源代碼:
publicsuper
{
privatevoidtest(inti,longj);
{
System.out.println(i+”and”+j);
}
}
子類的源代碼:
publicsub
{
privatevoidtest(longj,inti);
{
System.out.println(i+”and”+j);
}
}

子類和父類都用有相同名稱的方法test,參數(shù)類型不同而已.這種情況下,編譯可以被通過(guò).
但是如果你在另外一個(gè)類中用到了如下代碼:
Subsb=newSub();
sb.test(100,3000);
你就會(huì)遇到編譯錯(cuò)誤,因?yàn)闆]有確定的指出3000的類型,所以造成referenceambiguous的錯(cuò)誤了.

困惑6:
a2.protectedTest(helloObj);
輸出結(jié)果分別是:”inB.protectedTest(Object)..”經(jīng)過(guò)上面的解釋,想必大家都能很清楚的知道為什么會(huì)有這兩個(gè)輸出結(jié)果了:a2.protectedTest(helloObj);因?yàn)閖vm的late-binding,所以在run-time的時(shí)候,調(diào)用了B類的方法,雖然在編譯期間a2只是一個(gè)父類A的引用類型。

困惑7:
a2.protectedTest(helloStr);為什么這里會(huì)輸出”inA.protectedTest(Object)…”。為什么這里不會(huì)編譯出錯(cuò)?為什么b1.protectedTest(helloStr)會(huì)出錯(cuò)而a2.protectedTest(helloStr)會(huì)出錯(cuò)?我調(diào)用了a2.equals(b1)和a2==b1得到的結(jié)果都是true啊?但是為什么這里出這個(gè)錯(cuò)誤?
在這里,這個(gè)問(wèn)題是最關(guān)鍵的,也是我們放到最后來(lái)解答的原因。
首先,回顧一下equals()和==的在java里面的概念,記得有一道scjp的題目:
題目:下面的哪些敘述為真。
A.equals()方法判定引用值是否指向同一對(duì)象。
B.==操作符判定兩個(gè)分立的對(duì)象的內(nèi)容和類型是否一致。
C.equals()方法只有在兩個(gè)對(duì)象的內(nèi)容一致時(shí)返回true。
D.類File重寫方法equals()在兩個(gè)分立的對(duì)象的內(nèi)容和類型一致時(shí)返回true。
答案是AD,嚴(yán)格來(lái)說(shuō)這個(gè)問(wèn)題的答案是不確定的,因?yàn)閑quals()方法是可以被重載的,但是如果新類沒有重寫equals(),則該方法在兩個(gè)變量指向同一對(duì)象時(shí)返回真.實(shí)際上java也是推薦的是使用equals()方法來(lái)判斷兩個(gè)對(duì)象的內(nèi)容是否一樣,就像String類的equals()方法所做的那樣,判定兩個(gè)String對(duì)象的內(nèi)容是否相同。而==操作符返回true的唯一條件是兩個(gè)變量指向同一對(duì)象。
在這里,我們不再深入的討論關(guān)于equals()和==的區(qū)別和概念。我們只需要知道,在我們的例子里面,無(wú)論是equals()和==都是一個(gè)含義-就是引用值是否指向同一個(gè)對(duì)象(因?yàn)槲覀儾]有重寫equals()).
顯然,我們?cè)谶M(jìn)行了a2=b1.這一步之后,a2和b1都是指向同一個(gè)對(duì)象。
既然指向同一個(gè)對(duì)象,為什么還要區(qū)別對(duì)待a2和b1?為什么a2就沒有編譯錯(cuò)誤,而b1就要遇到referenceambiguous錯(cuò)誤?
我們現(xiàn)看看jvm規(guī)范里的一段話:
“TheJavaVirtualMachinedoesnotrequireanyparticularinternal
structureforobjects.InSun'scurrentimplementationoftheJavaVirtualMachine,areferencetoaclassinstanceisapointertoahandlethatisitselfapairofpointers:onetoatablecontainingthemethodsoftheobjectandapointertotheClassobjectthatrepresentsthetypeoftheobject,andtheothertothememoryallocatedfromtheJavaheapfortheobjectdata.”
實(shí)際上就是說(shuō):在java虛擬機(jī)中,類實(shí)例的引用就是指向一個(gè)句柄(handle)的指針,這個(gè)句柄是一對(duì)指針:一個(gè)指針指向一張表格,實(shí)際上這個(gè)表格也有兩個(gè)指針:一個(gè)指針指向一個(gè)包含了對(duì)象的方法表,另外一個(gè)指向類對(duì)象;另一個(gè)指針指向一塊從java堆中為分配出來(lái)內(nèi)存空間。
那么,在a2=b1的時(shí)候,到底發(fā)生了什么?
實(shí)際上,在a2=b1的時(shí)候,仍然是存在兩個(gè)句柄,a2和b1,但是a2和b1擁有同一塊數(shù)據(jù)內(nèi)存塊和不同的函數(shù)表。所以在a2.protectedTest(helloStr)的時(shí)候,jvm會(huì)從a2的函數(shù)表里找到protectedTest(StringStr)方法,但是b1.protectedTest(helloStr)卻會(huì)出現(xiàn)編譯錯(cuò)誤,因?yàn)閖vm從b1的函數(shù)表里找不到,然后就選擇自己上溯造型還是參數(shù)上溯造型出現(xiàn)了ambiguous。這也是我們對(duì)這個(gè)問(wèn)題的精確解釋。對(duì)這個(gè)問(wèn)題的解釋到此結(jié)束了,如果大家想對(duì)這篇文章相關(guān)內(nèi)容進(jìn)行討論,可以到: http://blog.csdn.net/chensheng913/archive/2004/10/23/148309.aspx 發(fā)表意見.

引用,造型,protected和private的困惑


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产精品久久久久久久久久红粉 | 日韩中文字幕不卡 | 国产999在线| 黄色7777 | 毛片在线不卡 | 国产毛A片啊久久久久久A | 精品一区二区三区在线视频 | 日韩在线激情 | 亚洲国产精品一区二区三区久久 | 大学门卫老秦无删减版txt | 九九九国产在线 | 2015小明看日韩成人免费视频 | 日韩在线短视频 | 免费在线亚洲视频 | 日本黄色福利视频 | 欧美老妇交乱视频 | 国产在线观看午夜不卡 | 91久久久久久久久 | 欧美日韩国产在线观看 | 日本黄色大片免费看 | 国产一卡2卡三卡4卡免费网站 | 精品五月天| 男女在线免费视频 | 青娱乐在线免费观看视频 | av789| 舒淇三级浴室洗澡在线观看 | 欧美一区二区三区久久久 | 五月天综合在线 | 99热热热 | 国产91久久最新观看地址 | 一级毛片在线看在线播放 | 欧美一区二区三区国产精品 | 中文字幕第一页在线 | 欧美日韩在线视频一区 | 午夜啪视频 | 亚洲欧美另类在线观看 | 久久网页| 天天操天天摸天天舔 | 六月婷婷在线 | 婷婷久月 | 一级毛片免费不卡在线 |