记一道 Java 综合面试题

栏目: Java · 发布时间: 6年前

内容简介:记一道 Java 综合面试题

昨天看了一道关于异常处理的题: 由一道 Java finally 执行顺序的题引发的思考 ,今天又在牛客网看到一道更深的题,这次加上了一个子父类继承关系的知识点。

原题

public class Test {
    public static void main(String[] args) {
        System.out.println(new B().getValue());
    }

    static class A {
        protected int value;

        public A(int v) {
            setValue(v);
        }
        public void setValue(int value) {
            this.value = value;
        }
        public int getValue() {
            try {
                value++;
                return value;
            } catch (Exception e) {
                System.out.println(e.toString());
            } finally {
                this.setValue(value);
                System.out.println(value);
            }
            return value;
        }
    }
    static class B extends A {
        public B() {
            super(5);
            setValue(getValue() - 3);
        }
        public void setValue(int value) {
            super.setValue(2 * value);
        }
    }
}

题解

这道题考的就是代码执行顺序,比较直观的方法是使用单步调试,来一起看下执行过程吧:

首先从 main 方法开始执行,new 了一个对象 B,没什么可说的。

记一道  <a href='https://www.codercto.com/topics/22013.html'>Java</a>  综合面试题

接下来执行到了 B 类的构造方法,也没什么问题。

记一道 Java 综合面试题

然后执行到了父类的有参构造。

记一道 Java 综合面试题

这里要执行 setValue(v) 方法了,那么这里的 setValue() 方法应该是执行 B 类的,还是 A 类的呢?

记一道 Java 综合面试题

其实这个结果是有些出乎我意料, 怎么会执行子类 B 的 setValue() 方法呢?

因为这里正在执行 B 的构造方法中,所以调用的方法就默认是 B 的,当 B 中没有,才会去找它的父类 A 中的方法。

下一步是 super.setValue() ,这里明确指明了调用父类的方法,所以应该没啥问题。

记一道 Java 综合面试题

嗯,这里将 A 类的 value 属性设值为 10。

记一道 Java 综合面试题

然后还回到 A 的构造方法中。

记一道 Java 综合面试题

再回到 B 的构造方法中,接下来应该调用 getValue

记一道 Java 综合面试题

由于子类中没有,所以调用父类的 getValue 方法。

记一道 Java 综合面试题

接下来将 A 中的 value 自增 1,然后到了 return value ,由于下面还有 finally 语句块,所以先执行 finally 语句块,再返回。

记一道 Java 综合面试题

又到了一个 setValue 方法,那么这里调用的是子类 B 的,还是父类 A 的呢?

记一道 Java 综合面试题

可以看到,这里调用的是子类 B 的构造方法,还是刚才的那个结论:

因为这里正在执行 B 的构造方法中,所以调用的方法就默认是 B 的,当 B 中没有,才会去找它的父类 A 中的方法。

接下来应该会执行 super.setValue() 也就是它父类 A 的 setValue() 方法。

记一道 Java 综合面试题

这里会将 A 的 value 值设为 22。

记一道 Java 综合面试题

然后回到刚才的方法里,准备打印 value 值,打印后一共会回到 try 里的 return 语句。

记一道 Java 综合面试题

这里虽然 value 的值是 22,但是刚才执行 finally 语句块之前就已经将 reutrn 的值确定了,也就是 11,详细参见 由一道 Java finally 执行顺序的题引发的思考

记一道 Java 综合面试题

回到刚才的调用,由于上一步返回的值是 11,所以这里应该是调用的 setValue(11- 3); ,这里调用的是 B 的方法。

记一道 Java 综合面试题

接下来又要执行 super.setValue() 了,也就是父类的 setValue() 方法。

记一道 Java 综合面试题

这里会将 A 类的的 value 值从 22 改为 16.

记一道 Java 综合面试题

然后 B 类的构造方法执行完了,回到 main 方法,准备调用 getValue() 方法,因为 B 类没有,所以会调用其父类 A 的。

记一道 Java 综合面试题

这里将 A 的 value 值自增1,变为 17 ,然后最为 return 的最终返回结果后,执行 finally 语句中的内容。

记一道 Java 综合面试题

这里又到了 setValue 的抉择,到底执行哪个类的呢?

记一道 Java 综合面试题

还是调到了 B 类中,因为 main 方法里调用的是 new B().xxx 方法,所以这里的 this 代表的是 B 类。

接下来这里指定 super.setValue() ,调用父类的方法,将父类的 value * 2 ,然后回到 finally 块中。

记一道 Java 综合面试题

然后调用输出语句,输出结果应为 34,输出后会返回到 try 里的 return 语句中。

记一道 Java 综合面试题

那么这里的 return 值应该是刚才已经确定的值,也就是 17,然后回到 main 方法

记一道 Java 综合面试题

这里返回的是 17,所以输出 17,程序结束。

记一道 Java 综合面试题

总结

这道题很长,不过也只是靠两个知识点:

  1. 子类与父类之间的调用关系: 动态分派 在调用new B()时调用A的构造器时和super.getValue()时的setValue(int value)方法是根据隐式对象的实际类型来确定的。只有实际类型未重写该方法时,才按照继承层次由下往上查找。这个可以参阅《深入理解JVM》 的“分派”一节。
  2. try-catch-finally 的执行顺序,详见: 由一道 Java finally 执行顺序的题引发的思考

理解了这两个知识点。这要脑子清醒,一步一步做,应该没什么问题。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

ES6标准入门(第3版)

ES6标准入门(第3版)

阮一峰 / 电子工业出版社 / 2017-9 / 99.00

ES6是下一代JavaScript语言标准的统称,每年6月发布一次修订版,迄今为止已经发布了3个版本,分别是ES2015、ES2016、ES2017。本书根据ES2017标准,详尽介绍了所有新增的语法,对基本概念、设计目的和用法进行了清晰的讲解,给出了大量简单易懂的示例。本书为中级难度,适合那些已经对JavaScript语言有一定了解的读者,可以作为学习这门语言最新进展的工具书,也可以作为参考手册......一起来看看 《ES6标准入门(第3版)》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具