java 之 继承
一、继承
1.1 、什么是继承?
- 继承就是把所有的类的公共部分(相同的成员)提取出来,放到一个类中
- 继承需要使用 extends 关键字
public class Animal{
public String name;
}
public class Dog extends Animal{}
Dog 是 Animal 的子类,Animal 是 Dog 的父类,发生继承关系后子类中包含有父类中的成员(成员方法和成员变量)
- 子类中要有自己特色的代码,否则直接调用父类就行了,还要子类干嘛?
1.2、为什么继承?
- 因为继承是把所有类的公共部分提取取来放到一个类中,那么想用这公共部分的类可以继承,那么就实现了代码的复用性
1.3、继承的好处?
- 我们知道,父类是公共成员,那么子类中也有子类的特色成员,除了实现代码的复用外,还让代码有拓展的能力
1.4、父类成员的访问
- 当子类继承父类后,通过子类的对象是可以访问父类当中的成员变量和成员方法的。
- 就是表明子类创建出来的对象,包含了父类的内容
- 子类和父类的内存布局如下
1.4.1、子类和父类不存在同名成员变量
- 子类new对象,用引用直接访问就行,比如你访问的是一个变量,他的机制就是首先在子类中寻找,如果没有,就到父类中寻找,父类中也没有的话就会报错
Dog dog1 = new Dog();
//这样就能访问到父类的name
dog1.name;
1.4.2、子类和父类的成员变量同名
- 如果有同名的话,加 this 就是子类中的,加 super 就是父类的
//假如子类中也有name 叫 旺财 , 父类中也有相同的变量name 叫 大黄
this.name; // 那么就会访问子类中的name输出旺财
super.name; // 那么就会访问父类中的name 输出大黄
如果什么都不加呢?上面我说他的访问机制是先从子类找,再到父类找,所以优先访问子类的
1.4.3、子类和父类的成员方法名字不同
- 调用谁就是谁,和成员变量一样
1.4.4、子类和父类的成员方法名字相同
- 如果完全一样(包括参数)那么子类的优先, 子类没有就调用父类的,父类没有就报错,如果构成了重载那么就是 调用谁就是谁
1.5、super关键字
1.5.1、什么是super关键字?
- super 主要作用是在子类中访问父类的成员
- 如果两个类发生了继承关系的话,我们知道子类中有父类的成员,所以如果我们想调用父类的成员那么怎么调用呢?此时就有了super ,super是子类中属于父类那一部分内存空间的标识,所以就可以使用super调用父类的成员
1.5.2、super 关键字的用法?
- super 的用法是访问父类的成员方法
- 访问父类的成员变量
- 访问父类的构造方法
1.5.3、super 关键字使用的范围
- super 只能在非静态的方法中使用,或者在子类中访问父类的成员
- super 调用父类构造方法时,和this调用当前类的另一个构造方法一样,需要调用几个参数的就调用几个参数的,并且要放在子类的构造方法中的第一行代码。我们知道this()也需要放在第一行,所以super()和 this() 不能同时使用,否者不知道哪个是第一行的
1.5.4、super 和 this 的区别
- 修饰变量时 super 调用的是父类中的成员变量,而 this 调用的是当前引用所指的对象的成员变量
- 修饰方法时 super 调用的是父类中的成员方法,而 this 调用的是当前引用所指的对象的成员方法
- 调用构造方法时 super 调用的是父类的构造方法,而this 是调用当前类的另一个构造方法
- 因为在调用完成子类的构造方法之前要调用父类的构造方法,如果父类是系统默认的构造方法(即无参的构造方法),那么在子类的构造方法中系统会在第一行默认隐藏一个super调用父类构造方法的代码。所以super()系统有时会调用,而this()只能自己写才调用
1.6、子类构造方法
- 我们知道子类中也会有成员变量的,有变量就少不了初始化,既然子类的需要初始化,那么父类的成员变量也是需要初始化的,究竟该怎么写构造方法呢?俗话说有父才有子,所以需要初始化父类的成员变量先,再初始化子类的成员变量。那么就有了在子类构造方法完成之前先调用父类的构造方法(即使用super()调用),需注意的是super()必须要放在子类构造方法的第一行
- 子类的构造方法中,一定有super();
1.7、继承关系上代码块等的初始化顺序
- 前面我们讲过代码块的初始化顺序,优先执行静态代码块,接着到实例代码块,最后到构造方法,同级的按顺序
- 那么在继承关系下,他们的执行顺序是怎么样的呢?
- 我们在上面知道,先有父再有子,先初始化父类,再初始化子类。但是我们也知道,静态代码块只要类一加载便执行,所以综上所述,先执行父类的静态代码块,再执行子类的静态代码块,接着执行父类的实例代码块,父类的构造方法,最后执行子类的构造代码块,子类的构造方法
1.8、protected 访问修饰限定符 的详解
- 被 protected 修饰后 不同包中的子类可以访问
- 就是有一个类(Animal)存在包一中,有一个类(Dog)存在包二中,并且这两个类在包二中发生的了继承关系,那么在包二 Dog 这个类中可以访问包一Animal 中 被 protected 修饰过的 成员变量
- 那么在包二中非继承包一Animal 的类是不能访问的
- 那么如果在包二中再创建一个 Cat 类 并且继承于Animal,那么它在自己的类中可以访问Animal中被 protected 修饰的成员变量,但是当Cat 在 Dog类中实例化对象时,这个引用不能访问父类中被 protected 所修饰的成员变量,所以说 他只能在自己的(Cat)子类中访问,不能在其他(Dog)子类中访问
public class Dog extends Animal{
}
1.9、继承的方式
- A 继承 B ,B < — A;单继承
- A 继承 B ,B 继承 C C < — B < — A;多层继承
在A实例化出来的对象的引用可以访问 C中的成员
- A 继承B ,a 继承 B B < — A , B < — a;一个类被多个类继承
- 注意:Java不支持一个类同时继承两个或两个以上的类
1.10、final关键字
1.10.1、什么是final关键字
- final 是不可更改的意思
- 可以修饰变量,语句,方法,类
1.10.2、final 关键字修饰变量 或字段
- 当final修饰变量时,把变量变成了常变量,意思就是把一个变量变为常量
1.10.3、final关键字修饰方法
- 当final 修饰方法时,表明这个方法不能被重写
1.10.4、final 关键字修饰类
- 当final修饰类时,表明这个类不能被继承