Java方法覆盖必须注意的3个问题:返回值、修饰符、异常
??哎我说兄弟们,你们有没有遇到过这种情况???
刚学会继承的概念,兴冲冲地给父类方法写了个覆盖版本,结果编译器直接甩你一脸红色波浪线。这时候是不是特别想摔键盘?稳住别慌,今天咱们就来唠唠方法覆盖里那些「看似简单实则暗藏杀机」的三大坑点!
第一个大坑:返回值玩变脸
??「子类方法的返回值可以随便改吗?」??——这问题就跟问「方便面能当主食天天吃吗」一样危险!咱们得记住:??覆盖方法的返回值要么和父类完全一致,要么是父类返回值的子类??(这叫协变返回类型)。举个栗子:
java复制// 父类 Animal getAnimal() { return new Animal(); } // 子类 ?允许 Dog getAnimal() { return new Dog(); } // Dog是Animal子类 // 子类 ?作死 String getAnimal() { return "旺财"; } // 直接类型不兼容
??重点来了??:协变返回类型这玩意儿是Java5之后才有的福利,你要是还在用古董级JDK版本,趁早升级吧!新手最容易栽跟头的地方就是自以为能随便改返回值类型,结果被编译器教做人。
第二个拦路虎:修饰符权限
??「我能不能把public方法改成private省事?」??——这想法就跟「为了省电把冰箱门拆了」一样离谱!记住这个铁律:??子类方法的访问权限必须≥父类方法??。具体怎么记?咱们搞个权限等级表对比下:
修饰符 | 开放程度排名 |
---|---|
public | 冠军 |
protected | 亚军 |
默认(不写) | 季军 |
private | 殿军 |
举个反例你品你细品:
java复制class 爸爸 { public void 给零花钱() { ... } } class 儿子 extends 爸爸 { // ?大逆不道!居然想缩水权限 private void 给零花钱() { ... } }
这代码要是能编译通过,那儿子岂不是能反过来限制老子的权限?Java的设计哲学可不答应!
第三个雷区:异常处理陷阱
??「父类方法抛异常,子类能不能装没事人?」??——这就像「老爸说有雷区,儿子偏要硬闯」!处理异常时有两条黄金准则:
- ??抛出的异常类型必须≤父类方法声明的异常??
- ??不能抛出父类方法没声明的新受检异常??
举个实际场景:
java复制// 父类声明 void 转账() throws IOException {...} // 子类合法操作 ? void 转账() throws FileNotFoundException {...} // FileNotFoundException是IOException子类 // 子类骚操作 ? void 转账() throws SQLException {...} // 凭空造出新异常类型
??划重点??:运行时异常(RuntimeException)不受这个限制,这也是为什么很多框架喜欢用运行时异常的原因。不过咱们新手还是悠着点,先把基础规则吃透再说!
灵魂拷问环节
??Q:这三个规则记不住怎么办???
A:记不住就写代码时开着IDE的自动提示!现在的IDE(比如IntelliJ IDEA)都会用红色波浪线提醒你哪里犯规了,就跟有个老师傅在旁边盯着你写代码似的。
??Q:万一我就是想突破限制呢???
A:年轻人,听叔一句劝——??继承是契约精神,不是让你为所欲为的??。真想搞事情,可以考虑用组合代替继承,这才是真正的高手思维。
个人碎碎念
干了这么多年Java开发,见过太多人在方法覆盖上翻车。其实这三个规则背后都藏着面向对象设计的智慧:
- 返回值限制保证了「里氏替换原则」
- 修饰符规则维护了类的封装性
- 异常约束确保了代码的可维护性
下次写覆盖方法时,不妨多花30秒检查这三个要点。记住,??代码首先是给人看的,其次才是给机器执行的??,养成好习惯比什么都重要!
本文由嘻道妙招独家原创,未经允许,严禁转载