今天周六,闲着蛋疼就报名参加了公司的一个java比赛,比赛地点某某大厦11楼会议室,想象中应该是能容纳上百人的超大会议室。没成想,到地方一看,只是一个
能容纳六七人的有圆形会议桌的小会议室。不过这仍然不能熄灭BZ因对Java热爱而燃起的满腔激情,于是满怀热情地投入到了比赛答题中。
一般这样的开头都会给人一种欲抑先扬的感觉,BZ这次当然也不例外...刚开始没做几题,就被其中的一个小题目给绊倒了,题目大体是这样的:
有两个类,一个叫BaseHole,如下所示:
public class BaseHole {
public int i = 1;
public BaseHole () {
bh();
}
public void bh () {
System.out.println("Base Hole - bh()");
}
}
另一个类继承了上面的BaseHole,如下所示:
public class UpConstrutorHole extends BaseHole{
public int i = 2;
public void bh () {
System.out.println("UpConstrutorHole - bh()");
}
public void uch () {
System.out.println("UpConstrutorHole - uch()");
}
}
然后运行如下代码:
public class UpConstructorClient {
public static void main(String[] args) {
BaseHole b = new UpConstrutorHole();// 第8行
System.out.println(b.i);// 第9行
        UpConstrutorHole u = (UpConstrutorHole) b;
        u.uch();// 第11行
u.bh();// 第12行
}
}
问8/9/11/12各行代码分别输出的结果是什么:
A.Base Hole - bh()
1
UpConstrutorHole - uch()
UpConstrutorHole - bh()
B.由于向上造型后b中没有uch()方法,所以第10行给b强转类型后仍然没有uch()方法,故第11行编译报错无法执行
C.Base Hole - bh()
2
UpConstrutorHole - uch()
UpConstrutorHole - bh()
D.UpConstrutorHole - bh()
2
UpConstrutorHole - uch()
UpConstrutorHole - bh()
E.UpConstrutorHole - bh()
1
UpConstrutorHole - uch()
UpConstrutorHole - bh()
本着诚实守信的原则,通过分析上题看看自己是否真正的深刻了解向上造型,务必要先在心里想好自己的答案再往下看。 对于向上造型,我之前知道的点基本就是以下两点:
1、向上造型后的对象,能引用的方法为:如果子类的方法满足重写父类方法的要求,则引用子类的方法,否则引的是父类的方法,毕竟对象的类型是父类类型;
2、向上造型,子类的属性不能覆盖父类。
通过以上两点,可知第9行是1,第12行是UpConstrutorHole - bh(),排除CD,还剩ABE,下面才是本题的重难点。
剩余的ABE总共涉及到两部分内容:
第一部分是B中的强制类型转换,同一个引用,为什么前者没有uch方法,而类型转换之后就有了呢?(所以B是不对的,仿佛是 在用貌似合理的话胡说八道,但是如果强制类型转换原理了解不清楚,很容易就被忽悠了,BZ就是很悲催的踩入了坑里 -- FK) 首先第8行那里进行向上造型,
new了一个UpConstrutorHole对象,就是说在堆内存中真真切切的生成了一个UpConstrutorHole对象,对象的实体数据中存放的就是这个类中的代码,这一点是
确定无疑的;其次,为什么把UpConstrutorHole对象赋值给b引用后就访问不到uch了呢?其实就是BaseHole类型的引用是有可见范围的,该可见范围
包括b中已有的方法属性跟被UpConstrutorHole类重写的方法,而UpConstrutorHole中的其余方法对该引用不可见,所以形成了向上造型的这种访问形式;
第三,为什么强制类型转换后就又能访问uch方法了呢?还是这个引用指针捣的鬼,强制类型转换后,引用的可见范围被改变,变为可以访问到UpConstrutorHole
类中的方法,所以又能引用到uch方法,虽然对象没变,引用地址没变,但是只要引用的类型变了其访问范围也会改变。至此,B的迷雾已经被拨开,pass掉。
第二部分,运行程序可知第8行输出的是UpConstrutorHole类中的bh方法打印的字符,为什么父类的构造器中执行的也是子类中重写的方法呢?其实这就要
追溯到对象初始化的时候的执行顺序了,翻阅了一下"圣经" - 《Thinking In Java》,发现有相关讲解,大意如下:
构造器初始化的顺序:
1、先将分配给对象的存储空间初始化为二进制的0;
2、在子类构造器执行前,先调用基类的构造器,此时如果基类的构造器中有子类重写的方法,会调用子类中的方法;
3、按顺序调用成员变量的初始化方法;
4、调用子类的构造器
而且后面还特意加了一句嘱咐:编写构造器时,尽可能的避免调用其他方法,尤其是非final跟private的方法。不然就可能出现如上题所示的莫名现象。
经此一役,发觉要学的东西仍然浩如烟海。还是那句话,学习之路,一定要多给自己灌鸡汤,Never at rest!
												

