面向对象的陷阱——instanceof运算符的陷阱

Java运算符-关键字 instanceof,这你必须得会! Java作为一种广泛使用的开发语言,具有强大的面向对象特性。其中,关键字instanceof在Java程序中具有重要的作用。本文将深入介绍instanceof关键字的用法和应用场景。本文将详细介绍instanceof关键字的用法和原理,以及它在Java开发中的应用场景和优缺点分析。同时,提供实际的代码示例和测试用例,以便读者更好地理解和应用instanceof关键字。instanceof是Java中的一种关键字,用于判断一个对象是否属于某个类或其子类。 阅读详情

1、instanceof运算符的陷阱

       instanceof是一个非常简单的运算符。instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个操作数通常是一个类(也可以是接口,可以把接口理解成一种特殊的类),它用于判断前面的对象是否是后面的类或其子类、实现类的实例。如果是,则返回true;否则,返回false。
       根据Java语言规范,使用instanceof运算符有一个限制:instanceof运算符前面操作数的编译时类型必须是如下三种情况。
  1. 要么与后面的类相同。
  2. 要么是后面类的父类。
  3. 要么是后面类的子类。
       如果前面操作数的编译时类型与后面的类型没有任何关系,程序将没法通过编译。因此,当时用instanceof运算符的时候,应尽量从编译、运行两个阶段来考虑它——如果instanceof运算符使用不当,程序编译时就会抛出异常;当使用instanceof运算符通过编译后,才能考虑运算结果是true还是false。
          一旦instanceof运算符通过了编译,程序进入运算阶段。instanceof运算返回的结果与前一个操作数(引用变量)实际引用的对象的类型有关,如果它实际引用的对象是第二个操作数的实例,或者是第二个操作数的子类、实现类的实现,那么instanceof运算的结果返回true,否则返回false。
       在极端情况之下,instanceof前一个操作数所引用对象的实际类型就是后面的类型,但只要它的编译时类型既不是第二操作数的类型,也不是第二个操作数的父类、子类,程序就没法通过编译。
public class InstanceofTest {
	public static void main(String[] args) {
		Object str = "Java对象";
		Math math = (Math)str;  //①
		System.out.println("字符串是否是String的实例:" + (math instanceof String));  //②  报错:Incompatible conditional operand types Math and String
	}
}
       当编译器编译Java程序时,编译器无法检查引用变量实际引用对象的类型,它只检查该变量的编译时类型。对于②行代码来说,math的编译时类型是Math,Math既不是String类型,也不是String类型的父类,还不是String类型的子类,因此程序没法通过编译。至于math实际引用对象的类型是什么,编译器并不关心。
       至于①行代码出为何没有出现编译错误,这和强制转型的机制有关。对于Java的强制转型而言,也可以分为编译、运行两个阶段来进行分析。
       ·编译阶段,强制转型要求被转型变量的编译时类型必须是如下三种情况之一。
  1. 被转型变量的编译时类型与目标类型相同。
  2. 被转型变量的编译时类型是目标类型父类。
  3. 被转型变量的编译时类型是目标类型子类。在这种情况下可以自动向上转型,无须强制转换。
       如果被转型变量的编译时类型与目标类型没有任何继承关系,编译器将提示编译错误。通过上面分析可以知道,强制转型的编译阶段只关心引用变量的编译时类型,至于该引用变量实际引用对象的类型,编译器并不关心。
       ·运行阶段,被转型变量所引用对象的实际类型必须是目标类型的实例,或者是目标类型的子类、实现类的实例,否则在运行时将引发ClassCastException异常。
       从上面的分析可以看出,对于①行代码来说,编译时不会出现错误,因为str引用变量的编译时类型是Object,它是Math类的父类。但是str运行时类型是String,它与Math类没有任何关系,所以运行时将会引发ClassCastException异常。
public class ConversionTest {
	public static void main(String[] args) {
		Object obj = "Hello";  //obj编译时类型是Object,运行时类型是String。
		String objStr = (String)obj;  //因为obj编译时类型是Object,所以可以通过编译。因为obj运行时类型是String,objStr也是String类,所以可以运行。
		System.out.println(objStr);
		
		Object objPri = new Integer(5);  //objPri编译时类型是Object,运行时类型是Integer。
		String str = (String)objPri;  //因为objPri编译时类型是Object,所以可以通过编译。因为obj运行时类型是Integer,objStr是String类,所以会引发异常。
		System.out.println(str);
		
		String s = "Java对象";  //s编译时类型和运行时类型都是String。
		Math m = (Math)s;  //String类不是Math的子类,也不是Math的父类,所以会导致编译错误。
	}
}

       关于instanceof还有一个比较隐蔽的陷阱。
