一、final使用场景
final可以稀释变量,方法和类,用于便是修饰的内容一旦赋值之后不会再被改变,比如string类就是一个final类型的类。
二、final修饰变量
在Java中变量可以分为成员变量和局部变量。
成员变量
通常每个类中成员变量可以分为类变量(static修饰的变量)以及实例变量针对这两种类型的变量赋初始值的时机是不同的。
类变量可以再声明变量的时候直接赋初始值或者在静态代码块中给类变量赋初始值;而实例变量可以在声明变量的时候给实例变量赋初始值,在非静态初始化块中以及构造器中赋初始值。
类变量有两个时机赋初始值,而实例变量可以有三个时机赋初始值。当final变量未初始化时系统不会进行隐式初始化,会出现报错。
将这几种情况归纳整理一下:
类变量:必须要在静态初始化块中指定初始值或者声明该类变量时指定初始值,而且只能在这两个地方之一警醒指定;
实例变量:必须要在非静态初始化块,声明该实例变量或者在构造器中指定初始值,而且只能在这三个地方警醒指定。
局部变量
final局部变量有程序员进行显示初始化,如果final局部变量已经进行了初始化则后面就不能再次进行更改,如果final变量未进行初始化,可以进行赋值,当且仅有一次赋值,一旦赋值之后再次赋值就会出错。
基本数据类型和引用数据类型
final修饰的基本数据类型和引用类型有区别吗?
通过上面的例子我们已经看出来,如果final修饰的是一个基本数据类型的数据,一旦赋值后就不能再次更改,那么,如果final修饰的是引用数据类型?这个引用的对象能够改变吗?
- package passtra;
- public class FinalExample{
- //在声明final实例成员变量时进行赋值
- private final static Person person=new Person(25, 175);
- public static void main(String[] args) {
- //对final引用数据类型person进行更改
- person.age=22;
- System.err.println(person.toString());
- }
- static class Person{
- private int age;
- private int height;
- public Person(int age, int height) {
- super();
- this.age = age;
- this.height = height;
- }
- @Override
- public String toString() {
- return "Person [age=" + age + ", height=" + height + "]";
- }
- }
- }
当我们对final修饰的应用数据类型变量person的属性改成22,是可以操作成功的。
通过代码可以看出,当final修饰基本数据类型时,不能对基本数据类型变量重新赋值,因此基本数据类型不能被改变,而对于引用数据类型,它仅仅保存的是一个引用,final只保证引用类型所引用的地址不会发生改变,即一直引用这个对象,但这个对象属性是可以改变的。
宏变量
利用final变量的不可更改性,在马祖下面三个条件时,该变量就会成为一个宏变量,即一个常量。
使用final修饰符修饰,在定义该final变量时就指定了初始值,该初始值在编译时就能够唯一指定。
注意:
当程序中其他地方使用该宏变量时,编译器会直接替换该变量的值。
三、final修饰方法
重写
当父类的方法被final修饰的时候,子类不能重写父类的该方法。你如在object中getClass()方法就是说final修饰的,我们就不能重写该方法,但是hasdhCode()不是被final修饰的,我们就可以重写hashCode()方法。
重载
- package passtra;
- public class FinalExample{
- public final void test(){
- }
- //没有报错
- public final void test(int i){
- }
- }
可以看出被final修饰的方法可以重载。
四、final修饰类
当一个类被final修饰时,表明该类不能被子类继承。
子类往往可以重写父类的方法和属性,会带来一定的安全隐患,因此当一个类不希望被继承是就可以用final修饰。
五、final在JDK中有哪些应用
final经常被用作不变类上,利用final的不可更改性。
不变类
不变类的意思是创建该类的实例后,该实例的实例变量时不可改变的。满足以下条件可以成为不变类:
- 使用private和final修饰该类的成员变量;
- 提供带参数的构造器用于初始化类的成员变量;
- 仅为该类的成员变量提供getter方法,不提供setter方法,因为普通方法无法修改final修饰的成员变量;
- 如果有必要就重写object的hashCode和equals方法应该保证用equals判断相同的两个对象其HashCode值也是相等的。
JDK中提供的八个包装类和String类都是不可变的,可以看看string的实现
private final char value[];
可以看出string的value就是final修饰的,上述其他几条性质也是吻合的。
https://harmonyos.51cto.com/#zz