向上造型中让我入坑的地方 (><)的更多相关文章

  1. 小程序入坑(一)---如何引入iconfont 字体图标

    最近一直忙于日常任务,其实是懒癌又犯了..........不过因为自己的“懒癌”,“不思进取”给自己挖了不少坑. 一,小程序工具的安装 打开简易小程序的官网https://mp.weixin.qq.c ...

  2. Java中的向上造型和向下造型等

    package com.study.oop.day01; /**  * 如果某个方法是静态 的,它的行为就不具有多态性  * @author LuHongGang  * @date 2017年6月5日 ...

  3. python函数中把列表(list)当参数时的"入坑"与"出坑"

    在Python函数中,传递的参数如果默认有一个为 列表(list),那么就要注意了,此处有坑!! 入坑 def f(x,li=[]): for i in range(x): li.append(i*i ...

  4. 反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑) C#中缓存的使用 C#操作redis WPF 控件库——可拖动选项卡的TabControl 【Bootstrap系列】详解Bootstrap-table AutoFac event 和delegate的分别 常见的异步方式async 和 await C# Task用法 c#源码的执行过程

    反爬虫:利用ASP.NET MVC的Filter和缓存(入坑出坑)   背景介绍: 为了平衡社区成员的贡献和索取,一起帮引入了帮帮币.当用户积分(帮帮点)达到一定数额之后,就会“掉落”一定数量的“帮帮 ...

  5. eclipse中导入外部包却无法查看对应源码或Javadoc的入坑指南

    eclipse中导入外部包却无法查看对应源码或Javadoc的 入坑指南 出现这个错误的原因是,你虽然导入了.jar包,但没有配置对应的Javadoc或源码路径,所以在编辑器中无法查看源 码和对应AP ...

  6. RoboGuice 3.0 (一)入坑篇

    RoboGuice是什么? 一个Android上的依赖注入框架. 依赖注入是什么? 从字面理解,这个框架做了两件事情,第一是去除依赖,第二是注入依赖.简单理解就是,将对象的初始化委托给一个容器控制器, ...

  7. [SSIS] 在脚本里面使用数据库连接字符串进行查询等处理, 入坑

    入坑.!!!!! SSIS 中dts包 设置的  ADO.Net连接, 在传入脚本的时候, 我要使用 数据库连接,进行数据的删除操作. 于是我使用了 了如下的 代码 使用的是windows 身份验证, ...

  8. webpack入坑之旅(六)配合vue-router实现SPA

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

  9. webpack入坑之旅(五)加载vue单文件组件

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

随机推荐

  1. (python)编程小练习

    1.将一串字符串反向输出,如将"abcd"变成“dcba” str1="abcd" print str1[::-1] 2.判断是否为回文——判断用户输入的字符串 ...

  2. web安全系列1:入侵的途径

    大家好,接下来的很长一段时间我都会介绍和web安全有关的知识,欢迎大家关注和转发. 话不多说,我们首先来看看今天的主题----入侵的途径.当然,今天介绍的都是针对web网站的常用手法和技巧. 不可否认 ...

  3. Java平台

    Java的平台无关性 不同的网络环境,操作系统 支持嵌入式设备 减少开发部署时间 Java自身的平台和语言 编译成class文件 可在Java虚拟机中运行,与外部环境无关(对虚拟机的依赖) 通过外部A ...

  4. 【ORA-12516 TNS监听程序找不到符合协议堆栈要求的可用处理程序】

    服务器上某个数据库出现' ORA-12516: TNS: 监听程序找不到符合协议堆栈要求的可用处理程'错误,要解决该问题首先查看一下数据库现有的进程数,是否已经达到参数processes的大小. 取得 ...

  5. Codeforces Codeforces Round #484 (Div. 2) D. Shark

    Codeforces Codeforces Round #484 (Div. 2) D. Shark 题目连接: http://codeforces.com/contest/982/problem/D ...

  6. cordova 问题汇总

    用chrome进行调试: https://jingyan.baidu.com/album/db55b609fde96d4ba30a2fa9.html?picindex=8 http://rensann ...

  7. Delphi XE7试用记录1

    Delphi XE7试用记录1 在网上看到XE7的一些新特征,觉得完整Unicode支持.扩展Pascal语法.更多功能的库都很吸引人,决定试试XE7. XE7官方安装程序很大,因此选择了lite版, ...

  8. EF学习笔记(八):更新关联数据

    学习笔记主目录链接:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考 ...

  9. pyqt5 graphics view简单使用

    Graphics View提供了一个平面,用于管理和交互大量自定义的2D图形图元,以及一个用于可视化图元的视图窗口小部件,支持缩放和旋转. 该框架包括一个事件传播架构,允许场景中图元的精确双精度交互功 ...

  10. 刺透内网的HTTP代理

    从偶然出发 在做测试的时候发现了这样一个漏洞,原请求报文如下: GET / HTTP/1.1 Host: attack_website [... HEADER ...] ... 当时最初目的是想测SS ...