freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

[工學(xué)]java學(xué)習(xí)筆記之父類與子類(編輯修改稿)

2024-09-13 01:11 本頁面
 

【文章內(nèi)容簡介】 selfdefine constructor  program end   如果沒有看過上面的關(guān)于類的構(gòu)造的說明,很容易讓人誤解為類的構(gòu)造順序是如下的結(jié)果(忽略參數(shù)綁定、內(nèi)存分配和非靜態(tài)成員的缺省值賦值): ?。ㄟ@個的先后順序取決于源文件中的書寫順序,可以將初始化塊置于成員聲明前,那么先執(zhí)行的將是初始化塊,將上面的代碼稍稍變動一下就可以驗證這一點。)  ?! ?。  ,執(zhí)行構(gòu)造方法體中的其它內(nèi)容。  如果根據(jù)以上java規(guī)范中給出的順序也可以合理的解釋程序的輸出結(jié)果,那么如何親眼看到是規(guī)范中的順序而不是以上根據(jù)程序的輸出推斷的順序呢?  下面就使用JDK自帶的javap工具看看實際的順序,這個工具是一個根據(jù)編譯后的字節(jié)碼生成一份字節(jié)碼的助記符格式的文檔的工具,就像根據(jù)機(jī)器碼生成匯編代碼那樣?! 》淳幾g:javap c classpath . Child  輸出的結(jié)果是(已經(jīng)經(jīng)過標(biāo)記,交替使用黑體和斜體表示要講解的每一塊):   Compiled from   class Child extends Parent {  int cm1。  int cm2?! nt cm3?! ther co?! ublic static int scm1?! tatic {}?! hild()。  Child(int)?! nt cmethod()?! tatic void staticmethod()。  }  Method static {}  0 bipush 10  2 putstatic 22 Field int scm1  5 getstatic 20 Field out  8 ldc 5 String Child39。s static initialize block  10 invokevirtual 21 Method void println()  13 return  Method Child()  0 aload_0  1 invokespecial 14 Method Parent()  4 aload_0  5 bipush 10  7 putfield 16 Field int cm2  10 aload_0  11 aload_0  12 invokevirtual 18 Method int cmethod()  15 putfield 17 Field int cm3  18 getstatic 20 Field out  21 ldc 2 String Child39。s instance initialize block  23 invokevirtual 21 Method void println()  26 aload_0  27 new 8 Class Other  30 dup  31 invokespecial 13 Method Other()  34 putfield 19 Field Other co  37 getstatic 20 Field out  40 ldc 1 String Child39。s default constructor  42 invokevirtual 21 Method void println()  45 return  Method Child(int)  0 aload_0  1 invokespecial 12 Method Child()  4 aload_0  5 iload_1   6 putfield 15 Field int cm1  9 getstatic 20 Field out  12 ldc 4 String Child39。s selfdefine constructor  14 invokevirtual 21 Method void println()  17 return  Method int cmethod()  0 getstatic 20 Field out  3 ldc 3 String Child39。s method  5 invokevirtual 21 Method void println()  8 iconst_3  9 ireturn  Method void staticmethod()  0 getstatic 20 Field out  3 ldc 6 String Child39。s staticmethod  5 invokevirtual 21 Method void println()  8 return   請仔細(xì)瀏覽一下這個輸出并和源代碼比較一下。  下面解釋如何根據(jù)這個輸出得到類實例的實際的構(gòu)造順序,在開始說明前先解釋一下輸出的語句的格式,語句中最前面的一個數(shù)字是指令的偏移值,這個我們在此可以不管,第二項是指令助記符,可以從字面上大致看出指令的意思?! ±?getstatic 指令將一個靜態(tài)成員壓入一個稱為操作數(shù)堆棧(后續(xù)的指令就可以引用這個數(shù)據(jù)結(jié)構(gòu)中的成員)的數(shù)據(jù)結(jié)構(gòu),而 invokevirtual 指令是調(diào)用java虛擬機(jī)方法,第三項是操作數(shù)(號后面跟一個數(shù)字,實際上是類的成員的標(biāo)記),有些指令沒有這一項,因為有些指令如同匯編指令中的某些指令一樣是不需要操作數(shù)的(可能是操作數(shù)是隱含的或者根本就不需要),這是java中的一個特色?! ∪绻阒苯訖z查字節(jié)碼,你會看到成員信息沒有直接嵌入指令而是像所有由java類使用的常量那樣存儲在一個共享池中,將成員信息存儲在一個常量池中可以減小字節(jié)碼指令的大小,因為指令只需要存儲常量池中的一個索引而不是整個常量?! ⌒枰f明的是常量池中的項目的順序是和編譯器相關(guān)的,因此在你的環(huán)境中看到的可能和我上面給出的輸出不完全一樣,第四項是對前面的操作數(shù)的說明,實際的字節(jié)碼中也是沒有的,根據(jù)這個你能很清楚的得到實際上使用的是哪個成員或者調(diào)用的是哪個方法,這也是javap為我們提供的便利。  說完上面這些你現(xiàn)在應(yīng)該很容易看懂上面的結(jié)果和下面將要敘述的內(nèi)容了。其它更進(jìn)一步的有關(guān)java字節(jié)碼的信息請自己查找資料。  先看看最開始的部分,很像一個標(biāo)準(zhǔn)的c++類的聲明,確實如此。成員聲明的后面沒有了成員初始化賦值語句和初始化塊,那么這些語句何時執(zhí)行的呢?先不要急,繼續(xù)往下看。  第二塊,是一個Method static {},對比看看第一部分,它被處理為一個靜態(tài)的方法(從前面的Method可以看出),這就是源代碼中的靜態(tài)初始化塊,從后面的語句可以看出它執(zhí)行的就是 (Child39。s static initialize block)語句,由于這個方法是沒有方法名的,所以它不能被顯式的調(diào)用,它在何處調(diào)用后面會有敘述?! 〉谌龎K,缺省構(gòu)造方法的實現(xiàn),這是本文的重點,下面詳細(xì)講解。由于源代碼中的缺省構(gòu)造方法沒有顯式調(diào)用this 方法,因此沒有this調(diào)用(對比看看下一塊的有參的構(gòu)造方法的前兩句),同時也沒有顯式的super調(diào)用,那么隱式調(diào)用父類的缺省構(gòu)造方法,也就是前兩條語句(主要是語句invokespecial 14 Method Parent()),它調(diào)用父類的構(gòu)造方法,和這個類的構(gòu)造相似(你可以使用javap ?c ?classpath . Parent反編譯父類的字節(jié)碼看看這個類的構(gòu)造過程);緊接著的是執(zhí)行源代碼中的第一條初始化賦值語句cm2=10(即接下來的三條語句,主要是 bipush 10和putfield 15 Field int cm2,此處回答了第一塊中的疑問,即初始化賦值語句到哪兒去了。);接下來是執(zhí)行cm3=cmethod()(接下來的四條語句);(Child39。s instance initialize block)(接下來的三條語句);java規(guī)范內(nèi)部約定的內(nèi)容至此執(zhí)行完畢,開始執(zhí)行構(gòu)造方法的方法體中的內(nèi)容,即co=new Other()(接下來的五條語句)(Child39。s default constructor)(接下來的三條語句),最后方法執(zhí)行完畢返回(最后一條語句return)?! ∈O碌膸讐K相信應(yīng)該不用解釋了吧,有參構(gòu)造方法調(diào)用無參構(gòu)造方法然后執(zhí)行自己的方法體,成員方法cmethod執(zhí)行一條打印語句然后返回一個常量3,靜態(tài)方法staticmethod執(zhí)行一條打印語句?! ×硗庑枰f明一下的是你可以將有參構(gòu)造方法中的this調(diào)用去掉,然后看看反編譯的結(jié)果,你會發(fā)現(xiàn)兩個構(gòu)造方法非常的類似,如果你將兩個構(gòu)造方法的內(nèi)容改為一樣的,那么反編譯后的生成也將是同樣的。從這個可以說明本文開始的構(gòu)造順序的說明中構(gòu)造方法中this調(diào)用的判斷是在編譯階段就完成的,而不是在運行階段(說明中的意思好像是這個判斷是在運行時進(jìn)行的)?! ?gòu)造過程的另一個細(xì)節(jié)你可能還不相信,就是順序中的第二條關(guān)于非靜態(tài)成員的賦予缺省初始值(內(nèi)存分配部分無法考證,這是java虛擬機(jī)自動完成的),這個你可以通過在子類Child的cmethod方法的最開始用 (cm3)打印cm3的值(輸出為0,其它類型成員的值可以通過類似的方法得到)?! ∠旅鎭碇v解另一個還沒有解決的問題:靜態(tài)成員初始化和靜態(tài)初始化塊的執(zhí)行是在何時完成的?這個可以通過一個小小的試驗推斷得到:是在第一次使用該類對象時進(jìn)行的(注意是類對象而不是類實例,對于類的公有靜態(tài)成員可以直接通過類名進(jìn)行訪問,并不需要生成一個類實例,這就是一次類對象的使用而非類實例的使用,如果在生成第一個類實例前沒有使用過該類對象,那么在構(gòu)造第一個類實例前先完成類對象的構(gòu)造(即完成靜態(tài)成員初始化以及執(zhí)行靜態(tài)初始化塊),然后再執(zhí)行以上類實例的構(gòu)造過程),試驗的步驟如下:  ,()和c= new Child(10)都注釋掉(不要刪除,后面還需要用到這兩個語句),編譯運行程序,輸出將只有program start和program end,這說明沒有使用類對象也沒有生成類實例時不進(jìn)行靜態(tài)成員的構(gòu)造。  ()的注釋取消,編譯運行后輸出多了父類和子類的靜態(tài)初始化塊部分的執(zhí)
點擊復(fù)制文檔內(nèi)容
環(huán)評公示相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖片鄂ICP備17016276號-1