为什么instanceof有时不编译,有时会返回false?

时间:2016-08-30 22:21:54

标签: java class inheritance interface instanceof

在以下示例中

  • test.of java.util.Map返回false

  • java.util.HashMap的测试实例不编译

  • mymap instanceof Set返回false 和
  • mymap instanceof HashSet返回false(为什么要编译?!?)

为什么呢?它们看起来非常相似!

import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;

public class InstanceofTest {
    public static class Test {}
    public static void main(String[] args) {
        // -- left operand references a Class instance
        Test test = null;

        // 1. outputs: false
        System.out.println(test instanceof Map);

        // 2. COMPILATION ERROR
        System.out.println(test instanceof HashMap);


        // -- left operand references an Interface instance
        Map mymap = new HashMap();

        // 3. outputs: false
        System.out.println(mymap instanceof Set);

        // 4. outputs: false
        System.out.println(mymap instanceof HashSet);
    }
}

1 个答案:

答案 0 :(得分:6)

在Java中使用instanceof运算符来测试引用是否指向作为特定类或接口的实例的对象。

例如:

String myString="test string";
System.out.println(myString instanceof String); // true, myString is a String
System.out.println(myString instanceof Object); // true, myString is a String, and so it is an Object, too

对于 null 引用, instanceof 始终返回 false

System.out.println(null instanceof Object); // false, null doesn't reference any object

有时编译器确定引用永远不能是特定类的实例,因为引用的类型不在特定类的层次结构树中。 例如,在以下示例中,编译器会抱怨: " 不兼容的条件操作数类型字符串和地图 "

String myString="test string";
System.out.println(myString instanceof java.util.Map);

现在,事情变得有趣了。在以下示例中,我们有一个非最终类测试和一个最终类TestFinal

public class InstanceofTest {
    public static class Test {}
    public static final class TestFinal {}
    public static void main(String[] args) {

        Test test = null;

         // 1. outputs: false
        System.out.println(test instanceof java.util.Map);

        // 2. COMPILATION ERROR
        System.out.println(test instanceof java.util.HashMap);

        TestFinal testFinal = null;

        // 3. COMPILATION ERROR
        System.out.println(testFinal instanceof java.util.Map);

        // 4. COMPILATION ERROR
        System.out.println(testFinal instanceof java.util.HashMap); 
    }
}

为什么它在1.中返回false,但它不会在2.,3.,4中编译。?

在1.中,我们正在针对接口(java.util.Map)测试参考测试。编译器无法确定测试不是java.util.Map的实例。实际上,测试可能会引用一个对象,该对象的类实现了java.util.Map并扩展了类Test。因此,没有编译错误,但它在运行时返回false。

在2.,我们正在针对 Class 测试参考测试。在这种情况下,编译器可以确定测试变量引用的对象不能扩展java.util.Map,因为Test类不会扩展java.util.Map,并且Test的每个子类都会扩展类Test (或其子类之一),因此它不能同时扩展java.util.Map。

在3.中,我们正在针对接口测试参考testFinal。它看起来与1.类似,但它完全不同,因为类TestFinal不能被子类化,所以TestFinal的实例也不可能是java.util.Map的实例。 / p>

在4.,我们正在针对 Class 测试参考testFinal。与2.一样,编译器可以确保testFinal变量引用的对象不能扩展java.util.Map。

还有另一个案例值得考虑:

    List myList = new ArrayList();

    // 5. outputs: false
    System.out.println(myList instanceof java.util.Map);

    // 6. outputs: false
    System.out.println(myList instanceof java.util.HashMap);

    ArrayList myArrayList = new ArrayList();

    // 7. outputs: false
    System.out.println(myArrayList instanceof java.util.Map);

    // 8. COMPILATION ERROR
    System.out.println(myArrayList instanceof java.util.HashMap);

在5.,6中,myList是对接口的引用,理论上它可以存在一个实现Map或扩展HashMap的List实例。

  1. 类似于1.

  2. 类似于2.

  3. 结论:

    一个。 null instanceof AnyClass (或 AnyInterface )始终返回false

    B中。 myreferenceToAClass instanceof MyInterface 可能会返回true或false,具体取决于上下文

    ℃。 myreferenceToAnInterface instanceof AnyClass (或 AnyInterface )可能会返回true或false,具体取决于上下文

    d。 myreferenceToAClass instanceof MyClass :    - 如果myreference的类不属于MyClass的层次结构树,则编译错误    - 如果myreference的类属于MyClass的层次结构树,则返回true或false,具体取决于上下文