Java的多态为何可以由子类实例化父类( 三 )
运行结果是:
obj instanceof Father
obj instanceof Son
obj is com.dumaisoft.zhihu.TestFatherAndSon$Son
因此,结论是:obj是一个Son类的一个实例。这个实例可以由一个Father类声明的变量持有,它并没有“实例化”一个Father类。
任何子类的实例,都可以合法的由其任一级父类、父接口声明的变量持有。但new的后面是什么类,就是“实例化”了一个什么类。
最后,来看你的问题“Java的多态为何可以由子类实例化父类”,这个问法说明你对多态、实例化两个概念都不清晰。
首先说实例化,“子类实例化父类”这种说法根本不成立。对象基本上都是由某个类“实例化”而来的,是什么类,就实例化出什么类的对象。调用子类的构造函数,不会实例化出来一个父类的对象,这一点前面已经详细说过了。
第二,多态。正是由于“任何子类的实例,都可以合法的由其任一级父类、父接口声明的变量持有”这个特性,才形成了Java中多态的概念。多态是指,某个父类或者父接口声明的变量,其行为却呈现出具体子类的行为,并且在很多情况下,由于具体的子类在编译时不确定,所以在运行时呈现出“多态”的模式。
希望对你有帮助。
■网友
你需要了解的并不是多态。。。而是JVM结构
简单的JVM是这样的。
有一个栈负责存储变量,也就是你的obj,obj2
有一个堆负责存储对象,也就是你两个子类对象。
你可以看到变量和对象是分开存储的,我们中间的等号改变的是他们的指针所指向的对象。(你如果没有学过C这类语言应该就没有指针的这个说法。)
父类类型变量改变了指向了子类的对象,这就是多态。我们使用的时候操作的是变量,所以在我们眼里尽管他指向了一个子类,其实他还是一个父类。
那么好吧,既然他只是一个父类变量那么我们就只能使用他的父类方法了,于是我们使用了子类里面重名的方法methods。
因为他是一个父类变量,指向一个子类对象,所以我们调用父类的时候调用的是子类对象里的重名方法。
不存在子类这么大怎么放进父类的概念,因为你控制的是变量,变量指向对象。
偶尔你以后会遇到一个常见异常叫做空指针异常,指的就是,你创建了一个变量但是没有赋予它对象。
■网友
程序最终运行,取决于你new的是谁,类型只是一种约束,比如,父类有一个 a 方法,子类重写了a,并且增加了 b 方法,假如 定义是这样 Father f=new son(),在内存中实际存在的是son的实例,那是不是可以调用 a 和 b 了呢,不是的,这时候 Father类型就起约束作用了,使用引用 f 你只能调用 a 方法,同时内存中存在的是son的实例,son存在 a ,所以运行的是son的 a 方法,假如son没有 a ,但是son有Father给的 a ,这时运行的就是Father的a,如果想要调用b,那就对引用 f 进行类型强制转换为son,相当于来自于Father类型的约束没有了。总之,内存中实例始终没有变化,一直都是son的实例,你定义的引用的类型,决定了你能使用哪些东西,实际使用的永远是内存中实例的东西。
■网友
其实并不是子类实例化父类,而是子类的实例隐藏自己,伪装成父类的样子(方法接口),但内核(方法实现)还是自己的。
从区分引用与对象的角度解释的话,是new一个子类的对象,赋值给一个父类的引用。JAVA中向上转型可以隐式转型,所以以后都是用父类的引用(编译时检查父类接口)访问子类的对象(执行时使用子类的实现)。
■网友
你可能需要了解的是 Jvm的 动态分派。
简单通俗地说就是,调用一个方法的时候的时候,jvm先在当前对象(操作数栈顶的)里边找,然后调用(当前对象是个子类对象,所以执行的就是重写过的代码啦),找不到就往父类去找的。(这个工作是invokevirtual指令做的)
推荐阅读
- #补贴#江阴为何迟迟没执行?|解忧帮 无锡:机动车报废有补贴
- OC为何跌出语言榜前十
- 何能|布局素质教育 教育巨头为何能迅速推进?
- dart这编程语言现在发展怎么样了,语法与Java,c#很相似,甚至更简洁
- 汽车|把车越卖越贵,全新领克01为何可以这样?
- 阿里程序员网上招人的情况为何如此多见
- 心流西春|为何你的后半箱油总是不耐用?油是正经油,问题可能出在这里
- 一粒尘埃的尘|为何很多新车不再设计“雾灯”,雾灯不重要吗?
- 环球车讯网|宝马MINI 为何在“迷你”的路上越跑越远?
- 汽车一起看|为何说国产高端SUV三强之首是名爵HS,领克和WEY竟无法反驳?