1. 主页 > 好文章

super关键字的正确使用:Java继承方法调用指南


你是不是经常遇到这种情况?辛辛苦苦写了个子类,结果发现父类的方法死活调不动,控制台连个错误提示都没有。哎,这破问题我当年初学Java时也踩过坑,今天咱们就来好好唠唠这个??super关键字??到底该怎么用才不翻车。

前两天还有个哥们问我:"为啥我的子类对象调用方法时,父类里的代码不执行啊?"——这其实就是??方法重写??后没正确处理父子类关系的典型症状。新手如何快速涨粉?哦不,说错了,新手如何快速掌握这个知识点?往下看就对了。


一、super到底是个啥玩意?

咱们先看个活生生的例子。假设你爹(父类)会做饭,你(子类)继承了他的厨艺,但是想加点创新:

java复制
class Father {
    void cook() {
        System.out.println("煮白米饭");
    }
}

class Son extends Father {
    @Override
    void cook() {
        // 这里不加super会怎样?
        System.out.println("加两个荷包蛋");
    }
}

这时候你new个Son对象调用cook(),控制台只会打印"加两个荷包蛋",爹的煮饭技能凭空消失了!这时候就需要??super.cook()??来救场,就像这样:

java复制
super.cook();  // 先让老爹把饭煮了
System.out.println("加两个荷包蛋"); 

二、必须用super的3种场景

  1. ??重写方法还想用父类功能时??
    就像上面的做饭例子,不加super就彻底覆盖父类方法,跟断绝父子关系似的

  2. ??调用父类构造方法时??
    这里有个大坑:子类构造方法??必须??先调用父类构造器,你不写的话Java会偷偷给你加个super()

java复制
public Son() {
    super(); // 就算你不写,编译器也会悄悄加上
    // 你的初始化代码...
}
  1. ??父类有同名属性时??
    如果父子类都有个String name,在子类里想拿到老爹的名字就得用??super.name??

三、新手最容易犯的5个错误

我整理了个对比表格,你们感受下:

错误操作正确姿势引发的后果
忘记写super()构造方法首行显式调用编译报错:找不到父类默认构造器
在静态方法里用super改用类名调用父类静态方法直接编译卡死
跨层级调用爷爷辈的方法老老实实逐层super想调用爷爷的method?没门!
在Lambda里用super改用方法引用或匿名内部类语法直接不支持
以为super能调用叔父类方法只能直系父类Java不支持多继承,别做梦了

四、灵魂拷问环节

??Q:super能不能用在main方法里???
想啥呢!main是static方法,这时候连对象都没创建,super根本找不到归属。就像你还没出生就想继承老爹的房产证,可能吗?

??Q:父类方法被final修饰了怎么办???
凉拌!final方法就像上了锁的保险箱,子类连重写的权利都没有,更别说用super调用了。这时候只能另辟蹊径,比如重新定义个新方法。

??Q:我同时继承多个父类行不行???
醒醒,Java是单继承的!虽然能用接口实现类似效果,但super永远只能指向那个唯一的亲爹。


五、那些年我踩过的坑

记得有次做电商项目,支付模块的父类有个核心校验方法。我手贱在子类重写时忘了加super,结果凌晨三点被报警短信吵醒——所有订单的金额校验都失效了!血的教训告诉我们:??关键业务代码里用super,最好在方法开头就调用??,就像这样:

java复制
@Override
void validatePayment() {
    super.validatePayment(); // 先走完父类校验
    // 再添加子类特有的风控逻辑
    checkRiskControl(); 
}

六、小编的私房建议

说实在的,刚开始用super时总觉得它像个监视自己的老古板。但混久了发现,这玩意儿其实是个护身符。我现在养成了三个习惯:

  1. 重写方法时??先无脑敲super.xxx()??,再写新增逻辑
  2. 构造方法里??显式写出super()??,哪怕参数为空
  3. 遇到继承问题先??F12看源码??,别急着瞎猜

最后说句掏心窝的话:别老想着搞什么骚操作,Java设计super的本意就是??防止你们这些新手把继承关系玩崩了??。老老实实按规范来,等真正吃透面向对象再玩高级的,它不香吗?

本文由嘻道妙招独家原创,未经允许,严禁转载