一、什么是继承?
继承是面向对象编程的三大特性之一(封装、继承、多态)。简单来说,继承就是让一个类拥有另一个类的属性和方法,就像孩子继承父母的财产一样。
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();
}
}