继承

继承机制:是面向对象程序设计使代码可以复用的最重要的手段。它允许程序员在保持原有类特性的基础上进行扩展,增加新功能。例如狗和猫都是一种动物。如果用代码描述,将会十分复杂。(Java不支持多继承,即一个子类同时继承两个父类)

public class Cat {
    
    public String name;
    public int age;
    
    public void sleep() {
        System.out.println(this.name + "睡觉");
    }

    public void eat() {
        System.out.println(this.name + "吃猫粮");
    }
    
}

public class Dog{
    
    public String name;
    public int age;
    
    public void sleep() {
        System.out.println(this.name + "睡觉");
    }

    public void eat() {
        System.out.println(this.name + "吃狗粮");
    }
    
}

继承语法

在子类后加 extends 父类


public class Animal{

    public String name;
    public int age;

    public void sleep() {
        System.out.println(this.name + "睡觉");
    }

    public void eat() {
        System.out.println(this.name + "吃饭");
    }

}

public class Dog extends Animal{ 

    public void bark() {
        System.out.println(this.name + "汪汪汪");
    }
    
}
  1. 子类会将父类的成员变量和成员方法继承到子类中
  2. 子类应添加自己的成员,否则没有继承的必要

子类访问父类的成员

子类访问父类的成员变量

public class Base {

    public int a;
    public int b;

}

public class Derived extends Base {、

    public int a;
    public int c;

}

从上面的代码看,Base类中有ab两个变量,Derived中由c变量。

  1. 当访问的成员变量子类有的时候,访问子类成员变量。
  2. 当访问的成员变量子类没有的时候,则访问父类成员变量。
  3. 当访问的成员变量子类和父类都没有的时候,则编译器报错。

子类访问父类的成员方法

public class Base {
    
    public void Method1() {
        System.out.println("Method1方法被调用");
    }
    
}

public class Derived extends Base {

    public void Method2() {
        System.out.println("Method2方法被调用");
    }

    public void Test() {
        Method1(); //父类的方法被调用
        Method2(); //子类的方法被调用
        //Method3(); //报错
    }

}

同理,Base类中有method1方法,Derived中由method2方法。

  1. 当访问的成员方法子类有的时候,访问子类成员方法。
  2. 当访问的成员方法子类没有的时候,则访问父类成员方法。
  3. 当访问的成员方法子类和父类都没有的时候,则编译器报错。

如果我想带调用父类的成员方法,就要用到super关键字

public class Base {
    
    public int a = 10;
    
    public void Method1() {
        System.out.println("父类的Method1方法被调用");
    }
    
}

public class Derived extends Base {

    public void Method1() {
        System.out.println("子类的Method1方法被调用");
    }

    public void Test() {
        System.out.println(super.a);
        super.Method1(); //父类的Method1方法被调用
    }

}

super() 还可以使子类可以调用父类的构造方法

public class Base {

    int a = 10;

    public Base(int a) {
        this.a = a;
    }

}

public class Derived extends Base {

    public Derived(int a) {
        super(a); // 用super(参数)的形式调用指定的父类的构造方法
    }

}
  1. 用super(参数)的形式调用指定的父类的构造方法
  2. super()和this()一样,必须写在构造方法的第一行,两者不能写在同一行
  3. 只能在类的非静态方法中使用,用来访问非静态成员变量和方法

继承关系中的代码块执行顺序

执行顺序:

  1. 执行父类的静态代码块,且无论调用几次,只会在第一次调用执行一次
  2. 执行子类的静态代码块,且无论调用几次,只会在第一次调用执行一次
  3. 执行父类的实例代码块
  4. 执行父类的构造方法代码块
  5. 执行子类的实例代码块
  6. 执行子类的构造方法代码块
public class Base { //父类
    
    public static int a;
    public int b;
    
    static {
        System.out.println("父类静态代码块被执行---1");
    }

    {
        System.out.println("父类实例代码块被执行---2");
    }

    public Base(int b) {
        this.b = b;
        System.out.println("父类构造方法代码块被执行---3");
    }
    
}

public class Derived extends Base { //子类
    static {
        System.out.println("子类静态代码块被执行---4");
    }

    {
        System.out.println("子类实例代码块被执行---5");
    }

    public Derived(int b) {
        super(b);
        System.out.println("子类构造方法代码块被执行---6");
    }
}

// 父类静态代码块被执行---1
// 子类静态代码块被执行---4
// 父类实例代码块被执行---2
// 父类构造方法代码块被执行---3
// 子类实例代码块被执行---5
// 子类构造方法代码块被执行---6

final关键字

  1. final修饰变量使其变成常量
  2. final修饰类名使其不能被继承