继承概述
什么是继承?
- Java中提供了一个关键字extends,用这个关键字,我们可以让两个类建立起父子关系
- 格式:子类extends父类
- Student称为子类(派生类),People称为父类(超类)
- 作用:当子类继承父类之后,就可以直接使用父类的公共的属性和方法了
使用继承的好处
- 提高代码的复用性,减少代码冗余,增强类的功能扩展性
设计规范
子类们的相同属性放在父类中定义,子类独有的属性和方法应该定义在子类自己里面
如果子类的独有属性和方法定义在父类的话,那么会导致其他的子类也会得到这些属性和方法,不符合面向对象逻辑。
代码参考
继承的特点
- 子类可以继承父类的属性和行为,但是子类不能继承父类的构造器
- Java是单继承模式:一个类只能继承一个父类
- Java不支持多继承,也就是不能同时有多个父类,但是支持多层继承
- Java中所有类都是Object类的子类,Object类是祖宗类
疑问
- 子类是否可以继承父类的构造器?不可以,子类有自己的构造器,父类构造器用于初始化父类对象
- 子类是否可以继承父类的私有成员?可以的,只是不能直接访问而已
- 子类是否可以继承父类的静态成员?只是可以共享,但不能算是继承,就好像你开你爸爸的车,这个车只是共享给你开,但不算继承给你的
继承后:成员变量和成员方法的访问特点
在子类方法中访问访问成员(成员变量、成员方法)满足:就近原则
- 先子类局部范围找
- 然后子类成员范围找
- 然后父类成员范围找,如果父类范围还没有找到则报错
如果子父类中出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办?
- 可以通过super关键字,指定访问父类的成员
代码理解
public class Test {
public static void main(String[] args) {
Dog d = new Dog();
d.run();//就近原则,狗跑
System.out.println(d.name);//狗名
}
}
class Animal{
public String name ="动物名";
public void run(){
System.out.println("动物跑!");
}
}
class Dog extends Animal{
public String name = "狗名";
public void run(){
System.out.println("狗跑!");
}
public void test(){
String name = "局部名";
System.out.println(name);
System.out.println(this.name);//当前子类对象的name
System.out.println(super.name);//访问父类的name
super.run();//找父类的方法
}
}
继承后:方法重写(override)
什么是方法重写?
在继承关系中,子类出现了和父类一模模一样样的方法声明,我们就称子类这个方法是重写的方法
应用场景
- 当子类需要父类的功能,但父类的该功能不能完全满足自己的需求时
- 子类可以重写父类的方法
也就是说在父类的基本功能基础上拓展新的功能
用案例来理解⬇
/**
* @Author: ttong
* @Description:方法重写
* 旧手机:可以打电话、发信息
* 新手机:旧手机的基本功能下拓展视频通话、发送语音和图片
*/
public class Test {
public static void main(String[] args) {
//理解方法重写
newPhone np = new newPhone();
np.call();
}
}
//旧手机
class Phone{
public void call(){
System.out.println("打电话");
}
public void sendMsg(){
System.out.println("发信息");
}
}
//新手机
class newPhone extends Phone{
//重写的方法
public void call(){
super.call();//先用父类基本功能
System.out.println("开始视频通话");
}
//重写的方法
public void sendMsg(){
super.sendMsg();//先用父类基本功能
System.out.println("开始发语音和图片信息");
}
}
@Override重写注解
可以放在重写方法上作为重写是否正确的校验注解
- 当重写的方法写错了会有报错提示,更安全
- 提高代码可读性,更优雅~
注意事项和要求
- 重写的方法的名称、形参列表必须与被重写的方法的一致
- 私有方法不能被重写
- 子类重写方法时,访问权限必须大于等于父类的
- 子类不能重写父类的静态方法,会报错的
继承后:子类构造器的特点
- 子类中的所有构造器默认都会先访问父类中的无参构造器,再执行自己
为什么呢?
- 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据
- 子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化
怎么调用父类构造器的?
- 子类构造器的第一行语句默认都是:super(),不写也存在
继承后:子类构造器访问父类有参构造器
使用super(...)调用父类的有参构造器
作用:
- 初始化继承自父类的数据
如果父类中没有无参构造器,只有有参构造器,会出现什么现象?
- 会报错,因为子类默认是调用父类的无参构造器
如何解决?
- 子类构造器中可以通过书写super(...),手动调用父类的有参构造器
子类一定会访问父类的构造器,无论是有参还是无参!!!
this和super使用总结
this:代表本类对象的引用
super:代表父类存储空间的标识
关键字 | 访问成员变量 | 访问成员方法 | 访问构造方法 |
this | this.成员变量 访问本类成员变量 | this.成员方法(..) 访问本类成员方法 | this(...) 访问本类(其他)构造器 |
super | super.成员变量 访问父类成员变量 | super.成员方法(...) 访问父类成员方法 | super(...) 访问父类构造器 |
疑问?this(...)⬇
this如何访问本类其他构造器
用案例去理解⬇
如果要开发一个学生信息管理系统,要填写姓名和学校,如果学生不填写学校,假设默认学校是苏州科技大学
public class Test {
public static void main(String[] args) {
Student s1 = new Student("gst","苏州科技大学");
System.out.println(s1.getName());
System.out.println(s1.getSchoolName());
//如果要开发一个学生信息管理系统,要填写姓名和学校
//如果学生不填写学校,默认学校是苏州科技大学
Student s2 = new Student("zcy");
System.out.println(s2.getName());
System.out.println(s2.getSchoolName());
}
public class Student {
private String name;
private String schoolName;
//无参构造器
public Student() {
}
//如果要开发一个学生信息管理系统,要填写姓名和学校
//如果学生不填写学校,默认学校是苏州科技大学
public Student(String name){
//借用本类的兄弟构造器
this(name,"苏州科技大学");
}
//有参构造器
public Student(String name, String schoolName) {
this.name = name;
this.schoolName = schoolName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
}
this和super使用注意点
- 子类通过this(...)去调用本类的其他构造器,本类其他构造器会通过super去手动调用父类的构造器,最终还是会调用父类的构造器
- 注意:this(...)super(...)都只能放在构造器的第一行,所以二者不能共存在于同一个构造器中,原因如下⬇
super(...)放在第一行:必须先初始化父类,再初始化自己
this(...)放在第一行:借用本类兄弟构造器时,那么这个构造器里面的super()就没有了【如果有的话会执行两次初始化父类,super()本身先初始化父类,然后this(...)调用兄弟构造器时,兄弟构造器里还有一次super()初始化父类,这样不合规】,然后借用兄弟构造器的时候也必须放在第一行因为无论如何要保证优先初始化父类,只有this(...)在第一行时才能马上去借兄弟的super()初始化父类
所以流程就是先执行this(...)然后借用兄弟构造器里执行super()初始化父类
this基本用法不懂→http://t.csdnimg.cn/YyWGu