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修饰的数据
目录 Java中final修饰的数据 有初始值的final域 final+基本数据类型 final+引用数据类型 final与static final 空白final域 final修饰的参数 基本数据 ...
- Java中final修饰符深入研究
一.开篇 本博客来自:http://www.cnblogs.com/yuananyun/ final修饰符是Java中比较简单常用的修饰符,同时也是一个被"误解"较多的修饰符.对很 ...
- java中final修饰符的使用
1.final修饰符的用法: final可以修饰变量,被final修饰的变量被赋初始值之后,不能对它重新赋值. final可以修饰方法,被final修饰的方法不能被重写. final可以修饰类,被fi ...
- Java中Final修饰一个变量时,是引用不能变还是引用的对象不能变
Java中,使用Final修饰一个变量,是引用不能变,还是引用对象不能变? 是引用对象的地址不能变,引用变量所指的对象的内容可以改变. final变量永远指向这个对象,是一个常量指针,而不是指向常量的 ...
- JAVA中final修饰符小结
一.final关键字可以用来修饰类.方法.变量.各有不同. A.修饰类(class). 1.该类不能被继承. 2.类中的方法不会被覆盖,因此默认都是final的. 3.用 ...
- Java中final修饰参数的作用
在方法参数前面加final关键字就是为了防止数据在方法体中被修改. 主要分两种情况:第一,用final修饰基本数据类型:第二,用final修饰引用类型. 第一种情况,修饰基本类型(非引用类型).这时参 ...
- 【java】final修饰符介绍
final: 最终,作为一个修饰符特点:1.可以修饰类,函数,变量2.被final修的的类不能被继承.因此类用final修饰可以避免被继承,被子类重写功能.3.被final修饰的方法不可以被重写.4. ...
- Java反射机制可以动态修改实例中final修饰的成员变量吗?
问题:Java反射机制可以动态修改实例中final修饰的成员变量吗? 回答是分两种情况的. 1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了. ...
- Java中final与 static final 修饰的常量的区别
喵喵开车,新手上路,多多关照.有任何错误请在评论区指出. ...........................................我是万恶的分界线( • ̀ω•́ )✧......... ...
随机推荐
- Go 数组&切片
数组相关 在Go语言中,数组是一种容器相关的数据类型,用于存放多种相同类型的数据. 数组定义 在定义数组时,必须定义数组的类型以及长度,数组一经定义不可进行改变. 同时,数组的长度是按照元素个数进行统 ...
- 日志分析平台ELK之日志收集器logstash常用插件配置
前文我们了解了logstash的工作流程以及基本的收集日志相关配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13761906.html:今天我们来了解下l ...
- 谈谈数据库的事务ACID
在数据库中新建一个字段并且设置为索引列,还有删除整张表的数据,类似这些操作都是一系列操作的组合,执行后不能出现中间状态,也就是不会出现新建了字段却不是索引的情况,也不会出现只有一部分数据被删除的情况. ...
- 049 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 11 break语句
049 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 11 break语句 本文知识点:break语句 break语句 break语句前情回顾 1.swi ...
- Python 为什么不支持 switch 语句?
本文出自"Python为什么"系列,请查看全部文章 在这篇文章里,我们会聊一聊为什么 Python 决定不支持 switch 语句. 为什么想要聊这个话题呢? 主要是因为 swit ...
- Spring IOC 容器预启动流程源码探析
Spring IOC 容器预启动流程源码探析 在应用程序中,一般是通过创建ClassPathXmlApplicationContext或AnnotationConfigApplicationConte ...
- css实现中间横线俩边文字效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C#数据结构-栈
栈的定义不需要多说,相信大家都非常熟悉,但是,在实际应用中栈的应用我们很少想到会去用栈结构,先上代码看下用法: Stack st = new Stack(); st.Push('A'); st.Pus ...
- 【原创】有利于提高xenomai 实时性的一些配置建议
版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正. @ 目录 一.影响因素 1.硬件 2.BISO(X86平台) 3.软件 4. 缓存使用策略与GPU 二.优化措施 1. BIO ...
- centos8平台安装redis6.0.1
一,redis的官网: https://redis.io/ redis6于5月3日正式发布,它的新增功能: acl 多线程io cluster proxy resp3协议 本文演示redis6.0.1 ...