Java中使用的“ instanceof”运算符是什么?


163

instanceof运算符是做什么用的?我看过类似的东西

if (source instanceof Button) {
    //...
} else {
    //...
}

但是,这对我来说都没有意义。我已经完成了研究,但只提出了没有任何解释的示例。


38
在这里提出问题没有错,但是,如果您正在学习Java,则可能想买一本书。任何一部体面的Java书籍都将回答这个问题,而您接下来将拥有1000本书。
总统詹姆斯·波尔克(James K. Polk)

这样的操作员具有许多特定用途。如果它要求解释对您没有意义的示例之一,则将是一个特定的问题。
2013年

2
下面的答案是正确的,但是请注意,instanceof是一个过度使用的运算符(十分之九),可以通过适当使用多态来代替(并非总是,但经常使用)
Richard Tingle 2013年

我要比理查德进一步:我从未见过有效使用instanceof的情况。它仅适用于设计不良的代码之上的快速黑客攻击。如果您不喜欢OOP,请使用另一种语言编写(有很多)。只需对instanceof说“不”!
Scott Biggs

5
@ScottBiggs替代instanceof时是否有很好的替代方法equals
本·亚伦森

Answers:


228

instanceof关键字是用于测试对象是否为二进制运算符(实例)是否为给定Type的子类型的。

想像:

interface Domestic {}
class Animal {}
class Dog extends Animal implements Domestic {}
class Cat extends Animal implements Domestic {}

想象一个用创建的dog 对象Object dog = new Dog(),然后:

dog instanceof Domestic // true - Dog implements Domestic
dog instanceof Animal   // true - Dog extends Animal
dog instanceof Dog      // true - Dog is Dog
dog instanceof Object   // true - Object is the parent type of all objects

然而,随着Object animal = new Animal();

animal instanceof Dog // false

因为它Animal是的Dog精写类型,可能较少。

和,

dog instanceof Cat // does not even compile!

这是因为Dog既不是的子类型也不是的超类型Cat,并且它也不实现它。

请注意,dog上面用于的变量是类型Object。这是instanceof一个运行时操作,将我们带到一个用例:在运行时根据对象类型做出不同的反应

注意事项:expressionThatIsNull instanceof T对于所有Types都是false T

快乐的编码。


14
我只是试过- Object dog = new Dog(); System.out.println(dog instanceof Cat);。这样可以编译并打印false。编译器不允许在编译时确定dog不能为Cat的(按照JLS中的规则)
Erwin Bolwidt

@ErwinBolwidt尝试尝试时犯了一个错误。对于任何想知道的人:JLS Section 15.20.2是您所需要的。举一个最小的无效示例:boolean b = "foo" instanceof Integer;
Felix S

3
@FelixS您需要重新阅读答案。答案是关于Object indirect = ...; if (indirect instanceof Something)。这并不是if (literal instanceof Something)您似乎要假设的那样。
Erwin Bolwidt

1
@ErwinBolwidt哦,对,我一定已经跳过了Object dog。我的错!
Felix S

dog instanceof Cat // does not even compile!(因为它是一类)。如果Cat是接口,它将进行编译。
Hamza Belmellouki

44

如果表达式的左侧是右侧的类名的实例,则它是一个返回true的运算符。

这样想吧。假设您街区的所有房屋都是根据相同的蓝图建造的。十间房屋(对象),一套蓝图(类定义)。

instanceof当您有一组对象并且不确定它们是什么时,它是一个有用的工具。假设您在表单上有一组控件。您想读取其中任何复选框的选中状态,但是不能向普通的旧对象询问其选中状态。相反,您将看到每个对象是否都是一个复选框,如果是,则将其强制转换为一个复选框并检查其属性。

if (obj instanceof Checkbox)
{
    Checkbox cb = (Checkbox)obj;
    boolean state = cb.getState();
}

15
也就是说,使用instanceof可以安全地进行下转换。
2013年

29

本网站所述

instanceof操作者可用于测试对象是否是特定类型的...

if (objectReference instanceof type)

一个简单的例子:

String s = "Hello World!"
return s instanceof String;
//result --> true

但是,instanceof对空引用变量/表达式应用返回false。

String s = null;
return s instanceof String;
//result --> false

由于子类是其超类的“类型”,因此您可以使用 instanceof来验证此...

