先来看一段重写的代码吧。
classLaoWang{publicvoidwrite(){System.out.println("老王写了一本《基督山伯爵》");}}publicclassXiaoWangextendsLaoWang{@Overridepublicvoidwrite(){System.out.println("小王写了一本《茶花女》");}}
重写的两个方法名相同,方法参数的个数也相同;不过一个方法在父类中,另外一个在子类中。就好像父类LaoWang有一个write()方法(无参),方法体是写一本《基督山伯爵》;子类XiaoWang重写了父类的write()方法(无参),但方法体是写一本《茶花女》。
来写一段测试代码。
publicclassOverridingTest{publicstaticvoidmain(String[]args){LaoWangwang=newXiaoWang();wang.write();}}
大家猜结果是什么?
小王写了一本《茶花女》
在上面的代码中,们声明了一个类型为LaoWang的变量wang。在编译期间,编译器会检查LaoWang类是否包含了write()方法,发现LaoWang类有,于是编译通过。在运行期间,new了一个XiaoWang对象,并将其赋值给wang,此时Java虚拟机知道wang引用的是XiaoWang对象,所以调用的是子类XiaoWang中的write()方法而不是父类LaoWang中的write()方法,因此输出结果为“小王写了一本《茶花女》”。
再来看一段重载的代码吧。
classLaoWang{publicvoidread(){System.out.println("老王读了一本《Web全栈开发进阶之路》");}publicvoidread(Stringbookname){System.out.println("老王读了一本《"+bookname+"》");}}
重载的两个方法名相同,但方法参数的个数不同,另外也不涉及到继承,两个方法在同一个类中。就好像类LaoWang有两个方法,名字都是read(),但一个有参数(书名),另外一个没有(只能读写死的一本书)。
来写一段测试代码。
publicclassOverloadingTest{publicstaticvoidmain(String[]args){LaoWangwang=newLaoWang();wang.read();wang.read("金瓶梅");}}
这结果就不用猜了。变量wang的类型为LaoWang,wang.read()调用的是无参的read()方法,因此先输出“老王读了一本《Web全栈开发进阶之路》”;wang.read("金瓶梅")调用的是有参的read(bookname)方法,因此后输出“老王读了一本《金瓶梅》”。在编译期间,编译器就知道这两个read()方法时不同的,因为它们的方法签名(=方法名称+方法参数)不同。
简单的来总结一下:
1)编译器无法决定调用哪个重写的方法,因为只从变量的类型上是无法做出判断的,要在运行时才能决定;但编译器可以明确地知道该调用哪个重载的方法,因为引用类型是确定的,参数个数决定了该调用哪个方法。
2)多态针对的是重写,而不是重载。
哎,后悔啊,早年我要是能把这道面试题吃透的话,也不用被老马刁难了。吟一首诗感慨一下人生吧。
青青园中葵,朝露待日晞。阳春布德泽,万物生光辉。常恐秋节至,焜黄华叶衰。百川东到海,何时复西归?少壮不努力,老大徒伤悲
另外,我想要告诉大家的是,重写(Override)和重载(Overload)是Java中两个非常重要的概念,新手经常会被它们俩迷惑,因为它们俩的英文名字太像了,中文翻译也只差一个字。难,太难了。