- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
每个人都知道Object是父类(super class),所有不扩展任何其他类的类都会隐式扩展Object类。我想知道这个隐式扩展是如何工作的。
最佳答案
我们有一个文件 child.java
class Child
{
public static void main(String[] args)
{
System.out.println(new Child().toString());
}
}
从上面的代码我们可以看到,其实Child类的父类是Object,所以我们可以在Child中使用Object类的public或者protected资源,比如toString方法。那么Java编译器和JVM是如何做到的呢?
知道这个原因并不需要真正了解JVM的实现细节。想想这个虚拟机程序的原理就知道了。一般来说,对于这类运行在虚拟机上的语言(例如Java),有两种方法可以处理默认继承问题。
在编译源代码阶段,如果遇到没有父类的类,编译器会给它分配一个默认的父类(通常是Object),而如果虚拟机处理该类,因为该类已经有默认的父类,因此VM仍将以通常的方式处理每个类。在这种情况下,从编译的二进制角度来看,所有类都将有一个父类。
编译器仍然使用实际代码进行编译,不会进行额外的处理。如果一个类没有显式继承其他类,并且编译后的代码仍然没有父类。那么当虚拟机运行二进制代码时,如果遇到没有父类的类,则自动将该类视为Object类的子类(一般默认父类是Object)。
<从上面两种情况可以看出,第一种情况是一篇关于编译器的文章,即当没有父类时,编译器在编译时自动为其分配一个父类。第二种情况是在虚拟机上做文章,即默认的父类是虚拟机添加的。
那么Java又是哪种情况呢?事实上,我们可以通过使用javap来得到这个答案。只要找一个反编译工具,反编译.class文件,看看编译器是如何编译的。以上面的代码为例。如果是第一种情况,即使Child没有父类,因为编译器自动给Child添加了一个Object父类,但是反编译后得到的源码中的Child类是继承自Object类的。如果不是这种情况,则采用第二种情况。
首先将child.java编译为Child.class
%javac child.java
现在我们使用JDK自带的反编译工具javap来反编译Child.class,首先执行以下命令:
% javap -c Child
在命令之后,我们的字节码以某种可读的形式出现,我们可以在其中识别我们的方法、整数、命令和字符串
class Child {
Child();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: new #3 // class Child
6: dup
7: invokespecial #4 // Method "<init>":()V
10: invokevirtual #5 // Method java/lang/Object.toString:()Ljava/lang/String;
13: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
}
从上面这段代码可以看出,Test继承自Object,因此可以得出Java是属性的第一种情况,即编译器指定Object为其默认父类没有父类的类。
关于java - 扩展对象隐式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58990173/
我是一名优秀的程序员,十分优秀!