Java小白踩坑录 - instanceof 用法揭秘

简介: Java小白踩坑录 - instanceof 用法揭秘

image.png

如何判断是不是谁的谁?Java有一个 instanceof 操作符(关系操作符)可以做这件事。

publicstaticvoidmain(String[] args) {
Strings="Hello World!";
System.out.println(sinstanceofString);
 }

打印出结果:

true

可是如果你的那个谁不存在呢?请看代码:

publicstaticvoidmain(String[] args) {
Strings=null;
System.out.println(sinstanceofString);
}

很多人都会异口同声的说:

false

你答对了!

JSL-15.20.2 规定

At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast to the ReferenceType without raising a ClassCastException. Otherwise the result is false.


注:在运行期,如果关系表达式不为空,并且类型转换时不会抛出ClassCastException异常时,instanceof表达式返回结果为真,否则结果为假


牵线之乱点鸳鸯谱

如果没有任何关系的两个类使用 instanceof 会如何?

classPoint { intx, y; }
classElement { intatomicNumber; }
publicclassInstanceofTest {
publicstaticvoidmain(String[] args) {
Pointp=newPoint();
Elemente=newElement();
if (einstanceofPoint) { 
System.out.println("匹配成功!");
    }else {
System.out.println("匹配不成功");
    }
 }
}

不少人会说:“匹配不成功”

抱歉,你又掉进坑里了,这个会报编译错误

image.png

JSL-15.20.2规定

The type of the RelationalExpression operand of the instanceof operator must be a reference type or the null type, or a compile-time error occurs.


注:instanceof操作符的关系表达式操作数的类型必须是一个引用类型或者null类型,否则抛出编译错误


It is a compile-time error if the ReferenceType mentioned after the instanceof operator does not denote a reference type that is reifiable。


注:如在instanceof操作符后面提及的引用类型表示的不是可具化(§4.7)引用类型.就会抛出编译错误。


If a cast of the RelationalExpression to the ReferenceType would be rejected as a compile-time error (§15.16), then the instanceof relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.


注:如从关系表达式到引用类型的强制类型转换将作为编译时错误而拒绝,那么 instanceof 关系表达式也就同样地产生编译时错误。这种情况下,instanceof 表达式的结果也永远不会是真。


当然,cast 也会是编译错误

classPoint { intx, y; }
classElement { intatomicNumber; }
publicclassInstanceofTest {
publicstaticvoidmain(String[] args) {
Pointp=newPoint();
Elemente=newElement();
p= (Point)e; // compile-time error    }
}

牵线之暗藏玄机

编译器并不是万能的,并不能检测出所有问题,看下面:

classPoint { intx, y; }
classElement { intatomicNumber; }
publicclassInstanceofTest {
publicstaticvoidmain(String[] args) {
Pointp=newPoint();
//Element e = new Element();p= (Point) newObject();
System.out.println(pinstanceofPoint);
 }
}

猛一看,没事问题,编译也没有问题,可是运行时报错:

Exceptioninthread"main"java.lang.ClassCastException: java.lang.ObjectcannotbecasttoPoint

上面的程序展示了,当要被转型的表达式的静态类型是转型类型的超类时,转型操作符的行为。与 instanceof 操作相同,如果在一个转型操作中的两种类型都是类,那么其中一个必须是另一个的子类型。尽管对我们来说,这个转型很显然会失败,但是类型系统还没有强大到能够洞悉表达式 new Object() 的运行期类型不可能是 Point 的一个子类型。因此,该程序将在运行期抛出 ClassCastException 异常。

牵线之竞争激烈

关系操作符 instanceof 可不是市场上唯一的选择,另外一个背靠大山的家伙要注意了:

Class 的方法

booleanisInstance(Objectobj)
DeterminesifthespecifiedObjectisassignment-compatiblewiththeobjectrepresentedbythisClass.

那么什么时候该用 instanceof 什么时候该用 isInstance 呢 ? 我的理解是:

instanceof 偏向于比较 class之间

isInstance 偏向于比较 instance 和 class 之间

stackoverflow 也有此问题的解答:

I take that to mean that isInstance() is primarily intended for use in code dealing with type reflection at runtime. In particular, I would say that it exists to handle cases where you might not know in advance the type(s) of class(es) that you want to check for membership of in advance (rare though those cases probably are).


注:我认为这意味着isInstance()主要用于在运行时处理类型反射的代码中。特别是,我想说它的存在是为了处理,您可能事先不知道您想要检查的类的类型(s)(尽管这些情况可能很少)的情况。


For instance, you can use it to write a method that checks to see if two arbitrarily typed objects are assignment-compatible, like:


注:例如,您可以使用它来编写一个方法,检查两个任意类型的对象是否兼容,如


publicbooleanareObjectsAssignable(Objectleft, Objectright) {
returnleft.getClass().isInstance(right);
} 


In general, I’d say that using instanceof should be preferred whenever you know the kind of class you want to check against in advance. In those very rare cases where you do not, use isInstance() instead.


注:一般来说,我想说,当您知道要提前检查的类的类型时,应该首选使用instanceof。在不使用isInstance()的非常罕见的情况下,可以使用isInstance()。


总结

回归本源,instanceof 是 Java 中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回 true;否则,返回 false。

目录
相关文章
|
Java
Java中的equals()与==的区别与用法
【7月更文挑战第28天】
337 12
|
8月前
|
存储 安全 Java
深入理解 Java 中的 instanceof 关键字
本文深入解析了 Java 中的 `instanceof` 关键字,探讨其在类型判断中的作用。作为二元操作符,`instanceof` 可用于检查对象是否为某类实例或实现特定接口,避免类型转换异常 (`ClassCastException`)。文章通过多态性下的类型判断、安全类型转换、接口实现检测及集合元素类型判定等实际应用场景,展示了 `instanceof` 的强大功能。掌握该关键字可提高代码健壮性,确保运行时类型安全。
571 0
|
12月前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
10566 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
存储 安全 Java
深入理解Java中的FutureTask:用法和原理
【10月更文挑战第28天】`FutureTask` 是 Java 中 `java.util.concurrent` 包下的一个类,实现了 `RunnableFuture` 接口,支持异步计算和结果获取。它可以作为 `Runnable` 被线程执行,同时通过 `Future` 接口获取计算结果。`FutureTask` 可以基于 `Callable` 或 `Runnable` 创建,常用于多线程环境中执行耗时任务,避免阻塞主线程。任务结果可通过 `get` 方法获取,支持阻塞和非阻塞方式。内部使用 AQS 实现同步机制,确保线程安全。
1250 3
|
安全 Java 测试技术
🌟 Java 零基础 | 详解 instanceof 运算符
【10月更文挑战第1天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
409 1
|
Java
Java 正则表达式高级用法
Java 中的正则表达式是强大的文本处理工具,用于搜索、匹配、替换和分割字符串。`java.util.regex` 包提供了 `Pattern` 和 `Matcher` 类来高效处理正则表达式。本文介绍了高级用法,包括使用 `Pattern` 和 `Matcher` 进行匹配、断言(如正向和负向前瞻/后顾)、捕获组与命名组、替换操作、分割字符串、修饰符(如忽略大小写和多行模式)及 Unicode 支持。通过这些功能,可以高效地处理复杂文本数据。
229 10
|
存储 Java 数据处理
Java 数组的高级用法
在 Java 中,数组不仅可以存储同类型的数据,还支持多种高级用法,如多维数组(常用于矩阵)、动态创建数组、克隆数组、使用 `java.util.Arrays` 进行排序和搜索、与集合相互转换、增强 for 循环遍历、匿名数组传递以及利用 `Arrays.equals()` 比较数组内容。这些技巧能提升代码的灵活性和可读性,适用于更复杂的数据处理场景。
137 10
|
安全 Java
Java switch case隐藏用法
在 Java 中,`switch` 语句是一种多分支选择结构,常用于根据变量值执行不同代码块。除基本用法外,它还有多种进阶技巧,如使用字符串(Java 7 开始支持)、多个 `case` 共享代码块、不使用 `break` 实现 “fall-through”、使用枚举类型、使用表达式(Java 12 及以上)、组合条件以及使用标签等。这些技巧使代码更加简洁、清晰且高效。
401 1
|
Java 数据处理
Java IO 接口(Input)究竟隐藏着怎样的神秘用法?快来一探究竟,解锁高效编程新境界!
【8月更文挑战第22天】Java的输入输出(IO)操作至关重要,它支持从多种来源读取数据,如文件、网络等。常用输入流包括`FileInputStream`,适用于按字节读取文件;结合`BufferedInputStream`可提升读取效率。此外,通过`Socket`和相关输入流,还能实现网络数据读取。合理选用这些流能有效支持程序的数据处理需求。
427 2
|
安全 Java 测试技术
day16:Java零基础-instanceof 运算符
【7月更文挑战第16天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
173 8