extends 关键字实现,子类继承父类的方法和属性,并
Java继承的实现机制详解
Java中的继承是面向对象编程(OOP)的核心特性之一,它允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的复用和扩展,以下是Java继承的详细实现机制:
继承的基本概念
继承是一种“is-a”关系,子类通过继承父类,可以获取父类的字段和方法,同时可以扩展或重写父类的功能,在Java中,继承通过extends关键字实现。
语法示例:
class Parent {
int age;
void display() {
System.out.println("Parent class method");
}
}
class Child extends Parent {
void display() {
System.out.println("Child class method");
}
}
继承的实现原理
Java中的继承是通过原型委托模型(Prototype Model)实现的,当一个类继承另一个类时,子类会获得父类的所有非私有字段和方法,同时可以定义自己的新字段和方法。
1 内存布局
在内存中,子类对象包含以下部分:
- 父类字段:子类对象会包含父类的所有非私有字段。
- 子类字段:子类自己定义的字段。
- 方法表:子类对象的方法表会包含父类的方法(除非被重写)以及子类自己定义的方法。
2 方法调用
当子类对象调用一个方法时,Java虚拟机(JVM)会首先检查子类是否重写了该方法,如果重写了,则调用子类的方法;如果没有重写,则调用父类的方法,这个过程称为动态绑定。
继承的类型
Java中的继承分为两种:
| 类型 | 描述 |
|---|---|
| 单继承 | 一个子类只能继承一个父类。 |
| 多继承 | Java不支持多继承,但可以通过接口实现类似功能。 |
1 单继承
Java中的类只能继承一个父类,这避免了多继承带来的复杂性问题(如菱形继承问题)。
2 接口继承
虽然Java不支持类的多继承,但一个类可以实现多个接口,从而间接实现多继承的效果。
继承中的访问修饰符
父类的字段和方法的访问修饰符会影响子类的访问权限:
| 父类成员的访问修饰符 | 子类是否可以访问 | 子类外部是否可以访问 |
|---|---|---|
public |
是 | 是 |
protected |
是 | 否 |
default(包级) |
是 | 否 |
private |
否 | 否 |
示例:
class Parent {
public int publicField;
protected int protectedField;
int defaultField;
private int privateField;
}
class Child extends Parent {
void accessFields() {
publicField = 1; // 可访问
protectedField = 2; // 可访问
defaultField = 3; // 可访问
// privateField = 4; // 不可访问
}
}
方法重写(Override)
子类可以重写父类的方法,以提供新的实现,重写方法必须满足以下条件:
- 方法名相同。
- 参数列表相同。
- 返回类型相同或协变(Java 5及以上支持协变返回类型)。
- 访问修饰符不能比父类更严格。
示例:
class Parent {
void display() {
System.out.println("Parent display");
}
}
class Child extends Parent {
@Override
void display() {
System.out.println("Child display");
}
}
构造函数与继承
子类的构造函数不会直接继承父类的构造函数,但子类可以通过super()调用父类的构造函数,如果子类没有显式调用super(),JVM会默认调用父类的无参构造函数。
示例:
class Parent {
Parent() {
System.out.println("Parent constructor");
}
}
class Child extends Parent {
Child() {
super(); // 显式调用父类构造函数
System.out.println("Child constructor");
}
}
继承中的静态成员
- 静态字段:子类继承父类的静态字段,但它们是共享的,修改静态字段的值会影响父类和子类。
- 静态方法:子类不会继承父类的静态方法,但可以通过父类名调用。
示例:
class Parent {
static int staticField = 10;
static void staticMethod() {
System.out.println("Parent static method");
}
}
class Child extends Parent {
void accessStatic() {
staticField = 20; // 修改静态字段
Parent.staticMethod(); // 调用父类静态方法
}
}
继承的优缺点
| 优点 | 缺点 |
|---|---|
| 提高代码复用性 | 可能增加耦合性 |
| 支持多态性 | 继承层次过深会导致复杂性增加 |
| 易于扩展和维护 | 父类的变化可能影响子类 |
继承与组合的选择
在选择继承和组合时,通常遵循以下原则:
- 使用继承:当子类和父类之间是“is-a”关系时。
- 使用组合:当类之间是“has-a”关系时。
示例:
- 继承:
Dog extends Animal(狗是一种动物)。 - 组合:
Car has Engine(汽车有一个发动机)。
FAQs
Q1: Java中的继承为什么不支持多继承?
A1: Java不支持类的多继承是为了避免菱形继承问题(Deadly Diamond of Death),多继承会导致多个父类拥有同名方法或字段,从而引发冲突和复杂性,虽然Java不支持类的多继承,但可以通过接口实现多继承的效果。
Q2: 子类如何调用父类中被重写的方法?
A2: 子类可以通过super关键字调用父类中被重写的方法。
class Parent {
void display() {
System.out.println("Parent display");
}
}
class Child extends Parent {
@Override
void display() {
super.display(); // 调用父类的方法
System.out.println("Child display");
