前面介绍了类的多态性,来自于鸡类的实例chicken,既能用来表达公鸡实例,也能用来表达母鸡实例。可是这导致了一个问题,假如在call方法内部需要手工判断输入参数属于公鸡实例还是母鸡实例,那该如何是好?所谓“雄兔脚扑朔,雌兔眼迷离,双兔傍地走,安能辨我是雄雌”,固然编译器在运行之时能够自动判断这是哪种鸡,可是若让程序员自己辨别倒的确是件伤脑筋的事情。虽说伤脑筋,却也并非无法实现,粗略算来大致有三个办法能派上用场,接下来分别进行阐述。
第一个办法,区别公鸡和母鸡,关键在于识别鸡的性别。注意到Chicken鸡类刚好有个性别类型字段sex,在公鸡类中sex固定为0,在母鸡类中sex固定为1。于是通过检查chicken实例的sex属性取值,即可判断该实例属于公鸡类还是属于母鸡类。据此可编写实例类型的鉴别方法,具体代码如下:

	// 通过属性字段type检查某实例的归属类
private static void checkType(Chicken chicken) {
if (chicken.sex == 0) { // 判断性别是否为雄性
System.out.println("检查类型字段:这是只公鸡。");
} else if (chicken.sex == 1) { // 判断性别是否为雌性
System.out.println("检查类型字段:这是只母鸡。");
} else {
System.out.println("检查类型字段:这既不是公鸡也不是母鸡。");
}
}

通过性别类型鉴定归属类,这种做法虽然在理论上可行,但事实上并不可靠。因为要是公鸡实例的sex取值被意外篡改为1,那该公鸡实例岂不是被误判为母鸡了?好比一只公鸡做了变性手术,难道它就变成母鸡了吗?篡改只能改变局部特征,并不能改变该事物的内在本质,或者说,血液中流淌着的基因是无法改变的。只要DNA里面携带Y染色体,那么这只鸡从根本上说就是公鸡,而不管它外表上如何整形。
由此可见,依据基因检测,才是检查实例类型的可靠办法。在Java代码中,获取某实例基因的手段是调用该实例的getClass方法,一旦获得某只鸡的基因,再跟公鸡的基因和母鸡的基因去比较,分分钟就比较出结果了。对于公鸡类Cock来说,它的基因可通过Cock.class提取;对于母鸡类Hen来说,它的基因可通过Hen.class来提取。于是实例类型的鉴别过程便分解为两个步骤:先调用实例的getClass方法得到它的基因,再将该基因与目标基因进行匹配操作,倘若匹配成功则表示二者是同一种类型。下面是按照基因匹配来检查实例归属类的代码例子:

	// 通过类的基因检查某实例的归属类
private static void checkClass(Chicken chicken) {
if (chicken.getClass().equals(Cock.class)) { // 判断这只鸡的DNA是不是公鸡DNA
System.out.println("检查对象的类名:这是只公鸡。");
} else if (chicken.getClass().equals(Hen.class)) { // 判断这只鸡的DNA是不是母鸡DNA
System.out.println("检查对象的类名:这是只母鸡。");
} else {
System.out.println("检查对象的类名:这既不是公鸡也不是母鸡。");
}
}

上述的基因检测手段很好很强大,然而其缺点也很明显,就是太专业太啰嗦了。本来仅仅是个判断实例类型的小事,何必要搞得兴师动众、追根溯源呢?因此Java专门提供了一个类型检查的关键字instanceof,使用格式形如“A instanceof B”,意思是检查A实例是否属于B类型,该表达式返回true表示属于,返回false表示不属于。这样关于鸡类实例的类型判断,借助于新关键字instanceof,又有了第三个鉴别办法,详细的鉴别代码如下所示:

	// 利用关键字instanceof检查某实例的归属类
private static void checkInstance(Chicken chicken) {
if (chicken instanceof Cock) { // 判断这只鸡是不是公鸡
System.out.println("检查对象实例:这是只公鸡。");
} else if (chicken instanceof Hen) { // 判断这只鸡是不是母鸡
System.out.println("检查对象实例:这是只母鸡。");
} else {
System.out.println("检查对象实例:这既不是公鸡也不是母鸡。");
}
}

可见利用instanceof判断实例的类型,不但简化了代码的写法,而且看起来也更易懂了。

