Day12 | Java继承详解

61 阅读5分钟

Java里的继承语法和面向对象的基本设计直接借鉴了C++。C++的类、继承、多态这些概念给Java提供了基础模版。

虽然采用了C++的继承机制,但是有摒弃了复杂的多继承,使用了单继承+接口的设计来避免多继承的菱形问题。

总体来说,Java的继承机制主要融合了C++的语法结构、Simula的OOP根基以及Smalltalk的纯对象模型。

同时通过接口借鉴了Objective-C的协议思想。

这样的设计既保留了经典OOP的清晰性,又通过简化(如单继承)和扩展(如接口)提升了代码的可维护性和安全性。

一、什么是继承?

在Java里,继承是指一个类可以获得另一个类的属性和方法。

通俗点讲,子类可以继承分类的功能,还能在此基础上拓展自己的行为。

package com.lazy.snail.day12;

/**
 * @ClassName Animal
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Animal {
    public void eat() {
        System.out.println("吃东西");
    }
}

Animal是定义的一个父类。

package com.lazy.snail.day12;

/**
 * @ClassName Dog
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Dog extends Animal {
    public void bark() {
        System.out.println("汪汪汪");
    }

    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
        dog.bark();
    }
}

Dog是定义的一个子类,通过extends关键字继承了Animal类。

UML类图可以通过下面的方式查看:

UML类图如下:

可以清晰的看出Dog类继承自Animal。

当在main方法创建Dog对象时,不仅可以调用Animal中定义的eat方法,也可以调用Dog中定义的bark方法。

eat方法就是Dog从Animal中继承过来的。

二、继承语法规则

Java中使用extends关键字来表示继承关系。

Java只支持单继承,一个子类只能继承一个父类。

所有的类都隐式的继承Object类(java.lang.Object)。

class A {}
class B extends A {}
class C extends A,B {} // 编译错误,不支持

看一下Object类:

IDEA左侧的Structure按钮可以列出类的所有方法和属性。

Object类开头有这样一段类注释:

Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.

Object类是整个类继承体系的根。每个类都以Object作为超类(父类)。所有对象,包括数组,都实现这个类的方法。

Dog类和Animal类中并没有定义类似toString、equals、clone、wait、notify等方法,但是dog对象却可以直接调用这些方法,就是因为Object作为了所有类的父类。子类继承了这些方法。

三、super关键字

super是子类访问父类成员的一种方式,主要有下面三种用法:

1)访问父类的成员变量

package com.lazy.snail.day12;

/**
 * @ClassName Animal
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Animal {
    String name = "动物";
}

父类定义一个成员变量name赋值为"动物"。

package com.lazy.snail.day12;

/**
 * @ClassName Dog
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Dog extends Animal {
    String name = "狗子";

    public void printName() {
        System.out.println(this.name);
        System.out.println(super.name);
    }
}

子类Dog同样定义一个成员变量name赋值为"狗子"。

super.name就是访问的父类Animal的name属性。

2)调用父类的方法

package com.lazy.snail.day12;

/**
 * @ClassName Animal
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Animal {
    void run() {
        System.out.println("动物在跑");
    }
}

父类中定义一个run方法。

package com.lazy.snail.day12;

/**
 * @ClassName Dog
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Dog extends Animal {
    @Override
    void run() {
        super.run(); // 调用父类的 run()
        System.out.println("狗在跑");
    }
}

子类中使用super直接调用父类的run方法。

3)在构造方法中调用父类构造

package com.lazy.snail.day12;

/**
 * @ClassName Animal
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Animal {
    public Animal(String name) {
        System.out.println("Animal 构造:" + name);
    }
}

定义一个有参构造Animal(String name)。

package com.lazy.snail.day12;

/**
 * @ClassName Dog
 * @Description TODO
 * @Author lazysnail
 * @Date 2025/5/27 10:28
 * @Version 1.0
 */
public class Dog extends Animal {
    public Dog() {
        super("狗子");
        System.out.println("Dog 构造");
    }
}

Dog中的无参构造,使用super调用Animal的有参构造。

四、子类构造方法

构造方法不是“自动继承”的。

子类构造方法必须负责调用父类构造方法。

如果父类没有无参构造方法,子类必须显式调用super(...),否则编译错误!

class A {
    public A(String msg) {}
}

class B extends A {
    // 编译错误:找不到默认构造方法 A()
    public B() {}
}

五、方法的重写

子类可以重写(Override)父类的方法。在重写的时候有下面几个要求:

方法名相同,参数列表完全一致。

返回值类型相同或为其子类(协变返回类型)

子类方法访问权限不能比父类更严格

可使用 @Override 注解提高可读性

在第三章第二节中Dog类中的run实际就是对Animal中的run方法的重写。

Dog有自己特定的叫声,不想继承动物的泛性的叫声,所以通过重写来修改这种行为。

六、常见疑问

Q:构造方法能被继承吗?

不能。构造方法属于类本身,不会被子类继承。但可以在子类中调用。

Q:Java为什么只支持单继承?

为了避免砖石继承(菱形问题),Java通过接口机制代替多继承。

Q:子类能否继承 private 成员?

不能直接访问。但仍然继承了,只是不可见。可以通过公共方法访问。

结语

本文就不做文字性的小结了,直接上关键点总结:

关键词关键点
extends建立子类与父类的继承关系
super子类访问父类的通道
构造顺序先构造父类 → 再构造子类
方法重写子类重新定义父类已有的方法
访问限制private 不可见,protected 子类可访问
单继承一个类只能继承一个父类,避免复杂冲突

下一篇预告

Day13 | Java多态详解

如果你觉得这系列文章对你有帮助,欢迎关注专栏,我们一起坚持下去!

更多文章请关注我的公众号《懒惰蜗牛工坊》