java-继承提升

本文探讨了Java中的继承概念,强调了子类在实例化时会默认调用父类的无参构造方法。详细分析了构造方法的执行顺序,指出子类构造方法第一条语句默认为`super()`。同时讲解了成员方法的调用规则,包括不同声明情况下如何选择执行。通过案例展示了如何正确理解和避免误解程序执行流程。
继承的特点:
java中只支持单继承不支持多继承。
有些语言是支持多继承的,格式:extends类1,类2...
但是java支持多层继承,例:子类继承父类,父类也可以继承父类的父类(此处形象称为:爷爷类),子类同样拥有爷爷类的属性和方法

案例:

“爷爷类:”

package day08;


public class GrandFather {
	public void show(){
		System.out.println("我会唱戏!");
	}


}
“父亲类”
package day08;


public class Father extends GrandFather {
	public void play(){
		System.out.println("我会开车!");
	}


}
子类:
package day08;


public class Son extends Father {
        
}
测试类:
package day08;


public class SonMain {


	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 创建son类对象
		Son s = new Son();
		//调用父类Father的play()方法
		s.play();
		//调用父类的父类GrandFather的show()方法
		s.show();
	}


}

输出:

我会开车!
我会唱戏!

继承的注意事项:
1-子类只能继承父类所有的非私有成员(方法和变量),不能继承父类的私有成员。

2-父类的构造方法不被子类所继承,但是可以通过super关键字访问父类构造方法,以及操作父类成员。

注意:子类虽然不能继承父类的构造方法,但是子类在实例化对象(不管对象有无参数)的时候会自动调用父类的无参构造方
法。

使用继承的场景:
    首先要思考类与类之间的关系:是否具有附属关系。

  例:
      人类:
            学生类
            老师类


      水果类:
            苹果类
            西瓜类
            香蕉类


继承中成员变量之间的关系:(一层父类情况下)
1-如果子类中成员变量名称和父类中成员变量名称不一样,可以很方便的调用。
2- 如果子类中成员变量名称和父类中成员变量名称一样,则要注意调用顺序:

     1- 首先在子类的方法的局部范围查找,有就调用使用
     2-然后在子类成员范围查找,有就调用使用
     3-然后在父类成员范围查找,有就调用使用 
        如果都没找到,就会报错。

    
this和super的区别:
  1-this代表本类对象的引用
  2-super代表父类存储空间的表示(理解为父类引用,可以操作父类的成员)

怎么使用:
   1-调用成员变量
      this.成员变量 调用本类的成员变量
      super.成员变量 调用父类的成员变量
   2-调用构造方法
      this(...) 调用本类的构造方法
      super(...) 调用父类的构造方法
   3-调用成员方法
      this.成员方法  调用本类的成员方法

      super.成员方法 调用父类的成员方法

继承中构造方法的关系:
子类在实例化对象(不管对象有无参数)的时候会默认先自动调用父类的无参构造方法。(注意:这里的先调用只能理解为先初始化的一个过程。)不然会对程程序执行造成误解!这个一定要注意!

案例:

类Y:

package day08;


public class Y {
     public Y(){
    System.out.println("Y");
     }
}

类X:

package day08;


public class X {
    Y y = new Y();
    
    public X(){
    System.out.println("X");
    }
}

类Z:

package day08;


public class Z extends X {


    Y y = new Y();
    public Z(){
    System.out.println("Z");
    }
public static void main(String[] args) {
new Z();
}


}

输出:

Y
X
Y
Z

我们来分析一下结果:首先创建new Z()执行到类Z,Z继承X所以加载到类X中,先执行成员变量Y y = new Y();

加载到类Y中,执行Y的构造方法打印输出Y,然后接着执行X的构造方法打印X,接着执行类Z,执行成员变量Y y = new Y();

打印Y, 最后执行类Z的构造方法打印Z,所以看到结果为YXYZ.记住这是正确的执行过程和结果

对于结果大家可能就有疑惑了,类Z中的构造方法第一句默认有个super()么,那么岂不是执行顺序是最先执行类Z中的Y y = new Y();打印Y

再执行super()依次执行Y y = new Y();打印Y

接着执行类X构造打印X;

然后回到类Z中,super执行完毕,接着执行下一条语句打印Z.

最终结果是YYXZ那么问题就出现了,和控制台的结果是不一样的,说明这种分析是错误的。实际上我们认为的先执行super()没有错误

关键在于这里的执行只能理解为先去为父类初始化的一个过程。这是问题的关键,并不是程序执行流程。理解这个就知道这是错误,只是先初始化,并非调用执行。


调用父类构造方法可能会使用父类中的数据,所以子类初始化之前一定要先完成父类数据的初始化,不然会造成父亲数据无法访问的情况
注意:子类的每一个构造方法的第一条默认(不显示但是系统存在)语句都是:super()调用父类的无参构造。

案例:

定义一个父类:

package day08;

public class Fu {
      public int num = 100;
      public Fu(){
    	  System.out.println("我是父类的构造方法!");
      }
}
定义一个子类:

package day08;

public class Zi extends Fu {
     public int num = 200;
     
     public Zi(){
    	 System.out.println("我是子类的构造方法!");
     }
     
     public void show(){
    	 int num = 300;
    	 System.out.println(num);
    	 System.out.println(this.num);
    	 System.out.println(super.num);
     }
}
测试类:

package day08;

public class FuZiMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//创建子类对象
		Zi z = new Zi();
		z.show();

	}

}

输出结果:

我是父类的构造方法!
我是子类的构造方法!
300
200
100

由结果可以看出,程序首先执行父类的无参构造方法,然后执行子类中的构造方法,接着执行子类中成员方法。

注意事项:
如果父类中没有无参构造方法,那么子类的构造方法中会出现什么情况??
安静系统会报错!!!
解决办法:
  1-在父类中加一个无参数的构造方法。
  2-子类通过super关键字显示的调用父类的带参构造方法
  3-子类通过this调用本类其他构造方法注意:子类构造方法中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
注意:
1-this或者super()必须出现在第一条语句上。

2-如果不在第一天语句上 就可能对父类进行了多次的初始化,所以必须放在第一条语句。



继承之间成员方法的关系:
1-子类中的方法声明和父类中的方法声明不一样,简单调用不影响。
2-子类中的方法和父类中的方法声明一样时候:
    通过子类调用方法
     1-先找子类中的方法,看有无这个方法,有就使用
     2-再找父类中的方法,看有无这个方法,有就使用
     3-如果都没有就报错。
案例:

父类:

package day08;

public class FatherDemo {
    public void method(){
    	System.out.println("我是父类的method方法");
    }
    public void play(){
    	System.out.println("我是父类的play方法");
    }
}

子类:

package day08;

public class SonDemo extends FatherDemo{
   public void show(){
	   System.out.println("我是子类的show方法");
   }
   public void method(){
	   System.out.println("我是子类的method方法");
   }
   public static void main(String[] args) {
	    SonDemo sd = new SonDemo();
	    sd.show();//子类有父类也有,调用子类
	    sd.method();//子类有父类没有,调用父类
	    sd.play();//子类没有父类有,调用父类
	    
   }
}
输出:

我是子类的show方法
我是子类的method方法
我是父类的play方法


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值