Java中final修飾的方法是否可以被重寫(xiě)示例詳解
這是一次阿里面試?yán)锉粏?wèn)到的題目,在我的印象中,final修飾的方法是不能被子類(lèi)重寫(xiě)的。如果在子類(lèi)中重寫(xiě)final修飾的方法,在編譯階段就會(huì)提示Error。但是回答的時(shí)候還是有點(diǎn)心虛的,因?yàn)閒inal變量就可以用反射的方法進(jìn)行修改,我也不太確定是否有類(lèi)似的機(jī)制可以繞過(guò)編譯器的限制。于是面試之后特地上網(wǎng)搜了下這個(gè)問(wèn)題,這里簡(jiǎn)單記錄一下。
首先說(shuō)一下結(jié)論:沒(méi)有辦法能夠做到重寫(xiě)一個(gè)final修飾的方法,但是有其他的方法可以接近在子類(lèi)中重新實(shí)現(xiàn)final方法并在運(yùn)行時(shí)的動(dòng)態(tài)綁定的效果。
這里需要用到一個(gè)aop框架叫aspectj,它和spring aop都是比較常用的aop框架。區(qū)別是spring aop是基于動(dòng)態(tài)代理的,而aspectj有獨(dú)立的編譯器可以實(shí)現(xiàn)靜態(tài)代理。關(guān)于aspectj的安裝配置網(wǎng)上有很多文章了,這里就不再贅述,直接快進(jìn)到例子。
首先定義一個(gè)SuperClass并在其中定義一個(gè)final方法。
SuperClass.java
public class SuperClass { public final void doSomething() { System.out.println("super class do something"); } public static void main(String[] args) { SuperClass instance = new SubClass(); //此處是父類(lèi)引用和子類(lèi)對(duì)象 instance.doSomething(); } }
SubClass.java
public class SubClass extends SuperClass { //doSomething是final方法,無(wú)法被重寫(xiě) }
super class do something
Process finished with exit code 0
運(yùn)行main方法,SubClass繼承了doSomething方法,但是不能重寫(xiě),所以通常情況下調(diào)用的一定是SuperClass的doSomething方法。
在SubClass中實(shí)現(xiàn)“重寫(xiě)”的doSomething方法
SubClass.java
public class SubClass extends SuperClass { //doSomething是final方法,無(wú)法被重寫(xiě) //子類(lèi)只能在另一個(gè)函數(shù)中實(shí)現(xiàn)重寫(xiě)的邏輯 protected void overrideDoSomething() { System.out.println("sub class do something"); } }
利用環(huán)繞通知修改實(shí)際調(diào)用的方法
DoSomethingAspect.aj
public aspect DoSomethingAsepct { // 環(huán)繞通知 匹配SuperClass類(lèi)的doSomething方法 void around() : execution(* SuperClass.doSomething()) { if (thisJoinPoint.getThis() instanceof SubClass) { //調(diào)用子類(lèi)方法 ((SubClass)thisJoinPoint.getThis()).overrideDoSomething(); } else { //調(diào)用原方法 proceed(); } } }
運(yùn)行結(jié)果
sub class do something
Process finished with exit code 0
可以看到,調(diào)用SubClass的doSomething方法時(shí)實(shí)際調(diào)用的是SubClass類(lèi)的overrideDoSomething方法,而如果是SuperClass對(duì)象的話(huà)調(diào)用的又是SuperClass里的doSomething方法。根據(jù)實(shí)際的類(lèi)型決定調(diào)用的方法,就比較接近動(dòng)態(tài)綁定的機(jī)制了。而僅從調(diào)用的代碼來(lái)看和子類(lèi)重寫(xiě)方法(雖然實(shí)際是final)的效果是一樣的。
總結(jié)
到此這篇關(guān)于Java中final修飾的方法是否可以被重寫(xiě)的文章就介紹到這了,更多相關(guān)Java中final修飾的方法被重寫(xiě)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java異常處理執(zhí)行順序詳解try catch finally
- Java關(guān)鍵字詳解之final static this super的用法
- 深入理解java final不可變性
- Java try-catch-finally異常處理機(jī)制詳解
- Java基礎(chǔ)之final關(guān)鍵字作用案例
- 詳解Java關(guān)鍵字final
- Java基礎(chǔ)之關(guān)鍵字final詳解
- Java基礎(chǔ)之finally語(yǔ)句與return語(yǔ)句詳解
- JavaSE static final及abstract修飾符實(shí)例解析
- Java內(nèi)存模型final的內(nèi)存語(yǔ)義
相關(guān)文章
SpringBoot Maven項(xiàng)目中Model間的最佳繼承設(shè)計(jì)詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot中一個(gè)優(yōu)秀Maven項(xiàng)目的各Model間最佳繼承設(shè)計(jì)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-01-01SpringBoot實(shí)現(xiàn)微信及QQ綁定登錄的示例代碼
本文主要介紹了SpringBoot實(shí)現(xiàn)微信及QQ綁定登錄的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07如何解決springboot讀取配置文件的中文亂碼問(wèn)題
本篇文章主要介紹了如何解決springboot讀取配置文件的中文亂碼問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看2018-05-05Java 運(yùn)算符 動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java 運(yùn)算符 動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,需要的朋友可以參考下2017-04-04Jenkin郵件收發(fā)實(shí)現(xiàn)原理及過(guò)程詳解
這篇文章主要介紹了Jenkin郵件收發(fā)實(shí)現(xiàn)原理及過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09使用多個(gè)servlet時(shí)Spring security需要指明路由匹配策略問(wèn)題
這篇文章主要介紹了使用多個(gè)servlet時(shí)Spring security需要指明路由匹配策略問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08Java基礎(chǔ)類(lèi)之ArrayUtils工具類(lèi)詳解
這篇文章主要介紹了java.ArrayDeque類(lèi)使用方法,java.ArrayDeque類(lèi)提供了可調(diào)整大小的陣列,并實(shí)現(xiàn)了Deque接口,感興趣的小伙伴們可以參考一下2021-09-09