final关键字详解

2021-10-13  本文已影响0人  Tiger_Lam

final的作用

final根据修饰位置的不同作用也不相同,针对三种情况:
1)修饰变量,被final修饰的变量必须要初始化,赋初值后不能再重新赋值。
注意:局部变量不在我们讨论的范畴,因为局部变量本身就有作用范围,不使用private、public等词修饰。
2)修饰方法,被final修饰的方法代表不能重写。
3)修饰类,被final修饰的类,不能够被继承。
注意:final修饰的类,类中的所有成员方法都被隐式地指定为final方法。

所有的final修饰的字段都是编译期常量吗?

并不是,比如String

如何理解private所修饰的方法是隐式的final?

不太正确,private可以通过反射的方式去修改,final如果通过反射的方式去修改值的话,必须要避开编译的自动优化,例如这样:private final int a=(null!=null?0:1);

Java反射机制可以动态修改实例中final修饰的成员变量吗?

回答是分两种情况的。

  1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了。

  2. 当final修饰的成员变量在定义的时候并没有初始化值的话,那么就还能通过java反射机制来动态修改它的值。

public class MainTest {


public static void main(String[] args) {

try {  
            A a = new A();  
  
            Field field = a.getClass().getDeclaredField("a");  
  
            field.setAccessible(true);  
  
            field.set(a, 2);  
  
            System.out.println(field.get(a));  //打印  2
            System.out.println(a.getA()); //打印  1 为什么这里不是2
        } catch (SecurityException e) {  
            e.printStackTrace();  
        } catch (NoSuchFieldException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        }  
   }
}


class A {  
    private final int a=1 ;  
    
   
    
    public int getA()
    {
    return this.a;
    }
}

如果把A修改为

class A {  
    private final int a ;  //区别在于这里没给a直接赋值,而是用构造函数
    
    public A()
    {
        this.a=1;
    }
    
    public int getA()
    {
        return this.a;
    }
}

System.out.println(field.get(a));  //打印  2
System.out.println(a.getA()); //打印  2  为什么这次是2了

原因在于编译期间final类型的数据自动被优化了,即:所有用到该变量的地方都呗替换成了常量。所以 get方法在编译后自动优化成了return 1 ; 而不是 return this.a;

要想不被自动优化,可以把初始化代码改成:private final int a=(null!=null?0:1);

所以说如果想要通过反射去修改final的值,必须要避开编译期间的自动优化

final方法可以被重载吗?可以

父类的final方法能不能够被子类重写?不可以

上一篇下一篇

猜你喜欢

热点阅读