class Parent {
    public Parent() {}
}

class Child extends Parent {
    public Child() {
        super();
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        System.out.println( child instanceof Parent );
    }
}
//result --> true

我希望这有帮助!


15

此运算符使您可以确定对象的类型。它返回一个boolean值。

例如

package test;

import java.util.Date;
import java.util.Map;
import java.util.HashMap;

public class instanceoftest
{
    public static void main(String args[])
    {
        Map m=new HashMap();
        System.out.println("Returns a boolean value "+(m instanceof Map));
        System.out.println("Returns a boolean value "+(m instanceof HashMap));
        System.out.println("Returns a boolean value "+(m instanceof Object));
        System.out.println("Returns a boolean value "+(m instanceof Date));
    }
} 

输出为:

Returns a boolean value true
Returns a boolean value true
Returns a boolean value true
Returns a boolean value false


4

如其他答案中所述,的典型用法instanceof是用于检查标识符是否引用了更具体的类型。例:

Object someobject = ... some code which gets something that might be a button ...
if (someobject instanceof Button) {
    // then if someobject is in fact a button this block gets executed
} else {
    // otherwise execute this block
}

但是请注意,左手表达式的类型必须是右手表达式的父类型(请参见JLS 15.20.2Java Puzzlers,#50,pp114)。例如,以下将无法编译:

public class Test {
    public static void main(String [] args) {
        System.out.println(new Test() instanceof String); // will fail to compile
    }
}

无法使用以下消息进行编译:

Test.java:6: error: inconvertible types
        System.out.println(t instanceof String);
                       ^
  required: String
  found:    Test
1 error

由于Test不是的父类String。OTOH,它可以完美编译false并按预期打印:

public class Test {
    public static void main(String [] args) {
        Object t = new Test();
        // compiles fine since Object is a parent class to String
        System.out.println(t instanceof String); 
    }
}

感谢您链接到规范!
jpaugh

1
public class Animal{ float age; }

public class Lion extends Animal { int claws;}

public class Jungle {
    public static void main(String args[]) {

        Animal animal = new Animal(); 
        Animal animal2 = new Lion(); 
        Lion lion = new Lion(); 
        Animal animal3 = new Animal(); 
        Lion lion2 = new Animal();   //won't compile (can't reference super class object with sub class reference variable) 

        if(animal instanceof Lion)  //false

        if(animal2 instanceof Lion)  //true

        if(lion insanceof Lion) //true

        if(animal3 instanceof Animal) //true 

    }
}

1

可以用作相等性检查中的简写。

所以这段代码

if(ob != null && this.getClass() == ob.getClass) {
}

可以写成

if(ob instanceOf ClassA) {
}

1

大多数人已经正确解释了这个问题的“内容”,但是没有人正确地解释了“如何”。

所以这是一个简单的例子:

String s = new String("Hello");
if (s instanceof String) System.out.println("s is instance of String"); // True
if (s instanceof Object) System.out.println("s is instance of Object"); // True
//if (s instanceof StringBuffer) System.out.println("s is instance of StringBuffer"); // Compile error
Object o = (Object)s;
if (o instanceof StringBuffer) System.out.println("o is instance of StringBuffer"); //No error, returns False
else System.out.println("Not an instance of StringBuffer"); // 
if (o instanceof String) System.out.println("o is instance of String"); //True

输出:

s is instance of String
s is instance of Object
Not an instance of StringBuffer
o is instance of String

s与StringBuffer 进行比较时,编译器错误的原因已在docs中进行了充分说明:

您可以使用它来测试对象是实现特定接口的类的实例,子类的实例还是类的实例。

这意味着LHS必须是RHS的实例,或者是实现RHS或扩展RHS的类。

那么如何使用use instanceof?
由于每个类都扩展了对象,因此将LHS类型转换为对象将始终对您有利:

String s = new String("Hello");
if ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //No compiler error now :)
else System.out.println("Not an instance of StringBuffer");

输出:

Not an instance of StringBuffer

在最后一个示例中,为什么返回“不是StringBuffer的实例”?由于您将L广播到Object并检查它是否是RHS的实例,因此 if ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //shouldn't this be true,由于我们要将S广播到Object?
sofs1

因为s是对String对象的引用(Java与C ++不同,所以它采用了动态多态性),而String不是StringBuffer的子类。
sziraqui


0

当您想了解特定对象的实例时,关键字的实例非常有用。

假设您抛出异常,并且在捕获时执行总和自定义操作,然后根据逻辑(抛出或日志等)再次继续

示例:1)用户创建了自定义异常“ InvalidExtensionsException”,并根据逻辑将其抛出

