instanceof 运算符在 Java 中用于测试引用是否指向作为特定类或接口实例的对象。
例如:
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 和 Map 不兼容"
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. 中,我们针对 Interface (java.util.Map) 测试参考测试。编译器不能确定 test 不是 java.util.Map 的实例。事实上,test 可能会引用一个对象,该对象的类实现了 java.util.Map 并扩展了类 Test。因此,没有编译错误,但它在运行时返回 false。
在 2. 中,我们针对 Class 测试参考测试。在这种情况下,编译器可以确定 test 变量引用的对象不能扩展 java.util.Map,因为 Test 类没有扩展 java.util.Map,并且 Test 的每个子类都会扩展 Test 类(或它的子类之一),因此它不能同时扩展 java.util.Map。
在 3. 中,我们针对 Interface 测试参考 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是一个Interface的引用,理论上可以存在实现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 instanceof MyClass:
- 如果 myreference 的类不属于 MyClass 的层次结构树,则编译错误
- 返回真或假,取决于上下文,如果 myreference 的类属于 MyClass 的层次结构树