Java语言基础 9

Java语言基础9:继承的概念、继承的特点、继承中成员变量的关系、继承中成员方法的关系、继承中构造方法的关系、静态代码块、构造代码块、局部代码块。


1、继承的概念

(1)多个类中存在相同属性和行为时,将这些内容抽取到单独的一个类中,那么,这许多个类中无需再定义这些相同的属性和行为,只要继承那个类即可。

(2)通过extends关键字可以实现类与类之间的继承:   class 子类名 extends 父类名 { } 

(3)单独的这个类称为父类基类或者超类;这多个类可以称为子类或者派生类

(4)有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员:成员变量和成员方法。

好处:提高了代码的复用性和维护性,让类与类之间产生关系,这是多态的前提(这其实也是继承的一个弊端:类的耦合性增强了)。

开发的原则:低耦合(类与类之间的关系)、高内聚(自己完成某件事情的能力)。

(5)继承的举例子:

class Person {
	String name;
	int age;	

	public Person(){}		
	//getXxx()/setXxx()	
	public void eat() {
		System.out.println("吃饭");
	}
}

class Student extends Person {
	public Student(){}
}

class Teacher extends Person {
	public Teacher(){}
}

2、Java继承的特点:

1)Java支持单继承,不支持多继承。一个类只能有一个父类,不可以有多个父类。

class SubDemo extends Demo{ }   //ok

class SubDemo extends emo1,Demo2...  //error
(2)Java支持多层继承(继承体系)
class A{}
class B extends A{ }
class C extends B{ }
多层继承的例子:来形成继承体系。
class GrandFather {
	public void show() {
		System.out.println("我是爷爷");
	}
}

class Father extends GrandFather {
	public void method(){
		System.out.println("我是老子");
	}
}

class Son extends Father {}

class ExtendsDemo2 {
	public static void main(String[] args) {
		Son s = new Son();
		s.method(); //使用父亲的
		s.show(); //使用爷爷的
	}
}

3、继承的注意事项

(1)子类只能继承父类的所有非私有成员(成员变量和成员方法)。其实这也体现了JAVA的另一个弊端:打破了父类的封装性。

(2)子类不能继承父类的构造方法,但是可以通过super 关键字去访问父类的构造方法。

(3)不要为了部分功能而去使用继承。

(4)采用假设法。继承体现的是一种关系:“is a”,而不是“has a”的关系。子类是父类的一种。

4、继承中成员变量的关系:

(1)子类中的成员变量和父类中的成员变量 名称不一样。

(2)子类中的成员变量和父类中的成员变量 名称一样。(采用就近原则)

         在子类方法中查找一个变量的查找顺序:

                    A:在子类方法的局部范围内查找,有就使用;

                    B:在子类的成员范围内查找,有就使用;

                    C:在父类的成员范围查找,有就使用;

                    D:如果还是找不到,则报错(先不考虑父类的父类.....)。

(3)我不仅仅要输出局部范围的num,还想要输出本类成员范围的num,怎么办?

this和super 分别是什么:

this:this代表本类对象的引用。

super:super代表父类存储空间的标识(可以理解为父类对象的引用,可以操作父类的成员)。

this和super 该怎么使用呢:

调用成员变量:

        this.成员变量            调用本类的成员变量

        super.成员变量         调用父类的成员变量

调用构造方法: 

        this(...)              调用本类的构造方法

        super(...)           调用父类的构造方法

调用成员方法:

        this.成员方法            调用本类的成员方法

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

5、继承中构造方法的关系:

(1)子类中所有的构造方法都会默认先去访问父类的无参构造方法,再回头执行自己构造方法。而不会访问父类的带参构造方法。

(2)因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。

(3)注意:子类的每一个构造方法的第一条语句默认都是:super();没写的话默认有它。

(4)如果父类中没有无参构造方法,那子类的构造方法中会出现先什么现象呢?如何解决呢?

答:报错。 解决方法:

                A:在父类中加一个无参构造方法。

                B:子类通过 super 去显示调用父类其他的带参构造方法。

               C:子类通过 this 去调用本类的其他构造方法。(子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。) 本类其他构造方法也必须首先访问父类构造方法。

                D:一定要注意:super(…) 或者this(….) 必须出现在第一条语句上。否则,就可能会对父类数据进行多次初始化。

(5)一个类的初始化过程:成员变量的初始化(  默认初始化——>显示初始化——>构造方法初始化 )

/*
	看程序写结果:
		A:成员变量	就近原则
		B:this和super的问题
			this访问本类的成员
			super访问父类的成员
		C:子类构造方法执行前默认先执行父类的无参构造方法
		D:一个类的初始化过程
			成员变量进行初始化
				默认初始化
				显示初始化
				构造方法初始化				
	结果:
		fu
		zi
		30
		20
		10
*/
class Fu{
	public int num = 10;
	public Fu(){
		System.out.println("fu");
	}
}
class Zi extends Fu{
	public int num = 20;
	public Zi(){
		System.out.println("zi");
	}
	public void show(){
		int num = 30;
		System.out.println(num); //30
		System.out.println(this.num); //20
		System.out.println(super.num); //10
	}
}
class ExtendsTest {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.show();
	}
}

