问题描述
packagetest;publicclassFather1{voidshow1(){}}packagetest;publicclassSon1extendsFather1{voidshow1(){}voidshow2(){}}packagetest;publicclassFather1VsShow1{publicstaticvoidmain(String[]args){Father1father1=newSon1();father1.show1();//这里就不能按照下方注释的那样去理解了,因为冲突,父类的引用找不到子类的show2方法Son1son1=newSon1();son1.show1();son1.show2();//这里可以调用show2方法,因为根据内存运行图,自己对象里有的,不需要到父类中找}}如注释所说,在不是多态的情况理解,根据画内存图,自己对象里有的,不需要到父类中找相应调用的方法,但在多态情况下,这么理解,就会自相矛盾,因为按照上述代码写的,如果father1.show2()就会报错,father1明明指向的是子类对象,也就是说,在子类对象里是可以找的到show2方法的,但JVM又会报错,说找不到show2方法,这也正是我不理解的地方,请高手指点迷津!
解决方案
解决方案二:
Father1father1=newSon1();father1.show1();father1这个引用的类型是Father1,至于实际对象是什么类型是在运行期才能够确定的,而不是编译期确定的,所以如果你调用show2方法,当然不行,编译通不过啊,编译器并不知道你这个引用实际指向什么类型啊。但是你可以强制类型转换是可以的。例如:((Son1)father1).show2();
解决方案三:
或者你可以用子类重写父类的方法
解决方案四:
Son1extendsFather1所以Son1中的方法show1()就相当于是重写了父类的方法、show2()是Son1中自己独有的方法、
解决方案五:
难道你要让编译器遇到一个类时要一直检查他的子类再子类再在子类。。。。。吗?看看他们到底有什么方法吗?然后在检查一下他是不是一个子类的引用然后确定他到底有多少方法吗?如果这样那编译器得做多少工作啊。不管他是不是一个子类的引用他都不会去看看他的子类有什么方法的他只会检查他有什么方法他继承了他父亲的什么方法他爷爷的方法。。。。。。就像你能了解你父亲,你爷爷,你的十八代祖宗的一生但你却不能了解你儿子,你孙子的一生(除非白发人送黑发人,这也太例外了吧,java也不可能考虑这例外吧)......
解决方案六:
一楼正解,编译时看的是引用的声明,像Father1father1=newSon1();编译器只会知道father1的声明类型是Father1,找方法也在Father1中找,所以Father1中有show1方法,故father1.show1()调用成功,但是Father1中没有show2方法,故father1.show2()编译出错。至于father1.show1()最终调用的是子类的show1方法,则就是动态绑定的问题。动态绑定:运行时自动确定调用哪个方法的现象。动态绑定调用的全过程:(如果方法为private,final,static则采用静态绑定,编译时已经索引好具体调用的地址)-编译器查看对象的声明类型和调用的方法名,然后一一列举出声明类型和该类型的超类中同方法名的所有方法(超类中的需要是public属性的);-根据调用方法的参数,选择合适的一个函数(合适指的是类型完全相同或者自动转换类型后符合)。如果没找到那么直接报错。-虚拟机确定对象的实际类型,寻找该类型下的合适方法调用,如果没找到则到超类中去找。
解决方案七:
Father1father1=newSon1();father1.show1();father1是Father1型的,在Father1中没有show2()方法,当然找不到啦,就这么简单