11 继承、final、类初始化、实例初始化
lix_uan 610 1

继承

11 继承、final、类初始化、实例初始化

继承的定义

  • 子类继承父类的属性和行为,使子类对象具有与父类相同的属性和行为

继承的好处

  • 提高代码的复用性
  • 提高代码的扩展性
  • 类与类之间产生了关系,是多态的前提

继承的演示

/*
 * 定义动物类Animal,做为父类
 */
class Animal {
    // 定义name属性
    public String name; 
    // 定义age属性
    public int age;
    // 定义动物的吃东西方法
    public void eat() {
        System.out.println(age + "岁的" + name + "在吃东西");
    }
}

/*
 * 定义猫类Cat 继承 动物类Animal
 */
class Cat extends Animal {
    // 定义一个猫抓老鼠的方法catchMouse
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}

/*
 * 定义测试类
 */
public class ExtendDemo01 {
    public static void main(String[] args) {
        // 创建一个猫类对象
        Cat cat = new Cat();

        // 为该猫类对象的name属性进行赋值
        cat.name = "Tom";

          // 为该猫类对象的age属性进行赋值
        cat.age = 2;

        // 调用该猫的catchMouse()方法
        cat.catchMouse();

          // 调用该猫继承来的eat()方法
          cat.eat();
    }
}

演示结果:
抓老鼠
2岁的Tom在吃东西

继承的特点

特点一:成员变量

  • 私有(private)和公有(public)均会被子类继承
  • 子类不能直接访问父类的私有成员,但可以通过继承来的公有get和set方法访问
  • 子类成员变量和父类成员变量重名时,如果要访问父类的变量,则要通过super.调用

特点二:成员方法

  • 子类成员方法与父类重名时,会出现方法的重写(Override)

  • 重写:方法的名称一样,参数列表也一样

  • 重写的示例

    class Phone {
        public void sendMessage(){
            System.out.println("发短信");
        }
        public void call(){
            System.out.println("打电话");
        }
        public void showNum(){
            System.out.println("来电显示号码");
        }
    }
    
    //智能手机类
    class NewPhone extends Phone {
    
        //重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
        public void showNum(){
            //调用父类已经存在的功能使用super
            super.showNum();
            //增加自己特有显示姓名和图片功能
            System.out.println("显示来电姓名");
            System.out.println("显示头像");
        }
    }
    
    public class ExtendsDemo06 {
        public static void main(String[] args) {
              // 创建子类对象
              NewPhone np = new NewPhone();
    
            // 调用父类继承而来的方法
            np.call();
    
              // 调用子类重写的方法
              np.showNum();
    
        }
    }
    • 重写的注意事项
      • 子类方法的返回值类型必须是父类方法的返回值类型或者是它的子类
      • 如果父类方法返回值类型是void,那么子类也必须是void
      • 子类方法的权限修饰符必须大于等于父类的
      • 静态方法不能被重写
      • 父类私有方法不能被重写
      • 被final修饰的方法不能被重写

特点三:构造方法

  • 由于构造方法的名字是与类名一致的,所以子类无法继承父类的构造方法

  • 构造方法看的作用是初始化成员变量的,所以子类初始化的过程中,会先执行父类的初始化,子类的构造方法中默认有一个super()

  • 父类没有无参构造怎么办?

    • 子类构造器中用super(实参列表),调用父类的有参构造

      public class Student extends Person{
          private int score;
      
          public Student(String name, int age) {
              super(name, age);
          }
          public Student(String name, int age, int score) {
              super(name, age);
              this.score = score;
          }
      
          //其他成员方法省略
      }

特点四:单继承

  • Java只支持单继承,不支持多继承,但支持多层继承

    //一个类只能有一个父类,不可以有多个父类。
    class C extends A{}     //ok
    class C extends A,B...    //error
    
    class A{}
    class B extends A{}
    class C extends B{}
  • 一个父类可以同时拥有多个子类

super

  • 父类空间优于子类对象产生。创建子类对象时,会先初始化父类空间,再创建子类对象本身
  • this和super都不能出现在静态方法和静态代码块中,因为super和this都是存在于对象中的

final

  • 修饰类
    • 这个类不能被继承,没有子类
  • 修饰方法
    • 这个方法不能被重写
  • 声明常量
    • 变量用final修饰,它的值就不能被修改,变成了常量
    • 被final修饰的常量,一般所有字母都大写

类初始化

  • 一个类只会初始化一次
  • 类初始化过程中调用()方法,这个方法是编译器自动生成的,它会将静态成员变量的显示赋值语句和静态代码块中的语句按顺序合并到的方法体中,完成初始化

静态代码块

【修饰符】 class 类名{
    static{
        静态代码块语句;
    }
}

非静态代码块

【修饰符】 class 类名{
    {
        非静态代码块语句;
    }
}

实例初始化

示例初始化方法体,由四部分构成

  • super()
  • 非静态实例变量的显示赋值语句
  • 非静态代码块
  • 对应构造器中的代码

执行的特点

  • 创建对象时,才会执行
  • 按顺序执行

类初始化和实例初始化比较

  • 类初始化优先于实例初始化
  • 类初始化只做一次
  • 实例初始化每次创建对象时都会执行

构造器和非静态代码块

  • 非静态代码块是对构造器的补充
  • 非静态代码块在构造器之前执行
  • 非静态代码块是一段固定的代码,不能接收任何参数
  • 非静态代码块对于同一个类的所有对象进行的初始化处理完全相同
评论区

索引目录