继承
一、继承的基本概念
1.继承的理解
- 自上而下:定义了一个类A,在定义另一类B时,可以发现类B与类A的功能相似,可以考虑类B继承类A。
- 自下而上:定义了类A、B、C等多个类,它们之中存在类似的属性或方法,可以考虑提取它们的共性封装到类D中,A、B、C等多个类继承类D,将原有重复代码删除即可。
2.继承的好处
- 继承的出现减少了代码冗余,提高了代码的复用性。
- 继承的出现,更有利于功能的扩展。
- 继承的出现让类与类之间产生了is-a的关系,为多态的使用提供了前提。
- 继承描述事物之间的所属关系,这种关系是: is-a 的关系。可见,父类更通用、更一般,子类更具体。
3.继承的格式
class A {
//属性、方法
}
class B extends A {
}
- 继承的基本概念
类A:父类、superClass、超类、基类
类B:子类、subClass、派生类
4.有了继承性以后:
- 子类就获取了父类中声明的所有属性和方法
- 继承不会打破封装性,子类不能直接调用父类中私有的属性和方法,但是子类依然继承到了。
- 子类在继承父类以后,还可以扩展自己特有的功能(增加特有的方法、属性)
5.默认的父类:
java中声明的类,如果没有显式的声明其父类时,则类默认继承Object类
6.补充说明:
- Java支持多层继承–直接父类、间接父类。
- java中的子父类的概念是相对的。
- java中一个父类可以被多个子类继承,一个子类只能继承一个父类。
二、方法的重写
1.为什么需要方法的重写?
子类在继承父类后,就获取了父类中声明的所有方法 。但是、父亲中的方法可能不太适用于子类,子类需要对父类中继承过来的方法进行覆盖、覆写的操作。
2.何为方法的重写?
子类对父类继承过来的方法进行覆写、重写的操作,就称为方法的重写。
3.方法重写应遵循的规则
- 父类被重写的方法与子类重写的方法名和形参列表必须相同。
- 子类重写的权限修饰符不小于父类被重写的方法权限修饰符。
- 子类不能重写父类中声明为private权限修饰的方法
- 关于返回值类型:
①.父类被重写方法的返回值类型是void,则子类重写方法的返回值类型也必须是void
②.父类被重写的返回值类型时基本数据类型,则子类重写的方法返回值类型必须要与父类中被重写的方法的返回值类型相同。
③.父类被重写的方法的返回值类型时引用数据类型(比如类),则子类重写的方法的返回值类型可以与父类中被重写方法的返回值类型相同 或 是被重写的方法的返回值类型的子类。
三、Super关键字
1.为什么需要使用super?
- 子类继承了父类,对父类的方法进行了重写,那么在子类中,是否还可以对父类中被重写的方法进行调用?
- 子类继承父类后,在子类中定义了与父类同名的属性,是否可以在子类中区分两个同名的属性?
- 使用super关键字即可解决这两个问题
2.super的理解:父类的
3.super可以调用的结构:属性、方法、构造器
-
super调用属性、方法
子类继承父类后,我们就可以在子类的方法或构造器中,调用父类的声明的属性和方法。(满足封装性的前提下)
一般情况下,我们可以省略super.的结构。但是如果出现子类重写了父类的方法或父类中出现了同名的属性时,就必须使用"super."的声明,显式的调用父类的被重写的方法或父类中声明的同名的属性 -
super调用构造器
①.子类继承父类时,不会继承父类的构造器。只能通过"super(形参列表)“的方式调用父类指定的构造器。
②.规定:“super(形参列表)”,必须声明在子类构造器的首行。
③.在构造器的首行,“this(形参列表)”和“super(形参列表)”只能二选一。
④.如果在子类构造其中既没有调用"this(形参列表)”,也没有显式调用"super(形参列表)",则子类构造器默认调用“super()”,即调用空参的构造器。
⑤.子类的任何一个构造器中,要么会调用本类中重载的构造器,要么会调用父类的构造器。只能是这两种情况之一。
⑥.一个类中有n个构造器,最多有n-1个构造器中使用了“this(形参列表)”,则剩下的那个一定使用“super(形参列表)”。
结论:我们在通过子类的构造器创建对象时,一定在调用子类构造器的过程中,直接或间接的调用到父类的构造器。也正是因为调用过父类的构造器我们才会将父类中声明的属性或方法加载到内存中,供子类对象使用。
四、子类对象实例化全过程
1.从结果的角度来看:体现为类的继承性
当我们创建子类对象后,子类对象就获取了其父类中声明的所有属性和方法,在权限允许的情况下,可以直接调用。
2.从过程的角度来看:
当我们通过子类的构造器创建对象时,子类的构造器一定会直接或间接的调用到其父类的构造器,而其父类的构造器会直接或间接的调用到其父类的父类的构造器…直到调用到Object类中的构造器为止。
正因为我们调用过子类所有父类的构造器,所以我们就会将父类中声明的属性、方法加载到内存中,供子类的对象使用。
五、Object类详解
1.Object类的说明
- 明确:java.lang.Object
- 任何一个Java类(除Object类)都直接或间接的继承于Object类
- Object类称为Java类的根父类
- Object类中声明的结构(属性、方法等)就具有通用性
Object类中没有声明属性
Object类中提供了一个空参的构造器
2.常用方法
- 重点方法:equals \ toString()
- 了解方法:clone()克隆一个对象,地址不同 \ finalize()类被回收前要做的事
3.equals()的使用
- 适用性:只能使用在引用数据类型上。
- 子类使用说明:
①.自定义的类在没有重写Object中equals()方法的情况下,调用的就是Object类中声明的equals(),比较两个地址的引用地址是否相同。(或比较两个对象是否指向了堆空间中的同一个对象实体)
②.对于像String、Flie、Date和包装类等,他们都重写了Object类中的equals()方法,用于比较两个对象的实体内容是否相等。 - 开发中使用说明
实际开发中,针对自定义的类,尝尝会判断两个对象是否equals(),而此时主要是判断两个对象的属性值是否相等,所以,我们要重写Object中的equals()方法。 - 如何重写?
①.手动自己手写
②.调用IDEA自动实现
4.toString()的使用
-
开发中的使用场景
平时我们在调用System.out.println()打印对象引用变量时,其实就是调用了对象的toString() -
子类使用说明
①.自定义的类,在没有重写toString()的方法的情况下,默认返回的是当前对象的地址值
②.像String、File、Date、或包装类等Object的子类,它们都重写了Object类的toString(),在调用时,返回当前对象的实体内容。 -
开发中的使用说明
习惯上,开发中对于自定义的类在调用toString()时,也希望显示对象的实体内容,而非地址值。这时候我们就要对toString()方法进行重写了