javaSE的继承
设计规范
- 子类们的相同特征(共性属性、共性方法)放在父类中定义。
- 子类独有的属性和行为应该定义在子类自己里面。
- 关键字:extends
内存机制
子对象被new以后,会在堆内存中创建一个对象空间,里面会分成两块空间,一个是父类空间(super),一个是子类空间(this),这两个空间整个代表的是一个对象。子类定义的变量和方法会在存放在子类空间中,父类定义的方法和变量会存放在父类空间中。对外是两个对象,对内是两个空间。
继承的语法
继承的特点
-
子类可以继承父类的属性和行为,但是子类不能继承父类的构造器
- 子类有自己的构造器,父类构造器用于初始化父类对象。
- 从内存的机制来看,子类能继承父类的私有属性和方法,但是不能访问,父类的私有属性存在于子类对象创造的内存空间里。
- 静态属性和方法,个人认为是共享而不是继承。
-
Java是单继承模式:一个类只能继承一个直接父类。
- 为什么不支持多继承?(面试题)
- 反证法:
- 两个父类的相同方法会造成歧义。
-
Java不支持多继承,但是支持多层继承。
-当多层继承有相同的方法时,就近原则,使用父类的方法。 -
Java中所有的类都是Object类的子类。
- 所有类都能使用Object类的公共属性和方法。
继承后成员变量和成员方法的访问特点
- 在子类方法中访问成员(成员变量,成员方法)满足:就近原则
- 先在局部范围找
- 然后子类成员范围找
- 然后父类成员范围找,如果父类范围还没有找到则报错。
- 在子父类中,出现了重名的成员,会优先使用子类的,如果一定要访问父类的成员,可以使用super关键字,指定访问父类的成员。
代码示例
package com.landiao.work;
public class Animal {
String name ="动物名";
public void run(){
System.out.println("动物在跑");
}
public static void main(String[] args) {
Dog d=new Dog();
d.showName();
}
}
class Dog extends Animal{
public String name ="狗名";
public void showName(){
String name="局部名";
System.out.println(name);//局部空间成员
System.out.println(this.name);//子类成员
System.out.println(super.name);//父类成员
super.run();//父类方法
run();//子类方法
}
public void run() {
System.out.println("狗在跑");
}
}
运行结果
方法重写
- 在继承体系中,子类出现了和父类一模一样的方法声明,我们就称子类这个方法是重写的方法。
- 当子类需要父类的功能,但父类的该功能不完全满足自己的需求时,子类可以重写父类的方法。
@Override重写注释
- @Override时放在重写后的方法上,作为重写是否正确的校验注解。
- 加上该注解后如果出现重写错误,编译阶段会出现错误提示。
- 建议所有重写方法都加上@Override注解,代码安全、优雅
方法重写注意事项和要求
- 重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致
- 私有方法不能被重写。
- 子类重写父类方法时,访问权限必须大于或等于父类。(缺省 < protected < public )
- 子类不能重写父类的静态方法,如果重写会报错。
子类继承父类后,构造器的特点
-
子类中所有的构造器默认都会先访问父类中的无参的构造器,再执行自己。
-
子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。
-
子类构造器的第一行语句默认都是:
super();
不写也存在。子类构造器可以调用父类有参数构造器
父类代码示例
package com.landiao.note;
public class People {
private String name;
private int age;
public People() {
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
子类代码示例
package com.landiao.note;
public class Teacher extends People {
public Teacher(String name , int age)
{
super(name,age);
}
}
运行代码
package com.landiao.note;
public class Test {
public static void main(String[] args) {
Teacher t=new Teacher("dilei",18);
System.out.println(t.getName());
System.out.println(t.getAge());
}
}
运行结果
this和super的总结
关键字 | 访问成员变量 | 访问成员方法 | 访问构造函数 |
---|---|---|---|
this | this.成员变量(访问本类成员变量) | this.成员方法(…)(访问本类成员方法) | this()(访问本类构造器) |
super | super.成员变量(访问父类成员变量) | super.成员方法(…)(访问父类成员方法) | super(…)(访问父类构造器) |
注意:
this(…)和super(…)都只能放在构造器的第一行,二者不可同时存在