
在以下示例中
> test instanceof java.util.Map返回false
> test instanceof 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);
}
}
例如:
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);
现在,事情变得有趣了.在下面的示例中,我们有一个非最终类Test和一个最终类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.中,我们正在测试针对类的参考测试.在这种情况下,编译器可以确定测试变量引用的对象不能扩展java.util.Map,因为Test类不扩展java.util.Map,并且Test的每个子类都将扩展类Test(或它的一个子类),所以它不能同时扩展java.util.Map.
在3.中,我们正在针对接口测试参考testFinal.它看起来与1.类似,但它完全不同,因为类TestFinal不能被子类化,所以TestFinal的实例也无法成为java.util.Map的实例.
在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.
>类似于2.
结论:
A. null instanceof AnyClass(或AnyInterface)总是返回false
B. myreferenceToAClass instanceof MyInterface可能会返回true或false,具体取决于上下文
C. myreferenceToAnInterface instanceof AnyClass(或AnyInterface)可能返回true或false,具体取决于上下文
D. myreferenceToAClass的MyClass实例:
– 如果myreference的类不属于MyClass的层次结构树,则编译错误
– 如果myreference的类属于MyClass的层次结构树,则返回true或false,具体取决于上下文
转载注明原文:java – 为什么instanceof有时不编译,有时返回false? - 乐贴网