黑马程序员技术交流社区
标题:
继承
[打印本页]
作者:
fmi110
时间:
2015-8-19 18:06
标题:
继承
a
1、继承的描述:
通过 extends 关键字让类与类之间产生关系。
多个类具有相同的属性或者行为时,将这些内容抽取到单独一个类中,那么多个类不必再
定义这些属性和行为,只要继承哪个类即可。多个类成为子类,单独的类成为父类或者超类。
PS: 1 子类可以访问父类中非私有的属性和行为
2 子类无法继承父类中私有的内容
3 父类怎么来的?共性不断向上抽取来的
继承的好处:
1 继承的出现提高了代码的复用性
2 继承的出现让类与类之间产生了关系,提供了多态的前提
2、继承的特点
java 类只支持单继承,不支持多继承。因此一个类只有一个父类,不能有多个
原因:当出现多继承时,父类中出现相同的方法名时,子类要执行哪一个方法是不确定。
3、 super 和 this关键字
1 成员变量
this 和 super 的用法很相似,this 代表本类对象的引用;super 代表父类的内存空间的标识
当本类成员和局部变量同名时,用 this区分;
当子父类中出现同名成员变量时,用 super区分父类
————————————————————————————————————————————————————————————————————
class Fu{
private int num = 4;
public int getNum(){
return num;
}
}
class Zi extends Fu{
private int num = 3;
void show(){
System.out.println("this.num:"+this.num+"...super.num:"+super.num);
}
}
class ExtendsDemo{
new Zi().show();
}
输出结果: this.num:3...super.num:4
————————————————————————————————————————————————————————————————————
2 成员函数
当子父类中出现成员函数一模一样去情况,会运行子类的函数
这种现象,称为覆盖操作,这是函数在子父类中的特性。
在子类覆盖方法中,要继续使用被覆盖的方法可以通过super.函数名 获取。
函数的两个特性:
1 重载,在同一个类中。函数名相同,参数列表不同 overload
2 覆盖,在子类中,覆盖也成为重写,覆写,override
何时使用重写操作?
当子类需要父类的功能,但子类的功能主体有子集独特的内容时,可以复写父类的方法,
这样既沿袭了父类的功能,又定义了子类特有的内容。
PS: 1 父类中私有方法不能被覆盖(子类看不到)
2 父类的 static 方法无法覆盖
3 覆盖时,子类方法权限一定要大于或等于父类方法的权限
3. 构造函数
子父类中构造函数的特点:
在子类构造函数执行时,发现父类构造函数也运行了。
原因:在子类的构造函数中,第一行有一个默认的隐式语句:super();
注意:如果使用super(4);语句调用父类的其他构造函数,那么默认的父类构造函数将不会再被调用。
4、子类的实例化过程
子类中所有的构造函数默认都会访问父类中空参数的构造函数
因为每一个子类的构造函数第一行都有一条默认语句 super();
为什么子类实例化的时候要访问父类中的构造函数呢?
那是因为子类继承了父类,获取到了父类中内容(属性),所以在使用父类内容之前,要先看父类是如何对
自己的内容进行初始化的。
P.S.
1 当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函
数。
2 子类构造函数中如果使用this调用了本类构造函数,那么默认的super();就没有了,因为super和this都只
能定义在第一行,所以只能有一个。 但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。
3 super语句必须要定义在子类构造函数的第一行!因为父类的初始化动作要先完成。
————————————————————————————————————————————————————————————————————
class Fu{
Fu(){
super();//没写时,系统会隐士的给出
//子类初始化时,调用的是子类的show,但此时子类特有的成员变量num 未初始化
show();
}
public void show(){
System.out.println("Fu show");
}
}
class Zi extends Fu{
int num = 8;
Zi(){
super();
//通过super初始化父类内容时,此时子类的成员变量并未显示初始化,等 super父类
//初始化完毕后,才进行子类的成员变量显式初始化
}
public vois show(){
System.out.println("Zi show..."+num);
}
}
class ExtendDemo(){
public static void main(String[] args){
Zi zi = new Zi();
zi.show();
}
}
输出结果: Zi show...0
Zi show...8
总结:Zi zi = new Zi();的实例化过程
1 JVM 会读取指定路径下的Zi.class 文件,并加载如内存,并会先加载Zi的父类(如果
有直接父类)
2 在内存开辟空间,并分配地址(父类、子类中的成员和方法同时开辟)
3 并在对象空间中,对对象的属性进行默认初始化
4 调用对应的构造函数进行初始化
5 在构造函数中,第一行会先调用父类中的构造函数super()进行初始化
6 父类构造函数初始化完毕后,再对子类的属性进行显示初始化
7 再进行子类构造函数的特定初始化
8 初始化完毕后,将地址值赋给引用变量
PS:类定义中如果存在构造代码块,代码块会先于构造函数执行!
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2