目录
一、介绍
- 继承是面向对象编程中的一种机制,它允许一个类(子类)从另一个类(超类或父类)继承属性和方法
- 当多个类存在相同属性(变量)和方法时,可以从中抽象出父类,父类中定义这些相同的属性和方法,通过 extends 继承父类,就可以使用其中的属性和方法
二、使用细节
子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问,私有属性和方法要通过父类提供公共的方法去访问
/**
* 子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问
* 私有属性和方法要通过父类提供公共的方法去访问
*/
public class Extends02 {
public static void main(String[] args) {
Sub sub1 = new Sub();
sub1.sayOk();
}
}
class Base {//父类
public int b1 = 11;//公开属性
protected int b2 = 22;//保护属性
int b3 = 33;//默认属性
private int b4 = 44;//私有属性
public int getB4() {//公共方法返回 b4 因为b4 是private
return b4;
}
public void Test111() {//公开方法
System.out.println("方法 test111");
}
protected void Test222() {//保护方法
System.out.println("方法 test222");
}
void Test333() {//默认方法
System.out.println("方法 test333");
}
private void Test444() {//私有方法
System.out.println("方法 test444");
}
public void getTest444() {//公共方法 因为Test444() 是private
Test444();//调用Test444()
}
}
class Sub extends Base {//子类
public void sayOk() {//子类方法
//非私有的属性和方法可以在子类直接访问
System.out.println("b1=" + b1 + " b2=" + b2 + " b3=" + b3);
//但是私有属性和方法不能在子类直接访问
//b4 是private 通过公共方法获取b4
System.out.println("b4=" + getB4());
Test111();
Test222();
Test333();
//Test444();;错误
//要通过父类提供公共的方法去访问
getTest444();
}
}
- 子类调用自己的构造器时必须先调用父类的构造器, 完成父类的初始化
/**
* 子类调用自己的构造器时必须先调用父类的构造器, 完成父类的初始化
*/
public class Extends02 {
public static void main(String[] args) {
Sub sub1 = new Sub();
}
}
class Base {//父类
public Base() {//无参构造器
System.out.println("父类 Base() 无参构造器被调用");
}
}
class Sub extends Base {//子类
public Sub() {//无参构造器
//super(); //编译器默认放置 默认调用父类的无参构造器
System.out.println("子类 Sub() 无参构造器被调用");
}
}
输出:
父类 Base() 无参构造器被调用
子类 Sub() 无参构造器被调用
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过
/**
* 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
* 如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器
* 完成对父类的初始化工作,否则,编译不会通过
*/
public class Extends02 {
public static void main(String[] args) {
Sub sub1 = new Sub("少爷");
}
}
class Base {//父类
public Base() {//无参构造器
System.out.println("父类 Base() 无参构造器被调用");
}
public Base(String name) {
System.out.println("父类 Base(String name) 构造器被调用");
}
}
class Sub extends Base {//子类
//当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
public Sub(String name) {
// 默认情况下会调用父类的无参构造器
// super()指定调用父类的Base(String name)构造器
super("aaa");
System.out.println("子类 Sub(String name)构造器被调用");
}
}
输出:
父类 Base(String name) 构造器被调用
子类 Sub(String name)构造器被调用
- 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
/**
* 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
*/
public class Extends02 {
public static void main(String[] args) {
Sub sub1 = new Sub();
}
}
class Base {//父类
public Base() {//无参构造器
System.out.println("父类 Base() 无参构造器被调用");
}
public Base(String name) {
System.out.println("父类 Base(String name) 构造器被调用");
}
public Base(String name, int age) {
System.out.println("父类 Base(String name ,int age) 构造器被调用");
}
}
class Sub extends Base {//子类
public Sub() {
//1. 调用父类无参构造器
super();//父类的无参构造器
//2. 调用父类 Base(String name) 构造器
super("少爷");
//3. 调用父类 Base(String name, int age) 构造器
super("龙部", 22);
}
}
- super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
- super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
- java 所有类都是 Object 类的子类, Object 是所有类的基类
- 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
- 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制
- 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
三、本质
- 当子类对象建立完后,建立查找关系
/**
* 1.方法区加载类 先加载顶级类 后父子 然后子类
* 2.堆里分配空间 先分配顶级类 后父子 然后子类 整个空间还是子类对象
* 当属性为私有时 内存中也会有
*/
public class Extends03 {
public static void main(String[] args) {
Son son = new Son();
//要按照查找关系来返回信息
//(1) 首先看子类是否有该属性
//(2) 如果子类有这个属性,并且可以访问,则返回信息
//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object 顶级父类
System.out.println(son.name);//输出 孙子
System.out.println(son.age);//输出 40
System.out.println(son.hobby);//输出 盘串
//当属性为不可访问时
//调用公共方法返回 私有属性
System.out.println(son.getHobby());//输出 跑步
//当爷爷类中 含有hobby 属性 父亲类中也含有hobby 属性时
//因为继承是查找关系
//从孙子类开始查找hobby 属性 当找到父亲类中发现后不管是什么访问权限 都不会再到爷爷类中查找
}
}
class GrandPa {
String name = "爷爷";
String hobby = "盘串";
}
class Father extends GrandPa {
String name = "爸爸";
int age = 40;
private String hobby = "跑步";
public String getHobby() {//公共方法返回 私有属性
return hobby;
}
}
class Son extends Father {
String name = "孙子";
}