1.父类对象与子类对象分别调用相同方法名的方法
class Person2{
public void show(){
System.out.println("父类Person2的show方法");
}
public void show1(){
System.out.println("父类Person2的show1方法");
}
}
class Student2 extends Person2{
public void show(){
System.out.println("子类Student2的show方法");
}
public void show1(){
System.out.println("子类Student2的show1方法");
}
}
public class OverrideDemo1 {
public static void main(String[] args) {
Student2 s = new Student2();
s.show();
s.show1();
Person2 p = new Person2();
p.show();
p.show1();
}
}
结果为
父类对象调用父类的方法,打印父类方法的两条语句
子类对象调用与父类同名的方法,优先调用子类自己重写后的方法,打印子类方法里面的两条语句
2. 父类方法和构造器调用被子类重写后的方法
class Person2{
public void show(){
System.out.println("父类Person2的show方法");
show1();
}
public void show1(){
System.out.println("父类Person2的show1方法");
show1();
}
}
class Student2 extends Person2{
public void show(){
super.show();
}
public void show1(){
System.out.println("子类Student2的show1方法");
}
}
public class OverrideDemo1 {
public static void main(String[] args) {
Student2 s = new Student2();
s.show();
}
}
这里通过子类对象调用子类的show方法,show方法的方法体内是super.show(); ,这句话的意思是调用父类的show()方法,父类的show方法里面是调用show1()方法。
那么问题来了,根据方法调用的优先级顺序,这里应该是优先调用本类的show1()方法。但是因为子类重写了父类的show1()方法,方法重写又叫覆盖,这里会调用子类的show1()方法,而不是父类的。
同理,在父类构造器中出现,被子类重写后的方法时,也是优先调用子类的方法
package test;
class Person2{
Person2(){
System.out.println("父类的构造方法");
show();
}
public void show(){
System.out.println("父类Person2的show方法");
}
}
class Student2 extends Person2{
Student2(){
System.out.println("子类的构造方法");
show();
}
public void show(){
//super.show1();
System.out.println("子类Student2的show方法");
}
}
public class OverrideDemo1 {
public static void main(String[] args) {
new Student2();
System.out.println("=======");
new Person2();
}
}
结果为
输出结果中的第二句是调用了子类的show方法
因为在调用子类的构造器之前,会先初始化父类的构造器,所以才会看到先打印了父类的构造方法,然后父类构造方法调用被子类重写后的show方法,最后才是子类的构造器输出结果并且调用子类的show方法
如果对为什么先调用父类构造器有点晕的话,可以看这篇博客(这个超链接指向的博客)的后半部分
当然,如果用父类对象直接调用父类的构造器或者方法,那么是不会调用子类中被重写的方法的,上面的例子的后半部分结果证明了构造器,下面这个例子证明了调用的是父类的方法
class Person2{
public void show(){
System.out.println("父类Person2的show方法");
show1();
}
public void show1(){
System.out.println("父类Person2的show1方法");
}
}
class Student2 extends Person2{
public void show(){
//super.show1();
System.out.println("子类Student2的show方法");
}
public void show1(){
System.out.println("子类Student2的show1方法");
}
}
public class OverrideDemo1 {
public static void main(String[] args) {
Person2 p = new Person2();
p.show();
}
}
父类对象调用父类的show方法,哪怕方法体中有 show1(); 也是调用父类自己的方法,而不是子类重写后的。
在子类用super调用父类的show1方法也一样,方法体中的 show1(); 语句会自动跳转到子类的show1()方法
package test;
class Person2{
public void show(){
System.out.println("父类Person2的show方法");
show1();
}
public void show1(){
System.out.println("父类Person2的show1方法");
show1();
}
}
class Student2 extends Person2{
public void show(){
super.show1();
System.out.println("子类Student2的show方法");
}
public void show1(){
System.out.println("子类Student2的show1方法");
}
}
public class OverrideDemo1 {
public static void main(String[] args) {
Student2 s = new Student2();
s.show();
}
}
不过有一点要记住的是,super调用父类的show,show1方法后,这两个方法都被执行了,里面的内容会被打印,不过是方法体中的 show1(); 语句会跳转到子类的show1方法
从上面的这个结果也能看出来, super.show1(); 调用了父类的show1方法,打印了 “父类Person2的show1方法” 这句话。然后父类show1方法中的
语句调用了子类的show1方法,打印了 “子类Student2的show1方法这句话”
最后继续执行子类的show方法剩下的方法体部分,打印 “子类Student2的show方法” 这句话
一个例子
package test1;
public class Demo1 {
class Father{
int num = 11;
Father(){
System.out.println("父类构造器");
show();
}
void show(){
System.out.println("父类的show方法,并且num的值为"+num);
}
}
class Son extends Father{
//int num = 22;
Son(int i){
num = i;
System.out.println("子类构造器");
show();
}
void show(){
System.out.println("子类的show方法,并且num的值为"+num);
}
}
public static void main(String[] args) {
Demo1 d = new Demo1();
d.new Son(10);
System.out.println("==============");
d.new Father();
}
}
在调用子类构造器之前,会先初始化父类的构造器,所以第一句话打印的是*“父类构造器”*
父类构造器里面通过 show(); 调用了子类的show()方法,此时子类的构造器还没有初始化,所以是继承父类的num值,num值为11。所以第二句是*“父类的show方法,并且num的值为11”*
父类构造器初始化完毕之后,才开始执行子类的构造器,所以打印第三句,”子类构造器“
之后子类构造器自己调用自己的show方法,并且num值变成了创建对象时传入的值10,所以第四句话是*”子类的show方法,并且num的值为10”*
总结一下
- 子类调用构造方法时,不论是有参还是无参构造,都是默认访问父类的无参构造方法
父类构造方法中的语句执行完毕后,才会执行子类构造方法中的语句
(可以用super(参数列表)的方式,改变要先初始化的父类构造方法) - 子类调用构造方法,初始化父类时,父类的构造方法会调用子类重写后的重名方法
- 子类用super调用父类方法时,父类方法会调用子类重写后的重名方法
- 父类自身调用构造方法和普通方法时,都是访问自身的方法,不会访问子类的同名方法
我写了一段比较绕的代码当最后总结的例子
package review;
class Father{
public int age = 30;
{
System.out.println("父类构造代码块");
}
public Father(){
System.out.println("父类无参构造方法");
Show();
}
public void Show(){
System.out.println("父类的方法一");
Show2();
}
public void Show2(){
System.out.println("父类的方法二");
}
}
class Son extends Father{
{
System.out.println("子类的构造代码块");
}
public Son(){
System.out.println("子类的无参构造方法"+"---"+age);
}
public Son(int age){
System.out.println("子类的有参构造方法"+"---"+age);
}
public void Show(){
System.out.println("子类的方法一");
super.Show2();
}
public void Show2(){
System.out.println("子类的方法二");
}
}
public class extendsDemo {
public static void main(String[] args) {
Son s = new Son(10);
System.out.println("---------");
Father f = new Father();
}
}