Java--继承

继承

继承指的是共性的抽取,从而实现代码的复用。Java中用类表示实体,每个实体间可能会存在某种关系,比方说猫和狗都是动物,我们可以将一样的地方抽取出来,实现继承的思想。A继承了B后,我们可以在B的基础上添加A特有的内容。A可以称为子类(派生类),B可以称为父类(基类或者超类)。A可以调用父类中的成员,也可以有自己特有的。

语法

修饰符class 子类名 extends 父类名 {
}

我们在这编写一个例子(动物类和狗类)

class Animal {
    String name;
    int age;
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println("吃饭");
    }
}
class Dog extends Animal {
    public Dog() {
        super("你好",18);
    }
}
public class JavaSE730 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
        System.out.println(dog.name);
        System.out.println(dog.age);
    }
}
  • 上述Dog类中并没有定义成员变量和普通成员方法,只有一个构造方法,但由于继承了Animal类,在main方法中通过子类对象可以访问到父类的内容。
  • 继承后,父类的成员都可以继承到子类中,子类可以进行访问。

使用子类方法(或对象)访问到的究竟是子类中的内容还是父类中的呢?

访问成员变量

总而言之,子类会优先访问自己的,自己没有才去访问父类继承下来的。

  1. 如果父类的成员变量和子类的成员变量名字不同的时候,直接用子类对象调用即可。
  2. 如果父类的成员变量名字和子类的名字相同,则用子类对象调用的时候会调用子类的成员变量。(子类有,就不必麻烦父类了,优先访问自己的)
  3. 如果访问的成员变量子类中有,则优先访问子类的。如果子类中没有才去父类中寻找。

访问成员方法

同理,子类会优先访问自己的,自己没有才去访问父类继承下来的。

  1. 如果子类和父类中没有相同名字的成员方法,会看访问的成员方法子类中有没有,如果有访问子类的,如果没有则访问继承父类中的,如果父类中也没用就会报错。
  2. 对于方法名字相同的时候(没有发生重载时),子类对象访问时,也是遵循子类优先原则。
  3. 但是还有一种情况,如果子类和父类相同的方法发生了重载,访问的时候会根据传递的参数来决定访问父类的还是访问子类的。

访问父类成员

上面我们已经知道了具体的访问规则,那么我们就是想要获取到子类父类有相同名称的变量,方法(没有重载)的时候父类中的成员的时候怎么办呢?

super关键字

这个关键字的主要作用是在子类方法中访问父类的成员
super和this只可以在非静态方法中使用。(静态方法也可以称为类方法,类加载的时候就会执行,而this指当前对象的引用,super指子类对象中从父类继承下来部分成员的引用,两者均依赖于对象的创建。而对象的创建晚于类加载,所以不可以在静态方法中用this或者super)

class Animal {
    String name;
    int age;
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void eat() {
        System.out.println("吃饭");
    }
}
class Dog extends Animal {
    String name = "hh";
    int age = 22;
    public Dog() {
        super("你好",18);
    }
    public void print() {
    //在子类的方法访问了父类的两个成员变量
        System.out.println(super.name);
        System.out.println(super.age);
    }
}

构造方法

在上一篇文章中我们已经介绍了类的构造方法,那么在继承的时候构造方法有什么不同呢?

既然继承,那么可以理解为是父子关系,父子嘛,肯定现有父再有子嘛,所以当我们实例化子类的时候,会先调用父类的构造方法,完成父类的创建后再调用子类的构造方法,完成子类的创建。

  1. 如果我们在编写代码的时候并没有为子类和父类编写构造方法,计算机在编译的时候会默认提供的。
//父类会默认提供这样的构造方法
    public Student() {
        
    }
//子类则和之前默认提供的构造方法稍有不同
    public A() {
    //会多这一句,这个作用是调用父类无参的构造方法
        super();
    }
  1. 如果我们不想用默认提供的,我们可以根据自己的需要去改,只不过需要注意的是,super这个语句必须在子类构造方法的第一句。
举个例子:
//父类会提供这样的构造方法
    public Student(int num, int age) {
        this.num = num;
        this.age = age;
    }
//子类
    public A() {
    //会多这一句,这个作用是调用父类含两个参数的构造方法
        super(1522);
    }
  1. super和this不可以同时使用。
  2. 在构造方法中,super()只可以出现一次

super和this

  1. 相同点
    (1)两者必须在非静态方法中使用,而且访问的是非静态的成员方法和成员变量。
    (2)两者都为Java中的关键字。
    (3)在构造方法中使用的时候,必须为构造方法的第一句,且二者不可同时存在。
  2. 不同点
    (1)this 是当前对象的引用,而super相当于是子类对象继承父类的部分成员的引用。
    (2)在非静态方法中,this用来访问当前对象的成员,super用来访问从父类继承下来的成。
    (3)构造方法中,this()调用当前类的构造方法,super()调用父类的构造方法,两者不可同时存在。
    (4)构造方法一定存在super()的调用,我们不写编译器也会加上,但是this不写就真的没有了。

继承的时候代码块的执行顺序

在上一篇文章中,我们介绍了代码块的执行顺序,那么继承关系的时候,代码块执行顺序是啥呢?

这里补充一下:实例代码块是写在类里面的{},Student student = new Student();这个语句如果也写在了类里面,这个也可以称为实例代码块。

class Animal {
    int age;
    static String name;
    static {
        System.out.println("父类的静态代码块");
    }
    {
        System.out.println("父类的实例代码块");
    }
    public Animal() {
        System.out.println("父类构造方法");
    }
}
class Dog extends Animal{
    static {
        System.out.println("子类的静态代码块");
    }
    {
        System.out.println("子类的实例代码块");
    }
    public Dog() {
        System.out.println("子类构造方法");
    }

}
public class JavaSE730 {
    public static void main(String[] args) {
        Dog dog = new Dog();
    }
}

在这里插入图片描述
注意!静态代码块还是只执行一次,再次实例化子类对象的时候不会再执行子类和父类的静态代码块。
在这里插入图片描述

继承方式

Java中继承方式有好几种,下面我们来介绍一下。

  1. 单继承
public class A extends B {
}
class B {
}
  1. 不同的类继承同一个父类
class A {
}
class B extends A {
}
class C extends A {
}
  1. 多层继承
class A {
}
class B extends A {
}
class C extends B {
}

注意

  1. Java中没有多继承,A extends B,A extends C,多继承就是一个类可以继承多个类。
  2. 我们在编写代码的时候,我们不希望出现多重继承超过三层。
  3. 我们可以通过final关键字限定类是否可以被继承。

final关键字

final关键字可以修饰变量,方法和类

  1. 修饰变量的时候,表示常量,不可再进行更改。
  2. 修饰类的时候,表示不可以再被继承。
  3. 修饰方法的时候表示不可以再被重写。

组合

组合和继承类似,也可以实现代码的复用,只不过此时并不是通过继承来复用的,而是通过将某个类作为另一个类的字段来复用。实际生活中,我们常用组合来实现代码复用。
继承是is-a的关系,狗是动物
组合而是has-a的关系,汽车有轮胎…

//轮胎类
class Tire {
    int num;
}
//汽车类
class Car {
    Tire tire;//可以将类用在另外的类中,当一个字段。这样也可以复用Tire类的代码

    public void make() {
        tire.num = 10;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值