2)现在在catch块中catch(Exception e){如果异常类型为“ InvalidExtensionsException”,则执行求和逻辑

InvalidExtensionsException InvalidException =(InvalidExtensionsException)e;

3)如果不检查实例且异常类型为Null指针异常,则代码将中断。

因此,您的逻辑应该在if(e instanceof InvalidExtensionsException){InvalidExtensionsException InvalidException =(InvalidExtensionsException)e; }

上面的示例是错误的编码实践,但是此示例可帮助您了解其实例的使用。


0

最好的解释是jls。始终尝试检查消息来源。在那里,您将获得最佳答案以及更多其他信息。在此处复制一些部分:

instanceof运算符的RelationalExpression操作数的类型必须为引用类型或null类型;否则,将发生编译时错误。

如果在instanceof运算符之后提到的ReferenceType不表示可校正的引用类型,则是编译时错误(第4.7节)。

如果将RelationalExpression对ReferenceType的强制转换(第15.16节)作为编译时错误,则关系表达式的实例同样会产生编译时错误。在这种情况下,instanceof表达式的结果永远不可能为真。


0

java instanceof运算符用于测试对象是否是指定类型(类,子类或接口)的实例。

java中的instanceof也称为type,comparison operator因为它将实例与type进行比较。它返回truefalse。如果我们对instanceof运算符应用任何具有null值的变量,则它将返回false

在包含JEP 305的 JDK 14+中,我们还可以为instanceof

模式基本上是测试一个值是否具有某种类型,并且当它具有匹配类型时可以从该值中提取信息。模式匹配可以更清晰有效地表达系统中的通用逻辑,即从对象中有条件地删除组件。

Java 14之前

if (obj instanceof String) {
    String str = (String) obj; // need to declare and cast again the object
    .. str.contains(..) ..
}else{
     str = ....
}

Java 14增强功能

if (!(obj instanceof String str)) {
    .. str.contains(..) .. // no need to declare str object again with casting
} else {
    .. str....
}

我们还可以将类型检查和其他条件结合在一起

if (obj instanceof String str && str.length() > 4) {.. str.contains(..) ..}

模式匹配的使用instanceof应减少Java程序中显式强制转换的总数。

PSinstanceOf仅当对象不为null时才匹配,然后只能将其分配给str


-1
class Test48{
public static void main (String args[]){
Object Obj=new Hello();
//Hello obj=new Hello;
System.out.println(Obj instanceof String);
System.out.println(Obj instanceof Hello);
System.out.println(Obj instanceof Object);
Hello h=null;
System.out.println(h instanceof Hello);
System.out.println(h instanceof Object);
}
}  

1
不要仅在StackOverflow上发布代码答案。请继续并添加说明。
L. Guthardt '18

-2

非常简单的代码示例:

If (object1 instanceof Class1) {
   // do something
} else if (object1 instanceof Class2) {
   // do something different
}

小心点 在上面的示例中,如果Class1是Object,则第一个比较将始终为true。因此,就像例外一样,层次顺序很重要!


-2

您可以使用Map对的实例进行更高的抽象

private final Map<Class, Consumer<String>> actions = new HashMap<>();

然后让这样的地图添加一些动作:

actions.put(String.class, new Consumer<String>() {
        @Override
        public void accept(String s) {
           System.out.println("action for String");       
        }
    };

然后拥有一个未知类型的对象,您可以从该映射中执行特定操作:

actions.get(someObject).accept(someObject)

-2

instanceof运算符用于检查对象是否为指定类型的实例。(类,子类或接口)。

instanceof也称为类型比较运算符,因为它会将实例与类型进行比较。它返回true或false。

class Simple1 {  
public static void main(String args[]) {  
Simple1 s=new Simple1();  
System.out.println(s instanceof Simple1); //true  
}  
}  

如果我们对任何具有null值的变量应用instanceof运算符,则它将返回false。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.