当前位置: 首页 > news >正文

2015携程JAVA工程师笔试题(基础却又没多少人做对的面向对象面试题)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

题目


public class Base
{
    private String baseName = "base";
    public Base()
    {
        callName();
    }

    public void callName()
    {
        System. out. println(baseName);
    }

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

 

求这段程序的输出值?

二、解题

因为本身一开始我也做错了这道题,因此不好写一开始的思考思路,我们就用最直接的方法来看下答案是什么?

直接把程序运行,看输出的结果:

直接运行输出结果为null.png

可以看到,结果为 null 。为什么呢?

我们在仔细的观察一下题目,可以知道,这道题无非就是考察我们三个知识点,第一,类的加载机制以及类的初始化过程;第二,继承的相关知识,其中这里涉及到子类继承父类的时候,同名的属性不会覆盖父类,只是会将父类的同名属性隐藏;第三,多态性,多态性就是让实现与接口进行分离,在这道题目中,在父类的构造方法中调用了虚函数造成多态

竟然我们上面就提到这个题目就是考察我们三个知识点,那么我们就根据题目对这三个知识点进行逐一击破

1.类加载的机制和程序运行的顺序

我们通过 Debug 能很好的了解程序的运行顺序,因为 new 了一个 Sub 对象,且 Sub 类中没有重写构造函数,因此会调用父类的构造函数,父类 Base 的构造函数中调用了 callName 方法,因此就在父类的 callName 方法中的输出语句打一个断点,最后因为子类的 Sub 重写了 callName 方法, 因此也在子类中重写的 callName 方法中打一个断点。最后通过 debug 我们可以看出程序的运行顺序

Debug查看运行的顺序.png

知道了程序的运行顺序之后,我们还需知道一个知识点,那就是类的实例变量的初始化过程,也就是题目中成员变量 baseName 的初始化过程。

我们都知道,一个类一旦被加载连接初始化,它就可以随时被使用了,程序可以访问它的静态字段,调用静态方法,或者创建它的实例。在 JAVA 程序中类可以被明确或者隐含地实例化有四种途径:(1)明确使用 new 操作符;(2)调用 Class 或者 Constructor 对象的 newInstance() 方法;(3)调用任何现有对象的 clone() 方法;(4)或者通过 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 。

时间也很晚了(2016年12月27日01:35:54),最后给出一个知识点就睡了

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

转载于:https://my.oschina.net/u/2822116/blog/877028

相关文章:

  • JavaScript服务器推送技术之 WebSocket
  • 在 Windows 上安装Rabbit MQ 指南
  • 20165318 预备作业二 学习基础和C语言基础调查
  • 终极简洁设置tabbar在push到新界面的时候隐藏,返回时显示
  • 06.系统规划
  • 打开mat文件
  • netty如何知道连接已经关闭,socket心跳,双工?异步?
  • Android 线性布局(LinearLayout)相关官方文档 - 指南部分
  • hexo 添加标签
  • 重载()运算符和重载强制类型转换
  • 配置openssh实现sftp远程文件上传
  • 单反相机学习资料
  • 正则表达式
  • Node.js + Express 4.x + MongoDB 构建登录注册(二)
  • VMware NAT模式
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • Angular6错误 Service: No provider for Renderer2
  • express + mock 让前后台并行开发
  • fetch 从初识到应用
  • maven工程打包jar以及java jar命令的classpath使用
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • underscore源码剖析之整体架构
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 解析带emoji和链接的聊天系统消息
  • 什么软件可以剪辑音乐?
  • 使用权重正则化较少模型过拟合
  • 微信支付JSAPI,实测!终极方案
  • 小李飞刀:SQL题目刷起来!
  • Python 之网络式编程
  • zabbix3.2监控linux磁盘IO
  • ​Python 3 新特性:类型注解
  • #pragma multi_compile #pragma shader_feature
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (二)Eureka服务搭建,服务注册,服务发现
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (论文阅读40-45)图像描述1
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (南京观海微电子)——COF介绍
  • (原)Matlab的svmtrain和svmclassify
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • ***通过什么方式***网吧
  • **CI中自动类加载的用法总结
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .apk文件,IIS不支持下载解决
  • .NET CORE 第一节 创建基本的 asp.net core
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET 中创建支持集合初始化器的类型
  • .net分布式压力测试工具(Beetle.DT)
  • .Net组件程序设计之线程、并发管理(一)