`
seara
  • 浏览: 622805 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java.lang.Object是如何成为默认父类的

阅读更多
本文为原创,如需转载,请注明作者和出处,谢谢!

经常有
Java初学者会问为什么一个没有父类的Java类会自动从java.lang.Object类继承。如下面是一个普通的Java类:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->publicclassTest//从Object类继承
{
publicstaticvoidmain(String[]args)
{
System.out.println(
newTest().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文件后,会看到如下的代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->publicclassTestextendsjava.lang.Object{
publicTest();
publicstaticvoidmain(java.lang.String[]);
}

再使用下面的命令来得到bytecode代码:

javap -c Test >Test1.txt

打开Test1.txt后,会看到如下的代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->publicclassTestextendsjava.lang.Object{
publicTest();
Code:
0:aload_0
1:invokespecial#8;//Methodjava/lang/Object."<init>":()V
4:return

publicstaticvoidmain(java.lang.String[]);
Code:
0:getstatic#16;//Fieldjava/lang/System.out:Ljava/io/PrintStream;
3:new#1;//classTest
6:dup
7:invokespecial#22;//Method"<init>":()V
10:invokevirtual#23;//Methodjava/lang/Object.toString:()Ljava/lang/String;
13:invokevirtual#27;//Methodjava/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#代码:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->usingSystem;

namespaceConsoleApplication1
{
classTest
{
staticvoidMain(string[]args)
{
Console.WriteLine(
newTest().ToString());
}
}
}

使用ildasm.exe将上面的代码反编译后,得到的MSIL代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->.classprivateautoansibeforefieldinitConsoleApplication1.Test
extends[mscorlib]System.Object
{
}
//endofclassConsoleApplication1.Test

从上面的代码可以清楚地看到,Test类已经有一个System.Object作为父类了。




国内最棒的Google Android技术社区(eoeandroid),欢迎访问!

《银河系列原创教程》发布

《Java Web开发速学宝典》出版,欢迎定购

分享到:
评论

相关推荐

    Java练习题(试卷)

    在Java语言中,有一个类是所有类或接口的父类,这个类的名称是 java.lang.Object 。 4.在Java中所实现的二维数组,实际上是由一维数组构成的 数组 。 5.在Java中,字符串是作为 对象 出现的。 6.接口可以看作是仅...

    Object类,Objects类,Date类,DateFormat类,Calendar类,Math类,system类

    所在包: java.lang.Object 概念: 所有类的根类。 任何类都会直接或间接的继承Object类 一个类如果没有明确的写出extends 父类,默认的爹就是Object类 方法: toString 如果直接输出对象名,没有重写Object类中的to...

    java常用工具类的使用

    该类的大部分构造器和方法都已经过时,但是该类使用非常方便,因此目前使用还很普遍,该类的另一个主要功能是,在数据库操作中,它允许将毫秒值表示为SQL DATE值,是数据库操作中java.sql.Date的父类。关于数据库...

    java 面试题 总结

    java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 3、int 和 Integer 有什么区别 Java 提供两种不同的类型:引用类型和原始类型(或内置...

    JAVA面试题最全集

    一、Java基础知识 1.Java有那些基本数据类型,String是不是基本数据类型,他们有何区别。 2.字符串的操作: 写一个方法,实现字符串的反转,如:输入abc,输出cba 写一个方法,实现字符串的替换,如:输入...

    android反编译(dex2jar.zip)

    5. 修复读取dex中java/lang/Object类时其父类是null导致的一个NPE问题 6. 提高异常信息的可读性 Fixes issue 44 反编译步骤 1、把 class.dex 拷贝到 dex2jar.bat 所在目录,直接拖动 class.dex 到 dex2jar.bat,...

    java经典面试2010集锦100题(不看你后悔)

    C) 程序能通过编译,运行时将打印出0/0,因为在Java中int型变量day和month默认为0。 D) 以上说法都不正确。 题目10:c 下面关于继承的描述正确的一项是:(选择1项) A) 子类继承父类,那么子类将继承父类的所有...

    Hibernate注释大全收藏

    具体的java.sql.Clob, Character[], char[] 和 java.lang.String 将被持久化为 Clob 类型. java.sql.Blob, Byte[], byte[] 和 serializable type 将被持久化为 Blob 类型。 @Lob public String getFullText() { ...

    超级有影响力霸气的Java面试题大全文档

     java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 6、int 和 Integer 有什么区别  Java 提供两种不同的类型:引用类型和原始类型(或...

    【05-面向对象(下)】

    •在定义接口时,接口里可以包含成员变量(只能是常量),方法(只能是抽象实例方法、类方法或默认方法),内 部类(包括内部接口、枚举类  –常量都是:public static final修饰  –方法都是:public abstract ...

    ssh(structs,spring,hibernate)框架中的上传下载

    7. <id name="fileId" type="java.lang.String" column="FILE_ID"> 8. <generator class="uuid.hex"/> 9. 10. 11. type="org.springframework.orm.hibernate3.support.BlobByteArrayType" 12. column="FILE_...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    书名:《Java开发实战1200例(第I卷)》(清华大学出版社.李钟尉,陈丹丹) PDF格式扫描版,全书分为24章,共817页。2011年1月出版。 全书压缩打包成4部分,这是第3部分 注:本系列图书的第I、II卷再版时均相应改名为...

    JSTL详细标签库介绍

    如找不到,那么:&lt;BR&gt;&lt;BR&gt;命令行APP/控制台APP(不基于GUI),当异常不能被“捕获”,那么该程序会运行默认异常处理程序,退出JAVA,若Applet或基于GUI的APP,当一个异常未被“捕获”,GUI在运行默认异常处理程序...

    javaSE代码实例

    3.10 常用数学工具包——java.lang.Math类 39 3.10.1 数学常量 39 3.10.2 常用数学函数 40 3.11 小结 41 第4章 流程控制——Java世界的航行舵手 42 4.1 if条件语句 42 4.1.1 简略形式 42 4.1.2 完全...

Global site tag (gtag.js) - Google Analytics