例如右边的语句:
Person person = new Woman();//Woman继承自Person
JVM的操作应该是将person放在栈中,作为一个堆中分配的Woman对象的指针。
我的问题是,jvm怎么能断定person是一个合法的指针声明?比如,我声明 Person person = new Dog();肯定会报错的。
这个应该和instanceof实现应该是一致的,故提出题目问题
------解决思路----------------------
这个涉及到编译期以及运行时的问题。
其实java的类型检查(检查引用是否合理)机制既有编译期的静态检查,也有运行时的动态检查。
静态时是根据一个显式类型(比如一个表达式的值的类型,一个变量的声明类型等)判断,比如说Person类的引用不能直接引用Object类的对象,也不能赋予一个Object类型的值。这样的特性给Java的运行时多态带来很多不便(父类将没办法再次转变为子类),好在一般编程语言都提供了强制类型转换,java也不例外。我们可以利用Object为所有类的父类这一点绕过所有的编译期检查,就像这样:
Integer x = (Integer)(Object)"明明不是整数";
这样会带来运行时的隐患(Integer的许多操作和数据成员在String类中是不存在的,或是错位的)。Java在设计之初就要避免使用不安全的指针,即是为了避免这样的危险行为(当发生程序员不自知的错误时可能导致程序崩溃,降低了整体稳定性)。于是java设计有运行时检查机制,即在实际执行转换时,进行对象实际类型的检查,以检验类型转换是否可以成立。这样就避免了上面所说的危险问题。上面的例子虽然能通过编译,但是在运行到这句话时检查会失败,抛出ClassCastException。
------解决思路----------------------
Person person = new Dog()这是静态类型检查,编译器在编译期确定实例类型在引用类型继承链上(语法分析中从符号表得到的),保证进入动态绑定时不会引发虚拟机错误。而instanceof是动态检查,obj instanceof Object和obj.getClass().equals(Object.class)是等效的(RTTI的实现),所以两者的实现不一致。
------解决思路----------------------
你这是把检查类型都想在了运行的时候。其实类型检查在编译和类加载的校验阶段进行的。