1.1 super关键字的基本定义与作用
想象一下你在一个大家族里,父亲掌握着家族的核心技能。当你想要继承这些技能时,就需要通过某种方式向父亲“请教”——在Java的世界里,super关键字就是这座沟通父子类的桥梁。
super本质上是一个引用变量,它指向当前对象的直接父类。每次创建子类实例时,Java都会隐式地创建一个指向父类的super引用。这个设计非常巧妙,它确保了继承体系的完整性。
我记得刚开始学Java时,总觉得super有些神秘。直到有次调试代码,看到子类对象中确实存在着父类的“影子”,才真正理解了super的意义。它就像家族传承的纽带,让子类能够自然地获取父类的特性。
1.2 super关键字的三种使用方式
调用父类构造方法 在子类构造方法中,super()总是第一个被执行的语句。即使你不写,编译器也会默默地帮你加上。这个机制保证了父类的初始化总是优先于子类。
访问父类成员变量 当子类定义了与父类同名的变量时,super就派上用场了。通过super.variableName,你可以明确地告诉Java:“我要的是父类的那个版本”。
调用父类方法 方法重写是面向对象的常见场景。但有时候,我们既想扩展父类方法,又需要保留原有逻辑。这时super.methodName()就成了最佳选择。
1.3 super与this关键字的对比分析
这对“孪生兄弟”经常让人困惑。简单来说,this指向当前对象本身,而super指向当前对象的父类部分。
它们的使用场景截然不同: - this用于区分局部变量和实例变量 - super用于突破子类对父类成员的覆盖
从内存角度理解,每个子类对象都包含完整的父类结构。this代表整个对象,而super只关注其中的父类部分。这种设计既保证了效率,又维护了清晰的层次关系。
我遇到过不少初学者在这两个关键字上栽跟头。其实记住一点就够了:当需要明确指定访问父类资源时用super,其他情况下用this。这个简单的规则能解决大部分使用场景。 public class Manager extends Employee {
private int teamSize;
public Manager(String name, double salary, int teamSize) {
super(name, salary); // 必须先初始化父类
this.teamSize = teamSize;
}
}
public abstract class BasePayment {
protected String transactionId;
protected BigDecimal amount;
public BasePayment(BigDecimal amount) {
this.transactionId = generateTransactionId();
this.amount = amount;
}
public void validate() throws PaymentException {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new PaymentException("金额必须大于零");
}
}
protected abstract void processPayment();
}
public class CreditCardPayment extends BasePayment {
private String cardNumber;
private String expiryDate;
public CreditCardPayment(BigDecimal amount, String cardNumber, String expiryDate) {
super(amount); // 必须调用父类构造方法
this.cardNumber = cardNumber;
this.expiryDate = expiryDate;
}
@Override
public void validate() throws PaymentException {
super.validate(); // 复用父类的基础验证
if (cardNumber == null || cardNumber.length() != 16) {
throw new PaymentException("信用卡号格式错误");
}
}
}
public abstract class GraphicObject {
protected int x, y;
protected String color;
public GraphicObject(int x, int y, String color) {
this.x = x;
this.y = y;
this.color = color;
}
public abstract void draw();
protected void preDraw() {
System.out.println("开始绘制图形对象");
}
protected void postDraw() {
System.out.println("图形对象绘制完成");
}
}
public abstract class Shape extends GraphicObject {
protected boolean filled;
public Shape(int x, int y, String color, boolean filled) {
super(x, y, color);
this.filled = filled;
}
@Override
public void draw() {
super.preDraw(); // 调用祖父类的方法
renderShape();
super.postDraw();
}
protected abstract void renderShape();
}
public class Circle extends Shape {
private double radius;
public Circle(int x, int y, String color, boolean filled, double radius) {
super(x, y, color, filled);
this.radius = radius;
}
@Override
protected void renderShape() {
System.out.println("绘制圆形: 位置(" + x + "," + y + "), 半径" + radius);
}
}