同步操作将从 帝八哥/JavaBooks 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
要说,封装和继承呀,问的比较少,还是多态问的多一点,能体现出来一定的钻研程度。
面试官:咱们聊聊多态?你是怎么理解多态的呀?
我:那我可就要按照我的意思去讲了。
三要素:加黑的地方!
首先我觉得即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
举个例子:
任何事物的多个姿态,多个形态。比如,你说一个猫在吃东西,同样的,你也能说一个动物在吃东西。
public class Test {
public static void main(String[] args){
Animal animal = new Cat();
animal.eat() // 猫也会吃饭
// 你看到了一只猫,同样它也是动物
// 比如有很多其他种类继承了动物哈,
// 当编译期间的animal引用变量,到底指的哪个实例对象,(重要)(主语是引用变量)
// 或者该引用调用的eat方法,到底是哪个实例对象的eat,编译期间恐怕不知道哦(主语是引用变量)
// 只有运行期间,哦哦, 原来是猫的eat方法哇...
}
}
所以多态的表现形式:
首先要说:首先当程序运行需要某个类时,类加载器会将相应的class文件载入到JVM中,并在方法区建立该类的类型信息(包括方法代码,类变量、成员变量以及方法表。(标黑的这个玩意)
面试官:方法表有啥?
我:方法表的结构如同字段表一样,依次包括了访问标志、名称索引、描述符索引、属性表集合几项。
接着回答:方法表是实现动态调用的核心。为了优化对象调用方法的速度,方法区的类型信息会增加一个指针,该指针指向记录该类方法的方法表,方法表中的每一个项都是对应方法的指针。
到这里:就要分情况讨论了,一个是方法调用,一个是接口
先说方法调用:举个例子
class Person {
// 重写object的toString
public String toString(){
return "I'm a person.";
}
public void eat(){}
public void speak(){}
}
class Boy extends Person{
// 重写object的toString
public String toString(){
return "I'm a boy";
}
// 继承Person的speak
public void speak(){}
// 自己实现的自定义方法
public void fight(){}
}
class Girl extends Person{
// 重写object的toString
public String toString(){
return "I'm a girl";
}
// 继承Person的speak
public void speak(){}
// 自己实现的自定义方法
public void sing(){}
}
这张图的指向:你可以根据颜色对应上,注意方法表条目指向的具体的方法地址。其次注意蓝色部分其继承自于 Person 的方法 eat() 和 speak() 分别指向 Person 的方法实现和本身的实现。如果子类改写了父类的方法,那么子类和父类的那些同名的方法共享一个方法表项。因此,所有继承父类的子类的方法表中,其父类所定义的方法的偏移量也总是一个定值。Person 或 Object中的任意一个方法,在它们的方法表和其子类 Girl 和 Boy 的方法表中的位置 (index) 是一样的。这样 JVM 在调用实例方法其实只需要指定调用方法表中的第几个方法即可。
调用过程:
一个类可以实现多个接口,那么就像多继承一样,这样的话,在方法表中的索引就会不一样,所以Java 对于接口方法的调用是采用搜索方法表的方式。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。