Java中的继承

什么是继承?

继承是一种类与类之间的关系,使用已经存在的类的定义作为基础建立新类。新类可以增加新的数据或新的功能,也可以用父类的功能,但是不能选择性继承父类。

继承的关系:满足A is a B的关系就可以形成继承关系。

比如:Animal类作为父类,那么Dog类和Cat类都可以是Animal类的子类,因为它们都满足:一只狗是动物/一只猫是动物

继承的实现

在Java中,使用extends关键字来表示继承关系,注意:在Java中只能使用extends继承一个类!
例如:
Animal类

public class Animal{
    private String name;

    public Animal(){

    }

    public Animal(String name){
        this.name = name;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    public void eat(){
        System.out.println(this.getName() + "在吃东西~");
    }
}

Dog类

public class Dog extends Animal{
    // 子类会继承父类的相关属性和方法,同时也可以自己添加属性和方法,但是父类的构造方法不能被继承
    private int month;
    private String name;

    public Dog(){

    }

    public Dog(int month, String name){
        this.setMonth(month);
        this.setName(name);
    }

    public void setMonth(int month){
        this.month = month;
    }

    public int getMonth(){
        return this.month;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    // 子类可以有它独特的方法
    public void sleep(){
        System.out.println(this.getName() + "在睡觉~");
    }
}

Test类:

public class Test{
    public static void main(String[] args){
        Dog dog = new Dog(2, "牛牛");
        // 调用父类的eat方法
        dog.eat();
        // 调用子类自己的sleep()方法
        dog.sleep();
    }
}

输出结果如下:
在这里插入图片描述

注意:

  • 子类可以访问父类的非私有成员

  • 父类不可以访问子类特有成员

访问修饰符

在java中,有四种访问修饰符,分别是:

  • public:允许在任意位置访问

  • private:只允许在本类中使用

  • protected:允许在本类/同包类/非同包子类中访问,不允许在非同包非子类中访问

  • 默认访问权限:允许在本类/同包类中访问,不允许在非同包类中访问

下图是对访问修饰符的总结:
在这里插入图片描述

方法重载 vs 方法重写

方法重载:同一个类中方法名称相同,参数列表不同(包括参数顺序/参数个数/参数类型)的方法,与方法的返回值和修饰符无关,也与参数名称无关

在Dog类中重载sleep()方法


// 原有的sleep()方法
public void sleep(){
    System.out.println(this.getName + "在睡觉~");
}

// 带一个参数的sleep()方法
public void sleep(int time){
    System.out.println(this.getName + "睡了" + time + "s");
}

// 带两个参数的sleep()方法
public void sleep(int time, String mood){
    System.out.println(this.getName + "睡了" + time + "s,真" + mood);
}

// 带两个参数的sleep()方法,将参数换位置
public void sleep(String mood, int time){
    System.out.println(" + mood + "" + this.getName + "睡了" + time + "s");
}

方法重写:在有继承关系的子类中,方法的返回值类型/方法名/参数类型/参数顺序/参数个数都要与父类相同,方法的访问修饰符的访问范围要大于等于父类的访问范围,与方法的参数名无关。

在Animal类中定义一个romr()方法,并在Dog类重写它。
Animal类:

public class Animal{
    public void romr(){
        System.out.println("动物在呼呼的叫~");
    }
}

Dog类:

public class Dog extends Animal{
    // 重写父类的romr()方法
    public void romr(){
        System.out.println("小狗在汪汪的叫~");
    }
}

当子类重写父类的方法后,子类对象调用的是子类的方法。

super vs this

this关键字:本类对象的引用
super关键字:父类对象的引用

this():同类的无参构造方法,必须放在方法第一行
super():父类的无参构造方法,必须放在方法第一行

So,this()和super()不能出现在同一个构造方法中!

还需要注意:this和super都不能在静态方法中调用

构造方法

关于构造方法,需要注意以下几点:

  • 父类的构造方法不允许被子类继承和重写,子类必须自己实现自己的构造方法

  • 子类构造方法默认调用父类的无参构造方法,所以不要以为无参构造方法不重要

  • 可以在子类构造方法中使用super()来调用父类允许被访问的其它构造方法,必须方法子类构造方法的第一行

Animal类:

public class Animal{
    public Animal(){
        System.out.println("我是父类的构造方法");
    }
}

Dog类:

public class Dog extends Animal{
    public Dog(){
        // 使用super()调用父类的无参构造,必须方法第一行
        super();
        System.out.println("我是子类的构造方法");
    }
}

Test类:

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

输出结果如下:
在这里插入图片描述

继承后的初始化顺序

在Java中,创建一个子类对象时的初始化顺序是怎样的呢?通过下面这段代码的输出结果看一下

Animal类:

public class Animal{
    static{
        System.out.println("我是父类的静态代码块");
    }

    {
        System.out.println("我是父类的构造代码块");
    }

    public Animal(){
        System.out.println("我是父类的构造方法");
    }
}

Dog类:

public class Dog extends Animal{
    static{
        System.out.println("我是子类的静态代码块");
    }

    {
        System.out.println("我是子类的构造代码块");
    }

    public Dog(){
        System.out.println("我是子类的构造方法"); 
    }
}

Test类:

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

输出结果如下:
在这里插入图片描述

总结:

  1. 子类实例化的过程中,首先把类加载到JVM中,查看其父类是否有静态成员(静态代码块/静态属性/静态方法),如果有,则初始化静态成员

  2. 查找子类是否有静态成员,如果有,则初始化静态成员

  3. 进行父类对象的构造,先查找父类的构造代码块,再执行父类的无参构造方法

  4. 进行子类对象的构造,执行子类的构造代码块,再执行子类的构造方法

Object类

一个类没有使用extends关键字明确标识继承关系,则默认继承Object类(包括数组)

任何java类都可以使用Object类中提供的可访问的方法

常用的方法:

  • equals():比较两个对象引用的是否为同一块空间,返回布尔值

String类重写了equals()方法,只笔记内容是否相同:

String str1 = new String("hello");
String str2 = new String("hello");
System.out.println(str1.equals(str2))  ------->返回True
  • toString()方法:返回对象的描述信息,格式:类型信息 + @ + 地址信息

final关键字

final关键字的几种用法:

  • final 类:表示该类不能有子类,可以写成public final classfinal public class

  • final 方法:表示该方法不可以被重写,但是可以被子类对象使用

  • final 方法内局部变量:只要在具体使用之前赋值即可,一旦赋值不可更改

  • final 类成员属性:可以在三个地方赋值:定义时赋值/构造方法中赋值/构造代码块中赋值,一旦赋值不可更改

注意:final 不可以修饰构造方法

final可以配合static来修饰变量,比如配置信息,这样在类的加载时就可以初始化并且不能更改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值