(6)一个类的静态代码块、构造代码块、构造方法的执行流程:

        静态代码块——>构造代码块——>构造方法

类的加载:静态的内容是随着类的加载而加载的,所以静态代码块的内容会在类的加载时优先执行!!!

类的构造:分层初始化:先进行父类初始化,再进行子类初始化!!!

/*
	看程序写结果:
		A:一个类的静态代码块,构造代码块,构造方法的执行流程
			静态代码块 > 构造代码块 > 构造方法
		B:静态的内容是随着类的加载而加载
			静态代码块的内容会优先执行
		C:子类初始化之前先会进行父类的初始化		
	结果是:
		静态代码块Fu
		静态代码块Zi
		构造代码块Fu
		构造方法Fu
		构造代码块Zi
		构造方法Zi
*/
class Fu {
	static {
		System.out.println("静态代码块Fu");
	}

	{
		System.out.println("构造代码块Fu");
	}

	public Fu() {
		System.out.println("构造方法Fu");
	}
}

class Zi extends Fu {
	static {
		System.out.println("静态代码块Zi");
	}

	{
		System.out.println("构造代码块Zi");
	}

	public Zi() {
		System.out.println("构造方法Zi");
	}
}

class ExtendsTest2 {
	public static void main(String[] args) {
		Zi z = new Zi();
	}
}
/*
	看程序写结果:
		A:成员变量的问题
			int x = 10; //成员变量是基本类型
			Student s = new Student(); //成员变量是引用类型
		B:一个类的初始化过程
			成员变量的初始化
				默认初始化
				显示初始化
				构造方法初始化
		C:子父类的初始化(分层初始化)
			先进行父类初始化,然后进行子类初始化。
			
	结果:YXYZ
		
	问题:
		虽然子类中构造方法默认有一个super(),但是,初始化的时候,不是按照那个顺序进行的。
		而是按照分层初始化进行的。它仅仅表示要先初始化父类数据,再初始化子类数据。
*/
class X {
	Y b = new Y();
	X() {
		System.out.print("X");
	}
}

class Y {
	Y() {
		System.out.print("Y");
	}
}

public class Z extends X {
	Y y = new Y();
	Z() {
		//super
		System.out.print("Z");
	}
	public static void main(String[] args) {
		new Z(); 
	}
}
虽然子类中的构造方法默认有一个super(),但是,初始化的时候,不是按照那个顺序进行的,而是按照分层初始化进行的。super()它仅仅表示要先初始化父类数据,再初始化子类数据。


6、继承中成员方法的关系

(1)子类中的方法和父类中方法声明 不一样,这很简单。

(2)子类中的方法和父类中方法声明 一样。

通过子类对象调用方法的顺序:

        A:先找子类中,看有没有这个方法,有就使用;

        B:再看父类中,看有没有这个方法,有就使用;

        C:如果没有,就报错(先不考虑父类的父类.....)。

(3)方法重写:子类中出现了和父类中 方法声明一模一样的方法。

        另:方法重载:本类中出现的方法名一样、参数列表不同的方法、与方法返回值无关。

子类对象调用方法的时候:先找子类本身,再找父类。

使用特点:如果方法名不同,就调用对应的方法。如果方法名相同,最终使用的是子类自己的。

方法重写的应用:当子类需要父类的功能,而功能主体子类有自己的特有内容时,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容。这时,使用关键字super(...)来调用父类被子类重写的方法内容。

class Phone {
	public void call(String name) {
		System.out.println("给"+name+"打电话");
	}
}

class NewPhone extends Phone {
	public void call(String name) {
		//System.out.println("给"+name+"打电话");
		super.call(name);
		System.out.println("可以听天气预报了");
	}
}

class ExtendsDemo9 {
	public static void main(String[] args) {
		NewPhone np = new NewPhone();
		np.call("林青霞");
	}
}

(4)方法重写的注意事项:

1)父类中的私有方法不能被重写。因为父类的私有方法子类根本就不会继承,所以就谈不上重写。

2)子类重写父类方法时,访问权限不能更低,但可以更高!但是,最好一致!

3)父类的静态方法,子类也必须通过静态方法进行重写!

子类重写父类方法的时候,最好在方法声明上一模一样。

7、两个面试题:

1:方法重写和方法重载的区别?    方法重载能改变返回值类型吗?
方法重写:在子类中,出现和父类中一模一样的方法声明的现象。    
方法重载:同一个类中,出现的方法名相同,参数列表不同的现象。
方法重载能改变返回值类型,因为它和返回值类型无关。
Override:方法重写
Overload:方法重载

2:this关键字和super关键字分别代表什么?    以及他们各自的使用场景和作用?
this: 代表当前类的对象引用。
super: 代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)。
场景:
    成员变量:
        this.成员变量
        super.成员变量
    构造方法:
        this(...)
        super(...)
    成员方法:
        this.成员方法
        super.成员方法


8、类的继承

先找到具体的事物,然后发现具体的事物之间有共性,这时才提取出这些共性,定义到一个父类中,然后出继承。(构造方法一定要自己给出!默认的无参构造方法和带参的构造方法!)




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值