public class NullInstaceof {
	public static void main(String[] args) {
		String s = null;
		System.out.println("null是否是String类的实例:"  + (s instanceof String));
	}
}
输出结果为:
null是否是String类的实例:false
       虽然null可以作为所有引用类型变量的值,但对于s引用变量而言,它实际上并未引用一个正在的String对象,因此程序会输出false。使null调用instanceof运算符时返回false是非常有用的行为,因为instanceof运算符有一个额外的功能:它可以保证第一个操作数所引用的对象不是null。如果instanceof告知一个引用变量是某个特定类型的实例,那么就可以将其转型为该类型,不用担心会抛出ClassCastException或NullPointerException异常。








JavaScript类型检测之typeof 和 instanceof 的缺陷与优化 在javascript中,typeof 和 instanceof 是用来判断数据类型比较通用的两个方法,这篇文章的目的是通过对这两个方法介绍来分析其存在的不足并提出优化方案 立即下载

相关推荐

CMOS传输门实战:如何用模拟开关优化你的电路设计(附常见问题排查)

本文深入探讨了CMOS传输门在电路设计中的实战应用与优化策略。文章从核心参数选型入手,详细分析了导通电阻、电荷注入等关键特性对电路性能的影响,并提供了多路复用器构建、精密电路应用等实战架构。同时,重点分享了PCB布局、电源去耦的工程细节,以及开关不导通、信号失真、高频性能不足等常见问题的系统性排查指南,旨在帮助硬件工程师充分发挥CMOS模拟开关的效能,提升电路设计的可靠性与精度。

js777的博客 451

js常用判断数据类型方法以及优缺点 以及 instanceof 原理实现

js常见判断数据类型方法以及优缺点

weixin_45748897的博客 769

Gazebo仿真平台模型搭建与修改

ROS里踩过的坑(一)Gazebo仿真平台模型搭建与修改文件讲解Models 文件World文件Launch文件模型编辑可视化编辑配置文件编辑模型展示如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出...

Redglass的博客 1万+

使用instanceof去检测数组的弊端是什么?

使用instanceof去检测数组的弊端是什么? 一般我们说去检测数组,会使用到 if (value instanceof Array){ // 操作数组 } 使用这一方法可能大家很少会注意到会有什么问题。 这也是我看书看到的,所以分享给大家。虽然这很少见到 使用 `instanceof` 的问题是假定只有一个全局执行上下文。如果网页里有多个框架,则可能涉及两 个不同的全局执行上下文,因此就会有两个不同版本的 Array 构造函数。如果要把数组从一个框架传 给另一个框架,则这个数组的构造函数将有别于在

WebView 1355

【ZYNQ驱动双AD9361实战】(一)从官方参考设计到自定义移植

本文详细介绍了如何将ADI官方的单AD9361参考设计移植到ZYNQ平台以驱动双AD9361射频板卡。内容涵盖从环境搭建、官方工程架构解析,到硬件HDL工程修改(包括顶层设计、引脚分配及TCL脚本适配)以及Linux设备树软件配置的全流程实战指南,帮助开发者实现自定义双通道射频收发系统。

weixin_29170327的博客 362

零基础教你学RDMA驱动开发:从入门到精通--第6章 内存管理与DMA映射​6.2 DMA地址转换:内核dma_map_single()与硬件IOVA(I/O虚拟地址)​

本文深入探讨RDMA驱动中DMA地址转换机制,重点分析内核dma_map_single()函数与硬件IOVA的作用。主要内容包括:1)DMA地址转换的必要性,解决CPU虚拟地址与HCA设备DMA地址的空间割裂问题;2)内核DMA映射机制实现原理,涵盖无IOMMU(直接物理地址映射)和有IOMMU(IOVA转换)两种场景;3)硬件IOVA的工作流程及其与RDMA内存注册的结合;4)RDMA驱动开发中的关键问题,如缓存一致性、映射方向错误、IOVA泄漏等;5)以mlx5驱动为例的实践分析。文章强调DMA地址转换

xiaoheshang_123的博客 239

Javascript之旅——第八站:说说instanceof踩了一个坑

  前些天写js遇到了一个instanceof的坑,我们的页面中有一个iframe,我在index页面中计算得到了一个array,然后需要传递到Flight页面 这个嵌套的iframe中的一个函数(SearchFlight)中,作为防御性编程,我需要在SearchFlight函数中进行参数检测,也就是判断过来的参数一 定是Array类型。   一:抛出问题 举个例子,下面有两个页面。 ...

