快捷搜索:

基础却又没多少人做对的面向对象面试题

2019-10-08 作者:2019精准正版资料   |   浏览(79)

这段日子着实开采本身更加的懒了,即便今后稍微晚了,然而内疚完事后,依然得更新每种周一篇的面试题,找了数不胜数面试题,发掘有一些很基础的就没须要分享出去,最终找了这么一篇经典的面试题,一开端自身也还真做错了,话比比较少说。来看下 二〇一四 蜂窝网的 JAVA 程序猿的面试题

public class Base{ private String baseName = "base"; public Base() { callName(); } public void callName() { System. out. println; } static class Sub extends Base { private String baseName = "sub"; public void callName() { System. out. println  ; } } public static void main(String[] args) { Base b = new Sub(); }}

求这段程序的输出值?

因为笔者一开端笔者也做错了那道题,由此不佳写一从头的商量思路,我们就用最直白的艺术来看下答案是何许?

向来把程序运转,看输出的结果:

图片 1一贯运维输出结果为null.png

能够看来,结果为 null 。为何吧?

咱俩在条分缕析的观察一下主题素材,能够理解,那道题无非就是阅览大家多少个知识点,第一,类的加运载飞机制以及类的开端化进程;第二,承袭的有关文化,在那之中这里提到到子类继承父类的时候,同名的属性不会覆盖父类,只是会将父类的同名属性掩饰;第三,多态性,多态性就是让贯彻与接口进行分离,在那道难点中,在父类的构造方法中调用了虚函数变成多态

居然大家地点就关系那个难点正是洞察大家八个知识点,那么大家就依靠难点对那四个知识点举行逐项击破

1.类加载的编写制定和程序运营的相继

大家通过 Debug 能很好的刺探程序的运转顺序,因为 new 了三个 Sub 对象,且 Sub 类中并未有重写构造函数,由此会调用父类的构造函数,父类 Base 的构造函数中调用了 callName 方法,因而就在父类的 callName 方法中的输出语句打五个断点,最终因为子类的 Sub 重写了 callName 方法, 因而也在子类中重写的 callName 方法中打二个断点。最终经过 debug 咱们能够看出程序的运营顺序

图片 2Debug查看运转的顺序.png

知道了程序的运营顺序之后,大家还需精通一个知识点,那就是类的实例变量的发轫化进度,也正是主题材料中成员变量 baseName 的初始化进程。

咱俩都通晓,一个类一旦被加载连接早先化,它就可以随时被运用了,程序能够访谈它的静态字段,调用静态方法,恐怕创制它的实例。在 JAVA 程序中类能够被醒目恐怕隐含地实例化有各类门路:分明使用 new 操作符;调用 Class 只怕 Constructor 对象的 newInstance调用别样现存对象的 clone也许经过 objectInputStream 类的 getObject() 方法反类别化。虚构机创制一个新的实例时,都亟待在堆中为保留对象的实例分配内部存储器。全数在对象的类二月它的父类中声称的变量(包涵隐形的实例变量)都要分配内部存款和储蓄器。一旦虚拟机为新的靶子打算好堆内部存储器,它马上把实例变量初叶化为私下认可的伊始值。

2.继承

主题素材中 Sub 类承接了 Base 类,关于持续,三个主导全部人都晓得的知识点,可是这里照旧贴出来

Java保障了二个指标被初阶化前其父类也必需被初阶化。有上边机制来确认保障:Java强制供给任何类的构造函数中的第一句必得是调用父类构造函数或许是类中定义的别的构造函数。若无构造函数,系统加多暗中同意的无参构造函数,要是大家的构造函数中并未有展示的调用父类的构造函数,那么编译器自动生成一个父类的无参构造函数

3.多态

父类中的构造函数调用了 callName 方法,在难题中是透过 new Sub() 对象,由此调用的是子类 Sub 类中的 callName 方法,因而当前的 this 是指 Sub 类中的。

好了,最后大家依据运营顺序分析任何进程1.Base b = new Sub();

在 main 方法中扬言父类变量b对子类的援引,JAVA类加载器将Base,Sub类加载到JVM;约等于水到渠成了 Base 类和 Sub 类的初叶化

2.JVM 为 Base,Sub 的的成员开发内部存款和储蓄器空间且值均为 null

在初阶化 Sub 对象前,首先 JAVA 设想机就在堆区开发内部存款和储蓄器并将子类 Sub 中的 baseName 和父类 Base 中的 baseName均赋为 null ,至于为什么 Base 类中的 baseName 为何会被隐形,上面包车型大巴知识点也早已表明,便是子类承袭父类的时候,同名的品质不会覆盖父类,只是会将父类的同名属性遮盖

3.调用父类的无参构造

调用 Sub 的构造函数,因为子类未有重写构造函数,暗中认可调用无参的构造函数,调用了 super() 。

4.callName 在子类中被重写,由此调用子类的 callName();

调用了父类的构造函数,父类的构造函数中调用了 callName 方法,此时父类中的 baseName 的值为 base,不过子类重写了 callName 方法,且 调用父类 Base 中的 callName 是在子类 Sub 中调用的,由此当前的 this 指向的是子类,也等于说是促成子类的 callName 方法

5.调用子类的callName,打字与印刷baseName

实际上在new Sub()时,实际执行进程为:

public Sub(){ super(); baseName = "sub"; }

足见,在 baseName = "sub" 推行前,子类的 callName() 已经实施,所以子类的 baseName 为暗中同意值状态 null 。

时光也很晚了(2014年七月二日01:35:54),最终交给八个知识点就睡了

构造器的最早化顺序大概是:父类静态块 ->子类静态块 ->父类初阶化语句 ->父类构造函器 ->子类最早化语句 子类构造器。

本文由正版香港马报免费资料发布于2019精准正版资料,转载请注明出处:基础却又没多少人做对的面向对象面试题

关键词: