1. instanceof关键字

如果你之前一直没有怎么仔细了解过instanceof关键字,现在就来了解一下:

instanceof其实是java的一个二元操作符,和=,<,>这些是类似的,同时它也是被保留的关键字,主要的作用,是为了测试左边的对象,是不是右边的类的实例,返回的是boolean值。

A instanceof B

注意:A是实例,而B则是Class类

下面使用代码测试一下:

class A{
}
interface InterfaceA{ }
class B extends A implements InterfaceA{ }
public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println(b instanceof B);
System.out.println(b instanceof A);
System.out.println(b instanceof InterfaceA); A a = new A();
System.out.println(a instanceof InterfaceA);
}
}

输出结果如下:

true
true
true
false

从上面的结果,其实我们可以看出instanceof,相当于判断当前对象能不能装换成为该类型,java里面上转型是安全的,子类对象可以转换成为父类对象,接口实现类对象可以装换成为接口对象。

对象aInterface没有什么关系,所以返回false

那如果我们装换成为Object了,它还能认出来是哪一个类的对象么?

public class Test {
public static void main(String[] args) {
Object o = new ArrayList<Integer>();
System.out.println(o instanceof ArrayList); String str = "hello world";
System.out.println(str instanceof String);
System.out.println(str instanceof Object);
}
}

上面的结果返回都是true,也就是认出来还是哪一个类的对象。同时我们使用String对象测试的时候,发现对象既是String的实例,也是Object的实例,也印证了Java里面所有类型都默认继承了Obejct

但是值得注意的是,我们只能使用对象来instanceof,不能使用基本数据类型,否则会报错。

如果对象为null,那是什么类型?

这个答案是:不知道什么类型,因为null可以转换成为任何类型,所以不属于任何类型,instanceof结果会是false

具体的实现策略我们可以在官网找到:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.instanceof

如果Sobjectref所引用的对象的类,而T是已解析类,数组或接口的类型,则instanceof确定是否 objectrefT的一个实例。S s = new A(); s instanceof T

  • 如果S是一个普通的(非数组)类,则:

    • 如果T是一个类类型,那么S必须是T的同一个类,或者S必须是T的子类;
    • 如果T是接口类型,那么S必须实现接口T。
  • 如果S是接口类型,则:

    • 如果T是类类型,那么T必须是Object。
    • 如果T是接口类型,那么T一定是与S相同的接口或S的超接口。
  • 如果S是表示数组类型SC的类[],即类型SC的组件数组,则:

    • 如果T是类类型,那么T必须是Object。
    • 如果T是一种接口类型,那么T必须是数组实现的接口之一(JLS§4.10.3)。
    • 如果T是一个类型为TC的数组[],即一个类型为TC的组件数组,那么下列其中一个必须为真:
      • TC和SC是相同的原始类型。
      • TC和SC是引用类型,类型SC可以通过这些运行时规则转换为TC。

但是具体的底层原理我在知乎找到的R大 回答的相关问题,https://www.zhihu.com/question/21574535,看完觉得我太弱了...我是菜鸟...我确实是菜鸟

2. isInstance()方法

其实这个和上面那个是基本相同的,主要是这个调用者是Class对象,判断参数里面的对象是不是这个Class对象的实例。

class A {
} interface InterfaceA { } class B extends A implements InterfaceA { } public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println(B.class.isInstance(b));
System.out.println(A.class.isInstance(b));
System.out.println(InterfaceA.class.isInstance(b)); A a = new A();
System.out.println(InterfaceA.class.isInstance(a));
}
}

历史总是惊人的相似!!!

true
true
true
false

事实证明,这个isInstance(o)判断的是o是否属于当前Class类的实例.

不信?再来测试一下:

public class Test {
public static void main(String[] args) {
String s = "hello";
System.out.println(String.class.isInstance(s)); // true
System.out.println(Object.class.isInstance(s)); // true System.out.println("=============================");
Object o = new ArrayList<String>();
System.out.println(String.class.isInstance(o)); // false
System.out.println(ArrayList.class.isInstance(o)); // true
System.out.println(Object.class.isInstance(o)); // true
}
}

可以看出,其实就是装换成为Object,之前的类型信息还是会保留着,结果和instance一样,区别是:

  • instanceof :前面是实例对象,后面是类型
  • isInstance:调用者(前面)是类型对象,参数(后面)是实例对象

但是有一个区别哦,isInstance()这个方法,是可以使用在基本类型上的,其实也不算是用在基本类型,而是自动做了装箱操作。看下面:

        System.out.println(Integer.class.isInstance(1));

参数里面的1,其实会被装箱成为new Integer(1),所以这样用不会报错。

3. instanceof,isInstance,isAssignableFrom区别是什么?

  • instanceof 判断对象和类型之间的关系,是关键字,只能用于对象实例,判断左边的对象是不是右边的类(包括父类)或者接口(包括父类)的实例化。
  • isInstance(Object o):判断对象和类型之间的关系,判断o是不是调用这个方法的class(包括父类)或者接口(包括父类)的实例化。
  • isAssignableFrom:判断的是类和类之间的关系,调用者是否可以由参数中的Class对象转换而来。

注意:java里面一切皆是对象,所以,class本身也是对象。

【作者简介】

秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。这个世界希望一切都很快,更快,但是我希望自己能走好每一步,写好每一篇文章,期待和你们一起交流。

此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者核实删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~

【Java基础】-- instanceof 用法详解的更多相关文章

  1. Java基础之 数组详解

    前言:Java内功心法之数组详解,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 数组概念 同一种类型数据的集合.其实数组就是一个容器. 数组 ...

  2. java基础之:详解内部类(转载)

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

  3. java中的instanceof用法详解

    instanceof是Java的一个二元操作符(运算符),也是Java的保留关键字.它的作用是判断其左边对象是否为其右边类的实例,返回的是boolean类型的数据.用它来判断某个对象是否是某个Clas ...

  4. [Java基础] Java enum的用法详解

    用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...

  5. 多线程java的concurrent用法详解(转载)

    我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,当然也有一些开源的框架提供了这些功能,但是这些依然没有JDK自带的功能使用起来方便.而当针对高质量Java ...

  6. java的concurrent用法详解

    我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,当然也有一些开源的框架提供了这些功能,但是这些依然没有JDK自带的功能使用起来方便.而当针对高质量Java ...

  7. 【转】Java enum的用法详解

    用法一:常量 在JDK1.5 之前,我们定义常量都是: public static fianl.... .现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. p ...

  8. Java enum的用法详解[转]

    Ref:http://www.cnblogs.com/happyPawpaw/archive/2013/04/09/3009553.html 用法一:常量 在JDK1.5 之前,我们定义常量都是: p ...

  9. Java enum的用法详解

    (转自:http://www.cnblogs.com/happyPawpaw/archive/2013/04/09/3009553.html) 用法一:常量 在JDK1.5 之前,我们定义常量都是: ...

  10. Java基础(52):ClassCastException详解(转)

    ClassCastException,从字面上看,是类型转换错误,通常是进行强制类型转换时候出的错误.下面对产生ClassCastException异常的原因进行分析,然后给出这种异常的解决方法. 这 ...

随机推荐

  1. Effective C++——Item33: 避免隐藏继承的名字

    Effective C++--Item33: 避免隐藏继承的名字 一.从原理理解隐藏 从变量作用域看隐藏 全局变量x和局部变量x的类型是不同的,但C++的隐藏规则:只隐藏名字(hiding names ...

  2. 基于Service Worker实现WebRTC局域网大文件传输能力

    基于Service Worker实现WebRTC局域网大文件传输能力 Service Worker是一种驻留在用户浏览器后台的脚本,能够拦截和处理网络请求,从而实现丰富的离线体验.缓存管理和网络效率优 ...

  3. ASP.NET Core Library – Hangfire

    前言 以前写过 Hangfire 的学习笔记, 但写的很乱. 这篇做个整理. 介绍 Hangfire 是用来做 server task 的, 比如: background job, delay job ...

  4. Identity – User Login, Forgot Password, Reset Password, Logout

    前言 这篇来聊聊常见操作. 会讲到: Create Account Login Logout Change Password Reset Password (by email) External Lo ...

  5. CF228E 题解

    CF228E 题解 题目简述 给定一个 \(n\) 个点,\(m\) 条边的无向图,每条边都为 \(0\) 或 \(1\),可以进行若干次操作,与此点相连的所有点权值取反,求一种方案使得所有边都变为 ...

  6. chatGPT能做职业规划?看完之后发现3年软测白做了!

    "每天都是重复.单调的工作,收入不理想,想跳槽无力,学习又没有动力和方向,不知道未来的发展在哪里,甚至想转行·····" 做测试久了,很多人都有诸如此类的疑惑,不想一直停留在测试需 ...

  7. ConcurrentLinkedQueue详解(图文并茂)

    前言 ConcurrentLinkedQueue是基于链接节点的无界线程安全队列.此队列按照FIFO(先进先出)原则对元素进行排序.队列的头部是队列中存在时间最长的元素,而队列的尾部则是最近添加的元素 ...

  8. 3.1 gradio的基本使用详解

    ·gr.Text:用于文本输入,适用于自然语言处理任务的模型. gr.Image:用于图像上传,适用于图像处理或计算机视觉模型. ·gr.Audio:用于音频输入,适用于语音识别或音频处理模型. im ...

  9. Spirng Aop 实现自定义注解及实现

    需求:日志记录 需要记录当前用户访问的每个接口对应的前端页面功能信息 声明一个注解 @Documented @Retention(RetentionPolicy.RUNTIME) @Target({E ...

  10. 《Vue.js 设计与实现》读书笔记 - 第5章、非原始值的响应式方案

    第5章.非原始值的响应式方案 5.1 理解 Proxy 和 Reflect Proxy Proxy 只能代理对象,不能代理非对象原始值,比如字符串. Proxy 会拦截对对象的基本语义,并重新定义对象 ...