weixin_33885676的博客 315

ArcGIS:景观指数和景观单元关联生成景观指数遥感图像

优快云@_养乐多_本文将记录,使用由 Fragstats V4.2 软件计算的景观指数和瓦片 tif 数据生成景观指数图像的操作步骤。本教程的操作均在ArcGIS上进行,最后生成一个研究区内指定景观单元大小的景观指数图像。结果如下所示,

养乐多的博客 4930

Java进阶5 面向对象的陷阱

Java进阶5 面向对象的陷阱 20131103 Java是一门纯粹面向对象的编程语言,Java面向对象是基础,而且面向对象的基本语法非常多,非常的细,需要程序员经过长时间的学习才可以掌握。本章重点介绍的是Java中面向对象中的容易出现的陷阱。 1. instanceof 运算符的陷阱 Instanceof运算符前一个操作数通常是一个引用类的变量,后一个操...

weixin_34220834的博客 82

利用XGBoost实现短期电力负荷预测

本数据集为某地区2009年-2015年的用电负荷,时间片为每分钟这里我们定义了XGB模型作为实例,来进行模型训练,之后我们会对其使用网格搜索找到最优的参数。

优快云 精品推荐 4495

【AUTOSAR AP PHM 】PHM 标准化“检查点上报接口”落地指南(AUTOSAR AP · R24-11取向)

本文介绍了AUTOSAR AP R24-11标准下PHM(平台健康管理)模块中"检查点上报接口"的标准化实现方案。主要内容包括: 核心设计理念:采用"配置优先"原则,通过部署模型预先定义监管参数,应用进程只需简单上报枚举标识,具体判定由PHM执行。 职责划分: 应用进程:仅调用ReportCheckpoint接口上报枚举值 PHM:负责Alive计数、Deadline区间判定和Logical路径校验 EM/IdsM:提供进程状态和越权检测 三类监管机制: Alive:

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 220

33-js-concepts构造函数:new操作符与instanceof原理揭秘

- ✅ 深入理解JavaScript构造函数的工作原理 - ✅ 掌握`new`操作符的底层实现机制 - ✅ 揭秘`instanceof`运算符的检测原理 - ✅ 学会手动实现构造函数和原型链检测 - ✅ 避免常见的构造函数使用陷阱 ## ???? 痛点场景:为什么需要理解构造函数? 在日常JavaScript开发中,你是否遇到过这样的困惑: ```javascript function Pe...

gitblog_00008的博客 845

【CT/电镜 重建教程 1.1】层析成像的精确实空间迭代重建算法(RESIRE)

在此,我们报告了RESIRE算法的发展用于准确的断层重建。与实空间迭代算法相比,RESIRE使用傅里叶切片定理或Radon变换作为正向投影,使用线性变换作为反向投影,两者都具有高精度。与EST和GENFIRE相比,RESIRE是一种实空间迭代算法,可以在并行计算中实现快速运行时间。

2401_87064292的博客 1062

4.面向对象的陷阱

