Java中final修饰的方法是否可以被重写示例详解
这是一次阿里面试里被问到的题目,在我的印象中,final修饰的方法是不能被子类重写的。如果在子类中重写final修饰的方法,在编译阶段就会提示Error。但是回答的时候还是有点心虚的,因为final变量就可以用反射的方法进行修改,我也不太确定是否有类似的机制可以绕过编译器的限制。于是面试之后特地上网搜了下这个问题,这里简单记录一下。
首先说一下结论:没有办法能够做到重写一个final修饰的方法,但是有其他的方法可以接近在子类中重新实现final方法并在运行时的动态绑定的效果。
这里需要用到一个aop框架叫aspectj,它和spring aop都是比较常用的aop框架。区别是spring aop是基于动态代理的,而aspectj有独立的编译器可以实现静态代理。关于aspectj的安装配置网上有很多文章了,这里就不再赘述,直接快进到例子。
首先定义一个SuperClass并在其中定义一个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(); //此处是父类引用和子类对象
instance.doSomething();
}
}
SubClass.java
public class SubClass extends SuperClass {
//doSomething是final方法,无法被重写
}
super class do something
Process finished with exit code 0
运行main方法,SubClass继承了doSomething方法,但是不能重写,所以通常情况下调用的一定是SuperClass的doSomething方法。
在SubClass中实现“重写”的doSomething方法
SubClass.java
public class SubClass extends SuperClass {
//doSomething是final方法,无法被重写
//子类只能在另一个函数中实现重写的逻辑
protected void overrideDoSomething() {
System.out.println("sub class do something");
}
}
利用环绕通知修改实际调用的方法
DoSomethingAspect.aj
public aspect DoSomethingAsepct {
// 环绕通知 匹配SuperClass类的doSomething方法
void around() : execution(* SuperClass.doSomething()) {
if (thisJoinPoint.getThis() instanceof SubClass) {
//调用子类方法
((SubClass)thisJoinPoint.getThis()).overrideDoSomething();
} else {
//调用原方法
proceed();
}
}
}
运行结果
sub class do something
Process finished with exit code 0
可以看到,调用SubClass的doSomething方法时实际调用的是SubClass类的overrideDoSomething方法,而如果是SuperClass对象的话调用的又是SuperClass里的doSomething方法。根据实际的类型决定调用的方法,就比较接近动态绑定的机制了。而仅从调用的代码来看和子类重写方法(虽然实际是final)的效果是一样的。
总结
到此这篇关于Java中final修饰的方法是否可以被重写的文章就介绍到这了,更多相关Java中final修饰的方法被重写内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
解决mybatis plus 分页查询有条数,total和pages都是零的问题
这篇文章主要介绍了解决mybatis plus 分页查询有条数,total和pages都是零的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-11-11
mybatis的mapper特殊字符转移及动态SQL条件查询小结
mybatis mapper文件中条件查询符,如>=,<,之类是不能直接写的会报错的需要转移一下,本文给大家介绍了常见的条件查询操作,对mybatis的mapper特殊字符及动态SQL条件查询相关知识感兴趣的朋友一起看看吧2021-09-09
Java查询Elasticsearch数据根据指定id检索(in查询)、sql权限过滤、多字段匹配检索及数据排序
在Java开发中Elasticsearch(简称ES)是一个非常流行的搜索引擎,它提供了强大的全文搜索和分析功能,这篇文章主要给大家介绍了关于Java查询Elasticsearch数据根据指定id检索(in查询)、sql权限过滤、多字段匹配检索及数据排序的相关资料,需要的朋友可以参考下2024-05-05
详解Guava Cache本地缓存在Spring Boot应用中的实践
Guava Cache是一个全内存的本地缓存实现,本文将讲述如何将 Guava Cache缓存应用到 Spring Boot应用中。具有一定的参考价值,感兴趣的小伙伴们可以参考一下2019-01-01
记一次线上SpringCloud Feign请求服务超时异常排查问题
这篇文章主要介绍了记一次线上SpringCloud Feign请求服务超时异常排查问题,本项目与下游项目均注册在Eureka上面,对这个1秒就超时感到很迷惑,于是开始查阅底层源码之旅。需要的朋友可以参考下2022-01-01


最新评论