• 【疯狂Java_突破程序员基本功的16课】charpt7 面向对象的陷阱


    7.1 instanceof运算符的陷阱

    instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个 操作数通常是一个类(也可以是接口,可以把接口当成一种特殊的类),它用于判断前面的对象是否是后面的类或其子类、实现类的实例。如果是,返回true,否则返回false。

    根据java语言规范,使用instanceof运算符有一个限制:instanceof运算符前面操作数的编译时类型必须是如下3种情况:

    • 要么与后面的类相同;
    • 要么是后面的类的父类;
    • 要么是后面类型的子类

    如果前面操作数的编译时类型与后面的类型没有任何关系,程序将无法通过编译。

    观察下面程序:

    public class InstanceofTest {
        public static void main(String[] args) {
            Object str = "疯狂Java讲义";
            // 执行强制类型转换,让math引用原来str引用的对象
            Math math = (Math) str;              // 1
            System.out.println("字符串是否是String的实例:" + (math instanceof String));     //2
        }
    }

    粗看之下,可能会得到一个结论:这个程序不能通过编译,编译期应该在1行代码处提示编译错误,因为1行代码尝试把一个String强制转型为Math。但是编译该程序时,却发现编译期提示如下的错误:

    InstanceofTest.java:6: 不可转换的类型
    找到: java.lang.Math
    需要: java.lang.String
            System.out.println("字符串是否是String的实例:" + (math instanceof String));
                                                     ^
    1 错误

    至于1行出的代码为何没有出现编译错误,这和强制转型的机制有关。对于Java的强制转型而言,也可以分为编译、运行两个阶段来分析它。

    • 在编译阶段,强制转型要求被转型变量的编译时类型必须是如下3种情况之一:
    1. 被转型变量的编译时类型与目标类型相同;
    2. 被转型变量的编译时类型是目标类型的父类;
    3. 被转型变量的编译时类型是目标类型子类,这种情况下可以自动向上转型,无需强制转换。

    如果被转型变量的编译时类型与目标类型没有任何继承关系,编译期将提示错误。通过上面的分析可以看出,强制类型转换的编译阶段只关心引用变量的编译时类型,至于该引用变量实际引用对象的类型,编译器并不关心,也没法关心。

    • 在运行阶段,被转型变量所引用对象的时实际类型必须是目标类型的实例,或者是目标类型的子类、实现类的实例,否则在运行时将引发ClassCastException异常。

    另外如果给一个引用变量赋值null,例如以下程序,将返回false:

    public class InstanceofTest {
        public static void main(String[] args) {
            String str = null;
            System.out.println("null是否是String的实例:" + (str instanceof String));
        }
    }
  • 相关阅读:
    原型设计工具比较及实践
    2020软件工程最后一次作业
    2020软件工程第四次作业
    2020软件工程第三次作业
    2020软件工程第二次作业
    2020软件工程第一次作业
    AJAX
    MY JQUERY NOTES
    2020软件工程最后一次作业
    2020软件工程第四次作业(第二次结对)
  • 原文地址:https://www.cnblogs.com/yangfengtao/p/2787814.html
Copyright © 2020-2023  润新知