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]static、final修饰的方法是否可以被子类继承、是否可以被子类重写及final修饰详解
- [Java]static、final修饰的方法是否可以被子类继承、是否可以被子类重写及final修饰详解
- Java final可以修饰类、属性、方法
- Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释
- Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释
- final 不能修饰抽象类 方法可以被重载 但不能被重写
- JAVA中子类是否可以可以继承、重写父类的静态方法--总结
- java方法的重载,重写,super,this,final关键字
- java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
- JAVA中用final来修饰方法的参数
- Abstract方法不能用final,static修饰非abstract方法在abstract类中可以用fina
- Java中子类是否可以继承父类的static变量和方法而呈现多态特性
- java中抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰
- java判断一个随机数组是否可以成为等差数组,以及等差数组的判断方法之一
- Java可以重写静态方法吗?
- java 方法的参数 使用 final修饰作用--- 防止方法体内部修改
- ”static”关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法?
- 【Java面试题】60 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法?
- final关键字可以用来修饰类、方法、变量、参数,不能修饰抽象类和接口
- java 判断一个url是否可以访问的方法