Java面向对象的设计过程中也会有一些陷阱***************************************************************************************学习笔记如下:instanceof运算符的陷阱 instanceof是一个非常简单的运算符。instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个操作数通常是一个类(...

Hyo_yew的博客 433

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java instanceof 深度解析:从原理到最佳实践与模式匹配

在面向对象编程中,类型检查是确保代码健壮性的基础操作。其核心原理在于运行时动态验证对象与目标类型的兼容性,这涉及到Java类型系统和RTTI(运行时类型识别)机制。从技术价值看,合理的类型检查能有效防止ClassCastException,是实现安全类型转换和防御性编程的关键。然而,过度依赖显式的类型判断,尤其是在业务逻辑中,往往被视为一种设计上的“坏味道”,可能意味着多态特性的缺失,从而影响代码的可扩展性和可维护性。常见的应用场景包括框架底层实现(如反序列化)、处理遗留异构集合、实现equals方法以及访

weixin_30394981的博客 294

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java面向对象

本文系统讲解了Java面向对象编程的核心概念与实践。从面向过程与面向对象的对比入手,详细阐述了封装、继承、多态三大特性。重点解析了类与对象的关系、构造方法与方法重载的实现,以及static、final、this、super四个关键字的用法。深入探讨了垃圾回收机制、继承与方法重写规则,并剖析了Object类的核心方法。通过代码示例和流程图,全面展示了面向对象编程从基础到设计原则的完整知识体系,为Java开发者提供了系统性的学习参考。

无论云泥意贯一 381

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【JavaScript】Javascript—JS进阶—Day03

深入面向对象、原型链相关知识

2301_77399671的博客 77

27、面向对象的陷阱

1、instanceof运算符的陷阱

YGingko的专栏 564

疯狂Java笔记之面向对象的陷阱

instanceof运算符的陷阱instanceof是一个非常简单的运算符。instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个操作数通常是一个类(也可以是接口,可以把接口理解成一个特殊的类),他用于判断前面的对象是否是后面的类或其子类,实现类的实例。如果是,则返回true,否则,返回false.String obj="Java"; obj instanceof Math上面程序

Jack921的专栏 460

No.7 面向对象的陷阱

1.instanceof 运算符的陷阱 instanceof 运算符前面操作数的编译时类型必须是以下三种情况:①与后面的类相同②是后面的父类③是后面的子类。否则 无法通过编译(Incompatible conditional operand types String and Math) 使用该运算符 从 编译、运行两个阶段来考虑 强制转换机制 编译阶段(需要有继承关系...

178

instanceof到底返回什么?一个boolean值背后的类加载机制揭秘

深入解析instanceof的boolean判断机制,揭示其背后类加载与类型检查的关联。适用于Java类型判断场景,阐明其如何通过继承关系实现安全的对象类型检测,提升代码健壮性,值得收藏。

CodeWhim的博客 897

Java instanceof 运算符深度解析:从核心机制到实战避坑指南

在Java编程中,类型检查是确保代码健壮性的基础环节。其核心原理在于运行时动态验证对象与目标类型的继承或实现关系,这为安全地进行向下转型提供了保障。这项技术的核心价值在于实现防御性编程,有效避免ClassCastException,从而提升系统的稳定性与容错能力。它广泛应用于处理异构数据源、实现插件化架构、适配第三方库以及重构遗留代码等场景。本文聚焦于instanceof这一关键运算符,结合类型守卫和模式匹配等热词,深入剖析其工作机制、典型应用模式、常见性能误区及与Java新特性的结合方式,为工程师提供一套

weixin_33826609的博客 413

【代码诗学】instanceof的浪漫陷阱:当AI用Java语法写情书

本文探讨了Java中的instanceof运算符在AI情诗创作中的独特应用,通过《world.execute(me)》歌词中的代码示例,展示了如何将冰冷的语法转化为炽热的情感表达。文章深入分析了instanceof从类型检查工具到情感载体的诗意变形,揭示了代码与艺术融合的浪漫可能性。

weixin_27960253的博客 380

【Java SE】instanceof 关键字

在Java的面向对象编程中,instanceof是一个看似简单却功能强大的运算符。它用于判断一个对象是否属于特定的类或其子类,是类型安全检查和多态编程的重要工具。随着Java版本的演进,instanceof也经历了从基础运算符到模式匹配的华丽蜕变。本文将全面解析instanceof的用法、演进历程、最佳实践及常见陷阱。

427

【疯狂Java_突破程序员基本功的16课】charpt7 面向对象的陷阱

7.1 instanceof运算符的陷阱 instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个 操作数通常是一个类(也可以是接口,可以把接口当成一种特殊的类),它用于判断前面的对象是否是后面的类或其子类、实现类的实例。如果是,返回true,否则返回false。 根据java语言规范,使用instanceof运算符有一个限制:instanceof运算符前面操作数的编...

delengyao1368的博客 171

Java运算符完全指南:从基础到实战技巧

在 Java 编程世界里,运算符是构建代码逻辑与执行运算的关键要素。本文《Java 运算符完全指南:从基础到实战技巧》全面剖析 Java 运算符体系,从赋值、算术、关系、逻辑、按位等基础运算符的原理与用法讲起,结合丰富代码示例助您理解基础运算规则,如整数除法特性、自增自减运算符的前缀后缀差异。同时深入挖掘实战技巧,包括按位取反原理在特定场景下的巧妙运用,以及巧用位运算解决不用临时变量交换两数等高效算法问题,为您带来从理论认知到实际编程应用的全方位运算符学习之旅,助您提升 Java 编程技能,灵活驾驭各类运算

weixin_51786043的博客 632
上一篇: Java流程控制的陷阱——for循环和foreach循环的陷阱
下一篇: CentOS7最小安装之后安装xfce桌面
Never_Blue
博客等级 码龄10年 5粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值