更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(五十二)对象的类型检查的更多相关文章

  1. Java开发笔记(十二)布尔变量论道与或非

    在编程语言的设计之初,它们除了可以进行数学计算,还常常用于逻辑推理和条件判断.为了实现逻辑判断的功能,Java引入了一种布尔类型boolean,用来表示“真”和“假”.该类型的变量只允许两个取值,即t ...

  2. Java开发笔记(一百二十五)AWT图像加工

    前面介绍了如何使用画笔工具Graphics绘制各种图案,然而Graphics并不完美,它的遗憾之处包括但不限于:1.不能设置背景颜色:2.虽然提供了平移功能,却未提供旋转功能与缩放功能:3.只能在控件 ...

  3. Java开发笔记(一百二十)AWT文本标签

    前面介绍了AWT窗口及其面板的简单用法,其中展示出来的控件只有按钮一种,还有很多好用好玩的控件有待介绍.首先是文本标签Label,该控件用于显示一段平铺文本,它不花哨也不跳动,完全就是素面朝天的文本字 ...

  4. Java开发笔记(一百二十二)AWT选择框

    前面介绍了两种文本输入框的用法,不过实际应用很少需要用户亲自文字,而是在界面上列出几个选项,让用户勾勾点点完成选择,这样既方便也不容易弄错.依据选择的唯一性,可将选项控件分为两类:一类是在方框中打勾的 ...

  5. Java开发笔记(一百二十四)AWT绘图操作

    前面介绍了如何使用画笔在控件上展示图像,可是图像来源于磁盘图片,无法即兴绘制个性化的图案.所幸画笔工具Graphics不仅能够描绘图像,还支持绘制常见的几何形状,也支持绘制文本字符串,除了绘制图像用到 ...

  6. Java开发笔记(一百二十八)Swing的图标

    前面提过,AWT没提供能够直接显示图像的控件,这无疑是个令人诟病的短板,因为一上来就得由程序员自己去定义新控件,对于初学者来讲很不友好.这个问题在Swing中也解决掉了,不过Swing并未提供单独的图 ...

  7. Java开发笔记(一百二十九)Swing的输入框

    Swing的输入框仍然分成两类:单行输入框和多行输入框,但与AWT的同类控件相比,它们在若干细节上有所调整.首先说单行输入框,AWT的单行输入框名叫TextField,平时输入什么字符它便显示什么字符 ...

  8. Java开发笔记(一百二十六)Swing的窗口

    前面介绍了AWT界面编程的若干技术,在编码实践的时候,会发现AWT用起来甚是别扭,它的毛病包括但不限于下列几点:1.对中文的支持不好,要想在界面上正常显示汉字,还得在运行时指定额外的运行参数“-Dfi ...

  9. Java开发笔记(九十)对象序列化及其读写

    有些时候,开发者想把程序运行过程中的数据临时保存到文件,可是前面介绍的字符流和字节流,要么用来读写文本字符串,要么用来读写字节数组,并不能直接保存某个对象信息,因为对象里面包括成员属性和成员方法,单就 ...

  10. Java开发笔记(九十二)文件通道的基本用法

    前面介绍的各色流式IO在功能方面着实强大,处理文件的时候该具备的操作应有尽有,可流式IO在性能方面不尽如人意,它的设计原理使得实际运行效率偏低,为此从Java4开始增加了NIO技术,通过全新的架构体系 ...

随机推荐

  1. Golang Go Go Go part2:变量及常量声明

    三.关键字及内置预声明常量.类型.函数 1.关键字 Go有25个关键字,只能用在语法允许的地方,不能作为名称使用,它们是: break          default         func    ...

  2. Xaml Controls Gallery 的五个没有用的控件

    HyperlinkButton 功能:这个控件可以实现点击按钮后跳到另一个按钮的功能. 我觉得这个功能有些多余,据我了解,一些深受欢迎的游戏大都具备的一个特点,那就是操作简单,界面中不会出现冗余的东西 ...

  3. 算法与数据结构(七) AOV网的拓扑排序(Swift版)

    今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...

  4. [Swift]LeetCode137. 只出现一次的数字 II | Single Number II

    Given a non-empty array of integers, every element appears three times except for one, which appears ...

  5. [Swift]LeetCode151. 翻转字符串里的单词 | Reverse Words in a String

    Given an input string, reverse the string word by word. Example: Input: "the sky is blue", ...

  6. [Swift]LeetCode801. 使序列递增的最小交换次数 | Minimum Swaps To Make Sequences Increasing

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  7. [Swift]LeetCode904. 水果成篮 | Fruit Into Baskets

    In a row of trees, the i-th tree produces fruit with type tree[i]. You start at any tree of your cho ...

  8. H5与企业微信jssdk集成

    H5与企业微信jssdk集成 一.公众号设置 注册企业微信,在应用与小程序栏目中,设置可信域名,配置公众号菜单.可信域名不得不说下,在最初开发时,认为设置并验证后,微信认证接口会实现跨域请求,其实并没 ...

  9. Python数据挖掘指南

    Data Mining in Python: A Guide 转载原文:https://www.springboard.com/blog/data-mining-python-tutorial/(全英 ...

  10. [IOI2007] sails 船帆

    显然答案与杆的顺序无关(按每个高度考虑). 从高到低考虑杆,设此时的状态为\(S\),\(S[i]\)是高度\(i\)的帆的数目,初始全为\(0\),当前杆的高度为\(h\),杆上需要放置的帆的数目为 ...