PDF 课件和源代码下载地址:
https://gitee.com/geektime-geekbang/LetsJava
作者回复: 往根节点撸,这样说比较没有歧义。
作者回复: 声明引用实际上就是在“内存”(可以是堆,比如是一个成员变量,也可以是线程栈,比如说说一个局部变量或者参数)中建立里一块(32bit或者64bit大小)引用“对象”的内存地址指向,这个引用具体指向的对象可以是他的子类,但是只能在这个内存区域(32bit或者64bit大小,和对象类型以及大小没关系,只是一个地址)中放入“子类或者本类的对象的地址”。所以在调用(调用什么?方法吗?)的时候,(后面感觉有点模糊,你可以再说的清楚一点)返回的值是由实际的子类对象的值,只不过这个值的类型是子类的类型,在重载的时候,标签对应的是这个值的类型。 其实覆盖不复杂,核心就是:寻找调用哪个方法。这里有两个角色:1)引用的类型,调用的方法签名必须是这个类型中定义了的;2)引用实际指向的对象,它决定的是通过这个签名调用的实际是哪个类的方法。 结合super,this,重载,问题会变得复杂,但是万变不离其宗,也就是上面的亮点。 -------- 以下内容涉及堆和栈,属于超纲 -------- 至于底层的逻辑,你的描述中有一个可能的错误,就是认为引用是在堆里建立一块内存。其实引用就是在内存里建立一个引用。也就是我们说的对象的“名”。 这里说的内存,可能是栈上的,比如下面的代码: public void test(){ Person person = new Person(); } person是个局部变量,那就是在栈内存上。 Person类的定义如果如下的话: public class Person{ private Company company = null; } 那么company这个引用就是在堆上。因为整个Person对象都在在堆上分配的内存,所有对象都是在堆上分配的内存。只有执行方法的时候,需要的局部变量和参数,才是在栈上分配内存。
作者回复: ✅
作者回复: 继承链+方法重载的情况,参数匹配确实比较麻烦。当我们在设计程序的时候,如果发现需要涉及到这方面的问题,首先要想的是避免,而不是如何正确的使用。没错,要避免出这种麻烦的,饶脑子的(代码不易读)的情况。 实际上大多数的设计的好的类库也会避免这种情况出现。这部分知识我在课程中也没有深入讲述,也正是出于这两点1)确实有点绕 2)确实不大用得到。也就是说,学习的投入产出比太低。尤其是对于初学者,还容易绕着绕着绕迷糊了。 到底应该调用哪个方法,这个问题到底有多麻烦呢,Java Language Specification上有详尽的描述 (15.12.2.5. Choosing the Most Specific Method) https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.12.2.5 当然这里还包括了覆盖和重载等内容。就你当前这个问题来说,我试下来和你的结果不大一样。如下代码(在包tta里)就已经报错了,错误内容是“Error:(16, 12) java: reference to overload is ambiguous both method overload(tta.D,tta.D) in tta.AppMain and method overload(tta.C,tta.F) in tta.AppMain match” 错误内容和你理解的一样,就是ambiguous method call,Java无法帮我们选择一个唯一的“最应该”调用的方法。 public class AppMain { public static void main(String[] args) { AppMain appMain = new AppMain(); C c = null; D d = null; E e = null; F f = null; appMain.overload(c,d); } public void overload(D d, D dd) { System.out.println("dd"); } public void overload(C c, F f) { System.out.println("cf"); } }
作者回复: override(覆盖)和overload(重载)本身就是两个东西。 override和继承有关,子类如果有签名相同的方法,会覆盖父类中的方法。overload是同一个类中的方法可以有不同的参数。 这两个概念不难,难在实际代码中的应用。
作者回复: 其实继承跟方法的重载一点关系也没有 有一点关系就是子类会继承父类的方法,这些继承来的方法也是参与重载的。 还有一个关系就是另一个纬度的,比如A是B的父类,那么当A,或者B作为方法的参数的时候,也会参与到重载的类型判定。
作者回复: new出来的对象(无论在哪里new的)都是在堆上的。对象里的成员变量也都是在堆上的。 方法里的数据都是在栈上的
作者回复: 是的,环环相扣,环环相通
作者回复: 静态多态:只看引用的类型,不看引用指向的对象的类型。
作者回复: (-: