Java中的继承:从入门到精通

一、什么是继承?

继承是面向对象编程的三大特性之一(封装、继承、多态)。简单来说,继承就是让一个类拥有另一个类的属性和方法,就像孩子继承父母的财产一样。

java 复制代码
// 父类(基类)
public class Animal {
    String name;
    
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
}

// 子类(派生类)
public class Dog extends Animal {
    public void bark() {
        System.out.println(name + "汪汪叫");
    }
}

// 使用
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "旺财";  // 继承了父类的属性
        dog.eat();          // 继承了父类的方法
        dog.bark();         // 自己的方法
    }
}

二、为什么要使用继承?

1. 代码复用

避免重复编写相同的代码,提高开发效率。

没有继承的糟糕代码:

java 复制代码
public class Dog {
    String name;
    int age;
    public void eat() { System.out.println("吃东西"); }
    public void sleep() { System.out.println("睡觉"); }
}

public class Cat {
    String name;
    int age;
    public void eat() { System.out.println("吃东西"); }
    public void sleep() { System.out.println("睡觉"); }
}
// 每个动物都要重复写name、age、eat()、sleep()

使用继承优化后:

java 复制代码
public class Animal {
    String name;
    int age;
    public void eat() { System.out.println("吃东西"); }
    public void sleep() { System.out.println("睡觉"); }
}

public class Dog extends Animal {
    // 自动拥有name、age、eat()、sleep()
    public void bark() { System.out.println("汪汪"); }
}

public class Cat extends Animal {
    // 自动拥有name、age、eat()、sleep()
    public void meow() { System.out.println("喵喵"); }
}

2. 建立类之间的层次关系

继承能体现现实世界中的"is-a"关系(狗是一种动物,猫也是一种动物)。


三、继承的关键语法

1. extends关键字

Java中使用extends来实现继承,一个类只能继承一个父类(单继承),但是支持多层继承。

java 复制代码
public class 子类 extends 父类 {
    // 子类特有的属性和方法
}

2. 方法重写(Override)

子类可以重写父类的方法,实现自己特有的行为。

java 复制代码
public class Animal {
    public void sound() {
        System.out.println("动物发出声音");
    }
}

public class Dog extends Animal {
    @Override  // 注解,表示重写父类方法(可选但推荐)
    public void sound() {
        System.out.println("汪汪汪");
    }
}

public class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("喵喵喵");
    }
}

3. super关键字

super用于访问父类的成员(属性、方法、构造方法)。

java 复制代码
public class Animal {
    String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void eat() {
        System.out.println(name + "在吃东西");
    }
}

public class Dog extends Animal {
    String breed;  // 品种
    
    public Dog(String name, String breed) {
        super(name);  // 调用父类构造方法,必须是第一条语句
        this.breed = breed;
    }
    
    public void eat() {
        super.eat();  // 调用父类的eat方法
        System.out.println(name + "在啃骨头");
    }
    
    public void showInfo() {
        System.out.println("名字:" + super.name);  // 访问父类属性
        System.out.println("品种:" + this.breed);
    }
}

4.this()方法如何用

this() 是Java中的一个特殊语法,用于在同一个类的构造方法中调用另一个构造方法 。它和 super() 是"兄弟",一个调用本类构造方法,一个调用父类构造方法。

java 复制代码
public class Student {
    private String name;
    private int age;
    private String grade;
    
    // 构造方法1:三个参数
    public Student(String name, int age, String grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
        System.out.println("调用三个参数的构造方法");
    }
    
    // 构造方法2:两个参数
    public Student(String name, int age) {
        this(name, age, "未分班");  // 调用构造方法1
        System.out.println("调用两个参数的构造方法");
    }
    
    // 构造方法3:一个参数
    public Student(String name) {
        this(name, 18);  // 调用构造方法2
        System.out.println("调用一个参数的构造方法");
    }
    
    public static void main(String[] args) {
        Student s1 = new Student("张三");
        // 输出:
        // 调用三个参数的构造方法
        // 调用两个参数的构造方法
        // 调用一个参数的构造方法
    }
}

不能循环调用

java 复制代码
public class Example {
    public Example() {
        this(1);  // 调用有参构造
    }
    
    public Example(int x) {
        this();   // 错误!循环调用,编译报错
    }
}

this() 和 super() 不能共存,因为两者都必须是第一条语句,所以不能同时出现。

java 复制代码
public class Parent {
    public Parent(String msg) {
        System.out.println("Parent: " + msg);
    }
}

public class Child extends Parent {
    public Child() {
        // 错误!不能同时使用
        // this("张三");
        // super("默认");
        
        // 正确做法:选择其中一个
        super("默认");  // 或者使用 this()
    }
    
    public Child(String name) {
        this();  // 调用本类无参构造
        // super() 会在 this() 调用的构造方法中执行
    }
}

四、继承中的访问权限

