黑马程序员 6 Java面向对象编程 三
#1继承
A.子类,父类(基类)
B.继承的好处:
1、提高了代码的复用性。
2、让类与类之间产生了关系,为第三个条件——多态,提供了条件。
C. java中支持单继承,不直接支持多继承,但对C++中的多继承机制改良。
单继承:一个子类一个父类;
多继承;一个子类可以有多个父类。(java不支持,消除调用的不确定性)
D. java支持多层继承
当要使用一个继承体系时:
1、查看该体系的顶层类,了解该体系的的基本功能。
2、创建体系中的最子类对象,完成功能的使用
*继承依赖关系,无关系不需要继承。相同部分可以抽取出来当做共同的父类成员。
E. 什么时候定义继承?
当类与类之间存在所属关系,就定义继承。
*子类中如果使用父类的成员,super.成员
*父类没有对象,成员存在于新建的子类对象中。
*子类可以继承父类中的私有变量但是不能直接访问,可以利用父类的方法访问。
F. 成员函数:
a.当子父类中出现一模一样的成员函数,则会运行子类的函数。这种现象叫做覆盖操作。这是函数在子父类中的特性。
b.函数的两个特性:
1.重载:同一个类中,overload。
2.覆盖:子类中,覆盖也称为重写,覆写,override。
c.覆盖注意事项:
1.子类覆盖父类方法时,子类权限必须大于等于父类的权限。
*父类中是private时,不算覆盖,因为父类方法子类不可用。
2.静态只能和静态相互覆盖。
d.什么时候覆盖:
当对一个类进行子类的扩展时,子类需要保留父类的功能声明,但是要定义子类中该功能的特有功能时,就是用覆盖操作完成。
*尽量少对源代码进行修改,带来安全隐患,不利于扩展。
实例分析:
子类成员VS父类成员:
class Animal{ int leg = 4;//父类成员
//父类方法 void showAnimal(){ System.out.println("Animal has "+leg+" legs."); } } class Bird extends Animal{
//子类成员变量 int leg = 2;
//子类方法 void showBird(){ System.out.println("Bird has "+leg+" legs,not "+super.leg+" legs."); } } public class Test7{ public static void main(String[] args){ Bird b = new Bird(); b.showAnimal(); b.showBird(); } }
*但是实际中极少定义子类变量与父类重名。
子类方法VS父类方法:
内存分析:
G.子父类中构造函数的特点:
a.构造系类对象时,父类的构造函数也运行了。因为子类构造函数第一行有一个默认的隐式空参数语句:super(),子类实例化过程中,子类所有构造函数都默认访问父类的空参构造函数;
*如果父类中没有空参数构造函数,子类也不能调用。
b. 为何要调用父类的构造函数:
因为子类继承了父类,获取到了父类内容,所以在使用父类内容时,要先看父类是如何对自己的内容初始化的。
*super()必须在构造函数第一行,因为父类必须先构造。
*如果父类中没有定义空参构造函数,子类的构造函数必须super()明确调用。
*子类中的构造函数使用了this调用了本类构造函数时,那么super就没了,因为this和super都要在第一行。但是super可以运行,因为别的构造函数中还有。
H. 一个对象实例化过程:
Person p = new Person();
1.JVM读取指定路径下的class文件加载进内存;并会先加载Person的父类(如果有);
2.在堆内存中开辟空间,分配地址。
3.并在对象空间中,对对象中的属性进行默认初始化。
4.调用对应的构造函数进行初始化。
5.在构造函数中,第一行会先调用父类中的构造函数进行初始化。
6.父类初始化完毕后,对子类的属性进行显式初始化。
7.再经行子类构造函数的特定初始化。
8.初始化完毕后,把地址赋给引用变量。
*继承——子父类中的构造函数——子类的实例化过程图解:
//father class Animal{ Animal(){ super(); show(); System.out.println("Animal!"); } void show(){ System.out.println("Animal ~"); } } class Bird extends Animal{ int leg = 4; Bird(){ super();//通过super进行父类初始化时,leg并未显式初始化 System.out.println("Bird!"); } void show(){ System.out.println("Bird has "+leg+" legs ~"); } } public class Test8{ public static void main(String[] args){ Bird b = new Bird(); b.show(); } }
在new对象之后已经赋给num默认值,在构造函数中调用父类构造函数,父类构造函数进栈,此时num还未被赋值。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。