instanceof运算符用法
运算符是双目运算符,左面的操作元是一个对象实例,右面是一个类.当
左面的对象是右面的类创建的对象时,该运算符运算的结果是true,否则是false
说明:
(1).一个类的实例包括本身的实例,以及所有直接或间接子类的实例
(2).instanceof左边操作元显式声明的类型与右边操作元必须是同种类或有继承关系,
即位于继承树的同一个分支上,否则会编译出错
double obj=1; if(obj instanceof Double){ System.out.println("true"); }
报 "Incompatible conditional operand types double and Double" 错误
obj 必须是对象的实例。不能是基础数据类型。
String obj=1.0+""; if(obj instanceof Double){ System.out.println("true"); }
报 "Incompatible conditional operand types String and Double" 错误
String 和 Double 不是位于继承树的同一个分支上。
if(null instanceof Object){ System.out.println("true"); }else{ System.out.println("false"); } String obj=null; if(obj instanceof Object){ System.out.println("true"); }else{ System.out.println("false"); }
打印都为 false. null用操作符instanceof测试任何类型时都是返回false的。
if(obj instanceof null){ System.out.println("true"); }else{ System.out.println("false"); }
编译出错。报"Syntax error on token "null", invalid ReferenceType" 错误。
public class Test { public static void main(String[] args){ System.out.println(new Student() instanceof String); //compile time error System.out.println(new Student() instanceof Exception); //compile time error System.out.println(new Student() instanceof Object); //compilation and output true System.out.println(new Student() instanceof List); //compilation and output false System.out.println(new Student() instanceof List<?>); //compilation and output false System.out.println(new Student() instanceof List<String>); //compile time error
System.out.println(new Student() instanceof List<Object>); //compile time error System.out.println(new String() instanceof List); //compile time error System.out.println(new String() instanceof List<?>); //compile time error System.out.println(null instanceof Object); //compilation and output false } } class Student{ }
看到上面的测试结果可能会有这样那样的疑惑,为什么Student对象测试String的时候是编译错误,而测试List的时候又能够通过(难道是instanceof对接口在编译时不作检查呢,还是由于List类型本身在编译时不确定具体类型导致的),但是后面你又会发现如果是List<String>的时候编译就不通过了(看来前面的猜测是错误的,他对接口是要做检查的),可是往后面看,你又会纳闷String测试List还是List<?>的时候,直接在编译期就报错了,这跟Student对象测试List和List<?>的结果大不同,可能此时你有点相当不解了。我们这个时候翻看java对instanceof操作符的说明时,发现instanceof的这些表现都是跟cast操作符是有点关系的,就是说当我们在instanceof方法时,编译器会检查这个对象能够cast到右边的类型,如果不能cast则直接报错,如果不能确定类型,则通过编译,具体看运行时定。
这里可能还有一个疑惑,我们Student已经确定类型了啊,List类型也是确定的啊,为什么能够编译通过呢,而String却不行呢(难道是自己定义的类和系统定义的类在编译处理上有不同),这里java没有做特别的说明,但是我想可能是因为final关键字的区别造成的,我们发现不论String、Integer、Long等都是最终类,他们的处理类似于编译器对常量的处理,因为编译器知道这个类在运行期间是不会有改变的,故而编译器在编译期间认为他自己能够确定这个类的最终类型。而对于自己定义的类呢(我试过系统的非最终类Hashtable、HashMap等,测试和我们自定义的类的结果一样,可以通过编译),由于不是最终类,可能编译器认为他可能在运行期间会有改变的可能,故而不把他作最为确定的类型处理,故而可以通过编译。其实当我们在自定义的类前面加上final关键字的时候,其表现就跟String、Integer、Long这些最终类测试instanceof表现的一样了。