前言
final关键字是一个常用的关键字,可以修饰变量、方法、类,用来表示它修饰的类、方法和变量都是不可改变;
final 修饰类成员变量和实例成员变量的赋值时机
对于类变量:
- 声明变量的时候直接赋初始值
- 在静态代码块中给类变量赋初始值
public class FinalTest {
//a变量直接赋值
private final static int a = 1;
private final static int b;
//b变量通过静态代码块赋值
static {
b=2;
}
}
对于实例变量:
- 在声明变量的时候直接赋值
- 在非静态代码块中赋值
- 在构造器中赋初始化值
public class FinalTest {
//c变量在在声明时直接赋值
private final int c =1;
private final int d;
private final int e;
//d变量在非静态代码块中赋值
{
d=2;
}
//e变量在构造器中赋值
FinalTest(){
e=3;
}
}
当 final 修饰的成员变量未对它进行初始化时,会出现错误吗?
java 语法规定,final 修饰的成员变量必须由程序员显示的初始化,系统不会对变量进行隐式的初始化;
final 修饰基本类型变量和引用类型变量的区别
- 当 final 修饰基本数据类型变量时,不能对基本数据类型变量重新赋值,因此基本数据类型变量不能被改变;
- 对于引用类型变量而言,它仅仅保存的是一个引用,final 只保证这个引用类型变量所引用的地址不会发生改变,即一直引用这个对象,但这个对象里面的属性是可以改变的;
final 修饰局部变量的场景
fianl 局部变量由程序员进行显示的初始化,如果 final 局部变量进行初始化之后就不能再次进行更改;
如果 final 变量未进行初始化,可以进行赋值,并且只能进行一次赋值,一旦赋值之后再次赋值就会出错;
final 修饰方法会对重载有影响吗?重写呢?
对于重载:final 修饰方法后是可以重载的;
对于重写:当父类的方法被 final 修饰的时候,子类不能重写父类的该方法;
final 修饰类的场景
final 域的重排序规则是指禁止对 final 域的写重排序到构造函数之外,可以确保在对象引用为任意线程可见之前,对象的 final 域已经被正确初始化过了,而普通域就不具有这个保障;
实现主要包含了两个方面:
- JMM 禁止编译器把 final 域的写重排序 到 构造函数 之外;
- 编译器会在 final 域写之后,构造函数 return 之前,插入一个 StoreStore 屏障。这个屏障可以禁止处理器把 final 域的写重排序到构造函数之外;
读 final 域的重排序规则,你知道吗?
是指在一个线程中,初次读对象引用和初次读该对象包含的 final 域,JMM 会禁止这两个操作的重排序,也就是读 final 域的重排序规则可以确保在读一个对象的 final 域之前,一定会先读包含这个 final 域的对象的引用;
网友评论