素材牛VIP会员
如下代码:子类重写了父类getA()方法,但是这个结果0,是怎么得到的呢?烦请讲解一下!谢谢!!
 go***le  分类:Java代码  人气:1013  回帖:4  发布于6年前 收藏

class Demo1 {

public static class Test1 {
    int a = 1;

    public Test1() {
        System.out.println(getA());
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}

public static void main(String[] args) {

    new Test2();
}

public static class Test2 extends Test1 {
    public int a = 2;

    Test2() {
        super();
        System.out.println(a);
        System.out.println(getA());
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}

}

 标签:java

讨论这个帖子(4)垃圾回帖将一律封号处理……

Lv7 码师
un***oo 职业无 6年前#1

楼主可以看一下 java 的官方文档,内容不多 https://docs.oracle.com/javas...

你这个例子里,继承会覆盖父类方法,super() 是调用父类的构造。因为你 Test2 里已经定义了 getA(),所以第一条打印就是 Test2 里的 getA() 输出的。

第一条 a 是 0,因为此时 Test2 里的 a 还没有开始赋值,要运行完 super() 才会进行 Test2 里 a 的赋值。官方文档里讲了 super() 必须要在第一行调用,其他讲的不是很清楚,楼主可以细看一下其他章节。

后面的两条 a 为 2 都好理解,上面连接的官方文档讲的很清楚

编辑 1:补充第一 a 为 0 的简要执行过程
先执行 super();//此时 a 为 0
super() 完成然后执行 a = 2;
继续执行接下的代码。。。

编辑 2:修改错别字,整理添加相应的官方文档
对于第一 a 为 0 原因,官方文档
http://docs.oracle.com/javase...
章节 12.5 Creation of New Class Instances (新的类实例的创建)
。。。the indicated constructor is processed to initialize the new object using the following procedure: (使用以下过程初始化新对象)

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
  2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
  4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
  5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

一共 5 点,前 3 是构造参数及方式,然后 4 是初始化成员,最后 5 是执行接下来的构造代码。

其他参考信息:
https://stackoverflow.com/que...
该问题和楼主的类似,回答者给出了官方文档

https://stackoverflow.com/que...
其实类似的问题还有,实际上使用 java 这样的问题可能很少遇到,一般不会这么用,也有人说这种编程是一种 bad style

Lv5 码农
sh***ao 职业无 6年前#2

自己动手丰衣足食,请DEBUG跟踪下,然后分析原理

Lv3 码奴
xi***xu 职业无 6年前#3

楼上最后说的不对,super执行之前,a=2已经执行了,你可以用debug模式加断点看执行顺序。为什么是0呢,因为在jvm有个恶心又有意思的特性,在构造器方法执行完之前,访问字段的值,jvm都认为他是初始值。

Lv2 入门
一***句 职业无 6年前#4

自己调试,丰衣足食。
挺有意思的问题,处女答给你了。
既然我调试过了,现在来总结下上面的发言。楼二说的是对的,但是我觉得他说的不够通俗易懂,稍后我来通俗的根据调试运行顺序来解释下。然后楼三说的是完全不对的,我十分怀疑他有没有调试过或者能否拿得出官方说明。
该问题主要涉及知识点:本类的成员变量初始化是在构造方法中的supper()方法调用父类构造方法结束的时候完成的,在supper方法调用结束前,即使给变量定义了初始值也无效,仍会被当作默认值处理。
代码执行中的主要问题体现在super();这句中,后面的System.out.println(a);与System.out.println(getA());我就不解释了。
调用supper();的执行过程:
1、进入Test1的构造方法,此时初始化Test1中的变量a=1
2、执行Test1构造方法中的getA()方法,由于getA被Test2继承并重写,因此这里会去调用Test2种的getA方法
3、进入Test2种的getA()方法,此时由于Test2的构造方法中的supper并没有执行结束,因此此时的Test2中的变量a还没有被初始化赋值,默认值为0,所以这里会返回0
4、Test1中打印getA()的结果0
5、supper()方法执行完毕。
6、初始化Test2中的成员变量a的值为2
7、打印a的值以及本类中的getA()的值,均为2

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取