Appearance
2026-08-27 · 子类复用父类的属性和方法——代码复用的核心机制。
Java 继承
1. 继承基础
用 extends 关键字,子类继承父类的属性和方法:
java
// 父类
public class Animal {
String name;
int age;
public void eat() {
System.out.println(name + " 在吃东西");
}
public void sleep() {
System.out.println(name + " 在睡觉");
}
}
// 子类
public class Dog extends Animal {
String breed; // 子类特有的属性
public void bark() { // 子类特有的方法
System.out.println(name + " 在汪汪叫");
}
}
// 使用
Dog dog = new Dog();
dog.name = "旺财"; // ✅ 继承了父类的属性
dog.breed = "金毛";
dog.eat(); // ✅ 继承了父类的方法
dog.bark(); // ✅ 子类特有方法继承规则:
- Java 只支持单继承(一个子类只能有一个父类)
- 可以多层继承(A → B → C)
- 子类可以有自己的属性和方法
多层继承(A → B → C)尽量少用,层级太深会很复杂。一般不超过两层。
2. 继承中的变量
子类和父类有同名变量时:
java
public class Parent {
String name = "父类";
}
public class Child extends Parent {
String name = "子类";
public void print() {
System.out.println(name); // 子类
}
}
Child c = new Child();
c.print(); // 子类(就近原则:优先用子类自己的)变量访问顺序(就近原则):
- 当前类(局部变量 → 成员变量 → 父类成员变量)
- 父类
- 父父类(以此类推)
变量不存在重写(override),只有重名遮蔽。子类和父类的
name是两个独立的变量,互不影响。
3. 继承中的方法
子类可以重写父类的方法(方法重写 Override):
java
public class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
public class Dog extends Animal {
@Override // 注解,告诉编译器这是重写,不是新方法
public void makeSound() {
System.out.println("汪汪汪!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("喵喵喵!");
}
}
Dog dog = new Dog();
Cat cat = new Cat();
dog.makeSound(); // 汪汪汪!
cat.makeSound(); // 喵喵喵!方法重写规则:
- 方法名必须相同
- 参数列表必须相同
- 返回值类型必须相同(或协变,子类返回值可以是父类返回值的子类型)
- 修饰符不能更严格(父类是
public,子类不能是private) - 不能抛出更多/更大的受检异常
java
// ✅ 合法重写
public class Parent {
public String get() { return ""; }
}
public class Child extends Parent {
@Override
public String get() { return "child"; } // 返回值类型相同
}
// ❌ 不合法(返回值类型不同)
public class Child extends Parent {
@Override
public int get() { return 0; } // 编译报错
}
@Override不是必须的,但强烈建议加上。它能让编译器帮你检查是否正确重写了。
4. super 与 this
java
public class Parent {
String name = "父类";
public Parent() {
System.out.println("父类无参构造");
}
public Parent(String name) {
System.out.println("父类有参构造:" + name);
}
public void show() {
System.out.println("父类方法:" + name);
}
}
public class Child extends Parent {
String name = "子类";
public Child() {
super(); // 调用父类无参构造(必须是第一行!)
System.out.println("子类无参构造");
}
public Child(String name) {
super(name); // 调用父类有参构造(必须是第一行!)
this.name = name;
System.out.println("子类有参构造:" + name);
}
@Override
public void show() {
System.out.println("父类的:" + super.name); // 访问父类的 name
System.out.println("子类的:" + this.name); // 访问子类的 name
}
}
Child c = new Child("小明");
// 输出:
// 父类有参构造:小明
// 子类有参构造:小明super vs this:
this:指向当前对象(子类自己的)super:指向父类对象(父类自己的)super():调用父类构造方法,必须写在子类构造方法的第一行this():调用本类的其他构造方法,也必须写在第一行super()和this()不能同时存在(都是第一行)
记忆:
this指向自己,super指向父亲。构造方法里super()是必写的(Java 默认自动加,但有参构造需要手动调)。
5. 继承构造方法特点
java
public class Parent {
public Parent() {
System.out.println("父类无参构造");
}
public Parent(String name) {
System.out.println("父类有参构造");
}
}
public class Child extends Parent {
public Child() {
super(); // 自动调用父类无参构造
System.out.println("子类无参构造");
}
public Child(String name) {
super(name); // 调用父类有参构造
System.out.println("子类有参构造");
}
}
Child c = new Child();
// 输出:
// 父类无参构造
// 子类无参构造
Child c2 = new Child("test");
// 输出:
// 父类有参构造
// 子类有参构造构造方法执行顺序:先父类,后子类。创建子类对象时,父类构造方法一定会先执行。
6. 父类 private 成员变量访问
java
public class Parent {
private String name = "父类私有";
public String getName() {
return name; // 通过 public 方法暴露
}
}
public class Child extends Parent {
public void print() {
// System.out.println(name); // ❌ 不能直接访问父类 private 成员
System.out.println(getName()); // ✅ 通过父类的 public 方法访问
}
}子类访问父类 private 成员的方式:
- 通过父类的 getter 方法(最常用)
- 通过父类的 public/protected 方法
- 通过 构造方法(
super(参数)传值)
java
// 方式3:构造方法
public class Parent {
private String name;
public Parent(String name) {
this.name = name;
}
}
public class Child extends Parent {
private int age;
public Child(String name, int age) {
super(name); // 把值传给父类构造方法
this.age = age;
}
}private 成员只能在本类访问,子类必须通过方法或构造方法间接访问。这是封装的体现,不是缺陷。