final普遍的认知就是“无法改变或者不需要改变”,但是在不同的应用场景,可能会存在着细微的区别。
final一般作用于数据、方法、类
1.final数据
使用final数据的原因是得到一个永不改变的编译时常量,编译器可以将该常量代入任何可能用到的它的计算中,减轻一些运行时负担。使用时有以下几点要注意
- 基本类型,使用final修饰时,表示数值恒定不变,在进行定义的时候必须对其进行赋值。
private final int n = 1;
- 不能认为某数据是final的就认为在编译时就知道它的值下面的对象必须在运行时被初始化才能知道具体的数值。
private static Random rand = new Random(47);
private final int n = rand.netxInt(10);
- 对象引用,使用final修饰时,表示的是引用更定不变,一但一个引用被初始化指向一个兑现个,就无法再把它改为指向另一个对象,但是对象本身可以更改。
final Test atomicIntegerTest = new Test ();
atomicIntegerTest = new Test ();//会编译异常
- 一个既是static又是final的域只占据一段不能修改的存储空间。
- 空final,指被声明为final但又未给定初始值的域,在关键字final的使用上提供了更大的灵活性,一个类中的final域可以做到根据对象而有所不同,却又保持了其恒定不变的特性。
package com.xie.api.moudules.concurrent; class Value{ private int i; Value(int i){i = i;} } public class Test { private final int i = 0; private final int j; private final Value value; //如果没有下面的构造方法,就会报编译时异常 public Test(){ j = 1; value = new Value(1); } public Test(int x){ j = x; value = new Value(x); } }
- final参数,java允许在参数列表中以声明的方式将参数指明为final,这意味着在方法中无法更改参数引用所指定的对象。
package com.xie.api.moudules.concurrent; class Value{ private int i; Value(int i){i = i;} } public class Test { void with(final Value value){ value = new Value(1);//编译时异常 } }
2.final方法
使用final方法的原因有两个
- 把方法锁定,以防任何继承类修改它的含义,确保在继承中使用方法的行为保持不变,并且不会被覆盖。
效率,指明为final的方法,编译器会将针对该方法的所有调用都转为内嵌调用。这种方式正在被慢慢的受到劝阻。
class Value{
final void f(){
System.out.println("Value.f()");
}
}
class Test extends Value{
@Override
void f(){//编译时异常
}
}
3.final类
将某个类整体定义为final时,表明该类不允许被继承,不允许做任何变动。
final class Value{
final void f(){
System.out.println("Value.f()");
}
}
class Test extends Value{//编译时异常
}
整理来自一个在深谋生的码农,欢迎广大码农加群交流,添加下面二维码,发送“加群”
群内小窥