访问修饰符对继承的影响:

java 复制代码
package com.parent;

public class Parent {
    private String privateField = "私有";
    String defaultField = "默认";
    protected String protectedField = "受保护";
    public String publicField = "公共";
    
    private void privateMethod() {}
    void defaultMethod() {}
    protected void protectedMethod() {}
    public void publicMethod() {}
}

package com.child;
import com.parent.Parent;

public class Child extends Parent {
    public void test() {
        // privateField 不可访问
        // defaultField 不可访问(不同包)
        protectedField = "可以访问";  // ✓
        publicField = "可以访问";     // ✓
        
        // privateMethod() 不可访问
        // defaultMethod() 不可访问
        protectedMethod();  // ✓
        publicMethod();     // ✓
    }
}

五、继承的注意事项

1. 构造方法的调用顺序

先调用父类构造方法,再调用子类构造方法。

java 复制代码
public class Parent {
    public Parent() {
        System.out.println("父类构造方法");
    }
}

public class Child extends Parent {
    public Child() {
        // 隐藏了super(),自动调用父类无参构造
        System.out.println("子类构造方法");
    }
}

// 输出:
// 父类构造方法
// 子类构造方法

2. final关键字

  • final修饰的类不能被继承

  • final修饰的方法不能被重写

  • final修饰的变量是常量

java 复制代码
final class FinalClass {
    // 这个类不能被继承
}

public class Parent {
    public final void finalMethod() {
        // 这个方法不能被重写
    }
}

public class Child extends Parent {
    // 编译错误!不能重写final方法
    // public void finalMethod() {}
}

3. Object类

Java中所有类都直接或间接继承自Object类,它提供了通用方法。

java 复制代码
public class MyClass {
    // 隐式继承了Object类
    // 拥有toString(), equals(), hashCode()等方法
}

// 重写toString方法示例
public class Person {
    String name;
    int age;
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

六、实战案例:游戏角色系统

java 复制代码
// 基础角色类
public class GameCharacter {
    protected String name;
    protected int hp;
    protected int level;
    
    public GameCharacter(String name, int hp, int level) {
        this.name = name;
        this.hp = hp;
        this.level = level;
    }
    
    public void attack() {
        System.out.println(name + "发动了攻击");
    }
    
    public void takeDamage(int damage) {
        hp -= damage;
        System.out.println(name + "受到" + damage + "点伤害,剩余生命:" + hp);
    }
    
    public void showInfo() {
        System.out.printf("角色:%s,等级:%d,生命:%d%n", name, level, hp);
    }
}

// 战士类
public class Warrior extends GameCharacter {
    private int rage;  // 怒气值
    
    public Warrior(String name, int hp, int level) {
        super(name, hp, level);
        this.rage = 0;
    }
    
    @Override
    public void attack() {
        rage += 10;
        System.out.println(name + "挥舞大剑攻击!怒气:" + rage);
    }
    
    public void berserkerMode() {
        if (rage >= 50) {
            System.out.println(name + "进入狂暴模式!攻击力大幅提升!");
            rage -= 50;
        } else {
            System.out.println("怒气不足,需要" + (50 - rage) + "点怒气");
        }
    }
}

// 法师类
public class Mage extends GameCharacter {
    private int mana;  // 魔法值
    
    public Mage(String name, int hp, int level) {
        super(name, hp, level);
        this.mana = 100;
    }
    
    @Override
    public void attack() {
        if (mana >= 10) {
            mana -= 10;
            System.out.println(name + "释放火球术!剩余魔法:" + mana);
        } else {
            System.out.println(name + "魔法不足,只能普通攻击");
            super.attack();
        }
    }
    
    public void recoverMana() {
        mana += 20;
        System.out.println(name + "恢复魔法值:" + mana);
    }
}

// 使用示例
public class GameDemo {
    public static void main(String[] args) {
        Warrior warrior = new Warrior("战士小明", 1000, 10);
        Mage mage = new Mage("法师小红", 600, 10);
        
        warrior.showInfo();
        mage.showInfo();
        
        warrior.attack();
        mage.attack();
        
        warrior.berserkerMode();
        mage.recoverMana();
    }
}
相关推荐
bearpping1 小时前
怎么下载安装yarn
java
西门吹雪分身2 小时前
JDK8之四大核心函数式接口
java·函数式接口
华科易迅2 小时前
Spring AOP
java·后端·spring
架构师沉默2 小时前
Gemini 正式登陆香港,不用翻墙!
java·后端·架构
zihao_tom2 小时前
Spring WebFlux:响应式编程
java·后端·spring
一只大袋鼠2 小时前
JavaWeb ——Cookie 对象
java·servlet·javaweb·cookie·小蛋糕
程序员buddha3 小时前
Java面试八股文高级篇
java·jvm·面试
yc_xym4 小时前
SpringAI快速入门
java·springai·deepseek