<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數據加載中……

    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的實現細節。只要思考一下對于這種虛擬機程序的原理即可。一般對于這種靠虛擬機運行的語言(如JavaC#等)會有兩種方法處理默認繼承問題。

    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 銀河使者 閱讀(2772) 評論(0)  編輯  收藏 所屬分類: java 原創

    主站蜘蛛池模板: 亚洲人成综合在线播放| 亚洲&#228;v永久无码精品天堂久久| 亚洲精品视频在线观看你懂的| 亚洲精品无码专区在线播放| 日韩亚洲国产高清免费视频| 亚洲最大中文字幕| 曰曰鲁夜夜免费播放视频| 亚洲一卡2卡4卡5卡6卡残暴在线| 无码国产精品一区二区免费虚拟VR| 亚洲人成在线中文字幕| 久久精品网站免费观看 | 99久久成人国产精品免费| 亚洲日韩av无码| 国产精品区免费视频| 亚洲色欲色欲综合网站| 69式国产真人免费视频| 亚洲私人无码综合久久网| 日本免费一二区在线电影| 黄色一级视频免费观看| 亚洲乱码中文字幕综合| 久久久久国产精品免费免费不卡| 亚洲性天天干天天摸| 4虎永免费最新永久免费地址| 麻豆狠色伊人亚洲综合网站| 免费看无码自慰一区二区| jizz在线免费观看| 亚洲色成人网一二三区| 四虎成人免费网站在线| 日日摸夜夜添夜夜免费视频| 亚洲精品国产字幕久久不卡| 在线观看免费视频资源| 亚洲国产成人AV网站| 亚洲AV第一页国产精品| 老司机永久免费网站在线观看| 日日摸夜夜添夜夜免费视频| 久久久亚洲欧洲日产国码aⅴ | 亚洲电影日韩精品| 久久久久久影院久久久久免费精品国产小说| 亚洲噜噜噜噜噜影院在线播放| 免费一级毛片免费播放| 最近免费中文字幕大全免费|