隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導航

          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          公告

          關注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務

          代理網站

          關注的網站

          協議

          喜歡的Blog

          國內廣告平臺

          圖書出版

          在線培訓

          開發工具

          微博客戶端

          手機鈴聲

          操作系統

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統

          數學

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學習

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1974651
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

          java.lang.Object是如何成為默認父類的

          本文為原創,如需轉載,請注明作者和出處,謝謝!

          經常有
          Java初學者會問為什么一個沒有父類的Java類會自動從java.lang.Object類繼承。如下面是一個普通的Java類:

          public class Test    // 從Object類繼承
          {
              
          public static void main(String[] args)
              {
                  System.out.println(
          new Test().toString());
              }
          }

          從上面的代碼可以看出,實際上,Test類的父類就是Object,因此,在Test中可以使用Object類的publicprotected資源,如toString方法。那么Java編譯器和JVM到底是如何做的呢?

          了解這個原因其實并不需要知道JVM的實現細節。只要思考一下對于這種虛擬機程序的原理即可。一般對于這種靠虛擬機運行的語言(如Java、C#等)會有兩種方法處理默認繼承問題。

          1. 在編譯源代碼時,當遇到沒有父類的類時,編譯器會將其指定一個默認的父類(一般為Object),而虛擬機在處理到這個類時,由于這個類已經有一個默認的父類了,因此,VM仍然會按著常規的方法來處理每一個類。對于這種情況,從編譯后的二進制角度來看,所有的類都會有一個父類。

          2. 編譯器仍然按著實際代碼進行編譯,并不會做額外的處理。如果一個類沒有顯式地繼承于其他的類,編譯后的代碼仍然沒有父類。然后由虛擬機運行二進制代碼時,當遇到沒有父類的類時,就會自動將這個類看成是Object類的子類(一般這類語言的默認父類都是Object)。

          從上面兩種情況可以看出,第1種情況是在編譯器上做的文章,也就是說,當沒有父類時,由編譯器在編譯時自動為其指定一個父類。第2種情況是在虛擬機上做文章,也就是這個默認的父類是由虛擬機來添加的。那么Java是屬性哪一種情況呢?其實這個答案很好得出。只需要隨便找一個反編譯工具,并.class文件進行反編譯即可得知編譯器是如何編譯的。就以上面代碼為例,如果是第1種情況,就算Test沒有父類,但由于編譯器已經為Test自動添加了一個Object父類,因此,在反編譯后得到的源代碼中的Test類是從Object類繼承的。如果沒是這種情況,那么就是第2種情況。

          現在我們使用JDK帶的反編譯工具javap來反編譯Test.class,先執行下面的命令:

          javap Test > Test.txt

          打開Test.txt文件后,會看到如下的代碼:

          public class Test extends java.lang.Object{
              
          public Test();
              
          public static void main(java.lang.String[]);
          }

          再使用下面的命令來得到bytecode代碼:

          javap -c Test >Test1.txt

          打開Test1.txt后,會看到如下的代碼:

          public class Test extends java.lang.Object{
          public Test();
            Code:
             
          0:    aload_0
             
          1:    invokespecial    #8//Method java/lang/Object."<init>":()V
             4:    return

          public static void main(java.lang.String[]);
            Code:
             
          0:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
             3:    new    #1//class Test
             6:    dup
             
          7:    invokespecial    #22//Method "<init>":()V
             10:    invokevirtual    #23//Method java/lang/Object.toString:()Ljava/lang/String;
             13:    invokevirtual    #27//Method java/io/PrintStream.println:(Ljava/lang/String;)V
             16:    return
          }

              從上面兩段代碼可以看出,Test已經從Object繼承了,因此,可以斷定Java是屬性第1種情況,也就是說由編譯器為沒有父類的類指定了Object作為其默認父類。如果讀者還不確定,可以直接打開Test.class,看看里面有沒有Object,圖1Test.class的十六進制代碼:



                                                          圖1

             大家可以看到,Java編譯器已經為Test指定了一個默認的Object類作為其父類。目前大多數基于虛擬器的語言都是采用的第1種方法來處理默認父類的,如下面的C#代碼:

          using System;

          namespace ConsoleApplication1
          {
              class Test
              {
                 
          static void Main(string[] args)
                  {
                      Console.WriteLine(
          new Test().ToString());
                  }
              }
          }

           使用ildasm.exe將上面的代碼反編譯后,得到的MSIL代碼如下:

          .class private auto ansi beforefieldinit ConsoleApplication1.Test
                 extends [mscorlib]System.Object
          {
          // end of class ConsoleApplication1.Test

              從上面的代碼可以清楚地看到,Test類已經有一個System.Object作為父類了。






          Android開發完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2008-05-06 15:14 銀河使者 閱讀(2777) 評論(0)  編輯  收藏 所屬分類: java 、 原創

          主站蜘蛛池模板: 兰考县| 彭山县| 九江市| 甘肃省| 凤城市| 海兴县| 新巴尔虎左旗| 汉沽区| 彝良县| 太仓市| 余姚市| 闽清县| 卢氏县| 当涂县| 昭平县| 黄石市| 江阴市| 平阳县| 抚顺县| 阜城县| 库伦旗| 嘉黎县| 平度市| 阜南县| 本溪市| 双牌县| 昌邑市| 石泉县| 双辽市| 景泰县| 桓仁| 石台县| 筠连县| 阿克苏市| 庄河市| 康平县| 黎川县| 祁连县| 吉林市| 江源县| 保定市|