final修饰符
- final 可用于修饰
类
、变量
和方法
,用于表示它修饰的类、方法和变量不可改变。 - final修饰的大都应用于
基本类型域
,或不可变类
。
- 不可变类:如果
类中的每个方法都不会改变其对象
,这种类是不可变的类。例如String
类。
- 不可变类:如果
- 对于
可变类
,使用final修饰只是
表示存储在对象变量中的对象引用不会再指向其他对象
,不过这个对象中的属性可以更改
。
final修饰特点
- 修饰
类
时,类不能被继承
。 - 修饰
变量
时,变量就变成了常量
,表示该变量一旦获取了初始值
就不可被改变
,就不能被重新赋值
。包括类变量(静态)和实例变量(非静态)。一般与public static
配合使用。 - 修饰
方法
时,方法不能被重写
。 - final修饰局部变量时:
- 方法内部或者方法声明上
- 基本类型:值不能被改变
引用类型
:地址引用不能被改变,不会再指向其他对象,但是对象中的属性可以改变。
会报 “无法为最终变量x分配值” 的错误
final变量的初始化时机
final成员变量
final
修饰的成员变量必须显式的进行初始化赋值来指定初始值
,否则默认值的是个无效值
,会报“可能尚未初始化变量xxx
”的错误。//方式1:直接进行显式得初始化赋值,不进行赋值,会报错 Class Demo{ final int num ; //没有显式赋值,报错 final int num = 10; //进行显式得初始化赋值 public Demo(){ } }
也可以在
构造方法执行完毕前
对其进行初始化赋值
//方式2:在构造方法执行完毕之前进行赋值初始化 Class Demo{ final int num; public Demo(){ num = 10; //在构造方法执行完毕之前进行赋值初始化 } }
当
类初始化
时,系统会为类的类变量
分配内存并分配默认值
;当创建对象
时,系统会为该对象的实例变量
分配内存,并分配默认值
。也就是说,当执行静态初始化块
是可以对类变量
赋初始化值
,当执行普通初始化块、构造器
时可对实例变量
赋初始化值
。即成员变量的初始化值可以在定义该变量时指定默认值,可以在初始化块、构造器中初始化值。
为什么final修饰的成员变量必须显式的进行初始化呢?
- 对于
final
修饰的成员变量而言,一旦有了初始化值,就不能被重新赋值
。如果既没有
在定义
成员变量时指定初始值
,也没有在初始化、构造器中
为成员变量指定
初始值,那么这些成员变量的值就会一直是系统默认值,即系统默认分配的0、’\u0000’、false或null,那么这么成员变量就无任何意义。所以final修饰的成员变量必须由程序员显式的指定初始化值
。
- 对于
归纳一下final修饰的类变量、实例变量能指定初始值的地方:
类变量
:必须在静态初始化块
中指定初始值或在声明定义该变量时
指定初始值,并且只能在这两处的其中之一指定
。实例变量
:必须在非静态初始化块
中、声明该实例变量时
或构造器中
指定初始值,并且只能在三个地方之一指定
。- final
实例
变量不能
在静态代码块
中指定初始值 - 因为静态代码块是静态成员,
不能访问非静态成员
。 final类变量
(静态变量)不能
放在普通初始化块
中指定初始值- 因为
类变量在类初始化时已经被初始化了
,普通初始化块不能再
对其重新赋值
了。 - final成员变量都
不能在普通方法中
初始化值。 - 以下代码示例为final成员变量初始化总结:
public class FinalVariableTest { // 定义成员变量时指定默认值,合法。 final int a = 6; // 下面变量将在构造器或初始化块中分配初始值 final String str; final int c; final static double d; // 既没有指定默认值,又没有在初始化块、构造器中指定初始值, // 下面定义的ch实例变量是不合法的。 // final char ch; // 初始化块,可对没有指定默认值的实例变量指定初始值 { //在初始化块中为实例变量指定初始值,合法 str = "Hello"; // 定义a实例变量时已经指定了默认值, // 不能为a重新赋值,因此下面赋值语句非法 // a = 9; } // 静态初始化块,可对没有指定默认值的类变量指定初始值 static { // 在静态初始化块中为类变量指定初始值,合法 d = 5.6; } // 构造器,可对既没有指定默认值、有没有在初始化块中 // 指定初始值的实例变量指定初始值 public FinalVariableTest() { // 如果在初始化块中已经对str指定了初始化值