继承:
含义:让类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有成员
格式:
public class Zi extends Fu{}
Fu:是父类,也被称为基类、超类
Zi:是子类,也被称为派生类
若调用子类的有参构造,子类需要重写创建有参构造方法(当创建有参时,需要手动创建无参,否则系统不会默认创建)
public Student(){};
public Student(String name ,String age){
super.setName(name);
super.setAge(age);
}
或
public Student(String name ,String age){
super(name,age);
}
建议:后续直接用无参构造,配合set、get方法去调用,如果重复多可以抽取成方法,这样子类就不需要再写一遍有参构造(如果不这样,都采用有参构造,会导致复用性降低,因为要在每一个子类中创建有参构造)
继承的好处:
1.提高复用性(直接继承就能使用非私有成员)(后续如果有需要用到同样的内容可以直接继承使用)
2.提高维护性(直接在父类修改)
3.让类与类之间产生关系,是多态的前提
弊端:
1.继承是入侵性的,降低了代码的灵活性(继承关系导致子类必须拥有父类的非私有成员,让子类多了些约束)-----意思是 子类继承了父类,如果子类只想拥有父类的一部分功能,而其他的非私有成员不继承,这个是达不到的,且私有的也会继承,只是子类用不了
2.增强了代码的耦合性(代码与代码之间存在关联都可称之为耦合性)
继承的应用场景:
当类与类之间存在相同(共性)的内容,且产生 is a (例如:Student类和Teacher类,都是Person的一种)的关系,就可以考虑用继承
继承的特点:
java只支持单继承,不支持多继承,但支持多层继承
(若支持多继承,子类在执行父类的成员时,应该执行哪一个父类成员,所以不允许使用)
成员包括:成员变量、成员方法、构造方法
继承的 成员(变量、方法) 之间的访问特点:
若子父类中,出现同名的成员变量,java会使用就近原则
子类局部变量→子类成员变量→父类成员变量
若一定要用
父类:super.成员名
子类:this.成员名
切记一点:this 和 super 只能在成员方法中使用(this的产生是为了解决成员名和参数名重名的问题,而super又是this引伸过来的)
this():调用本类构造方法(有参可以在括号内加参数)
应用规范:只能存在于 构造方法,只能是构造方法中,且是第一条,如果是有参构造,必须传参数(实参或代参)
super():调用父类构造方法(有参可以在括号内加参数)
重写和重载的区别:
重载:在同一个类中,只要方法名一致,参数列表不一致即可(数量、类型、顺序),与返回值无关
重写:在继承关系中!!!,方法声明一样(返回值类型、方法名、参数列表一致)
多层继承应该理解为,干爸爸的地位,而不是爷爷
干父亲:public class GanFu{ pubilc void ganfuqin(){ sout(干父亲中的方法)}} 父类:public class Fu extends GanFu{ pubilc void fu(){ sout(父类中的方法)}} 子类:public class Zi extends Fu{ pubilc void zi(){ super.fu();-------不仅继承了父类,而且还有子类的新特性 sout(子类的新特性)}} | 首先,在类中的访问父类,必须要写方法 public class Zi extends Fu{ pubilc void zi(){xxx} 不然this、super都写不了(super和this只能存在于成员方法中) 重写的目的是保留父类的内容,且有子类自己的特性 切记子父类的方法声明要一致 |
快捷重写方式:
父类的方法名+回车
@Override :注解,作用:检查子父类的方法声明是否一致
注意:
1.父类中私有方法不能被重写
2.父类静态方法,子类只能用静态方法重写,若父类为非静态,子类也必须使用非静态重写
(静态方法实际上是不允许重写的,这里只是形态上和重写的效果一致,实际上是子类对父类的重写方法进行替换/隐藏)
3.子类访问父类时,访问权限必须大于等于父类(就算在同一个包下,子类的访问权限也必须大于等于父类)
看问题时,优先考虑权限问题:(否则连访问都访问不到,就不用考虑后面的问题)
同个类 | 同个包 | 不同包,子类 | 不同包,无关类 | 总结 | |
private | ✔ | 类中 | |||
默认 | ✔ | ✔ | 同包 | ||
protected | ✔ | ✔ | ✔ | 同包+不同包的子类 | |
public | ✔ | ✔ | ✔ | ✔ | 任意 |
例:不同包下,相互继承,测试类与子类不在同一个包下,子类的是protected/默认修饰的,(测试类和子类不是继承关系)都访问不到。
同一个包下,子类访问
(注意:子类访问的意思不是创建对象访问,就算访问,也无需创建对象,因为java系统默认在每个类中自动创建空参,且每个构造方法中都存在super()父类空参构造方法,且父类构造方法是优先于子类初始化的,所以super.fu()才能调用到父类的数据)
pubilc void zi(){
super.fu();}
继承中 构造方法 的访问特点:(无论有多少层继承关系,每个子类都会继承父亲类(包括干父亲)的super()无参构造方法)
1.子类在初始化之前,一定会先完成父类数据的初始化(因为子类继承了父类的成员,有可能会在构造方法中使用到父类的成员,所以无论如何可以确定下来,父类的无参构造必须先于子类初始化完成)
2.系统在每个!!构造方法中(包括无参、有参构造),默认隐藏的一句代码super()
( super() :父类的无参构造 )