Java中final关键字的使用

《Java编程思想》

final是Java的一个非访问控制修饰符(non-access modifier),可以用于修饰变量、方法和类,有着“不可变”的作用。下面我们简单看一下final有哪些用法。

1 final变量

当一个变量被final修饰时,它分为两种情况:
当这个变量是一个基本数据类型时,这时就意味着该变量是可读的、不可更改的常量(constant),对于常量,有两个方面的应用:
(1)编译时常数,它永远不会改变,对于编译期的常数,编译器可将常数值“封装”到需要的计算过程里。也就是说,计算可在编译期间提前执行,从而节省运行时的一些开销;
(2)在运行期初始化的一个值,我们不希望它发生变化;
而当这个变量是一个对象的引用时,它表示的则是引用只能被赋值一次(引用不可变,但对象本身可变)。

		final int MY_CONSTANT_INT = 1;//编译时常数
//		MY_CONSTANT_INT = 2; //编译错误
		
		final int MY_RUNTIME_CONSTANT_INT = (int) (Math.random() * 10);//运行时常数
//		MY_RUNTIME_CONSTANT_INT = 3;//编译错误
		
		final List<String> MY_CONSTANT_LIST = new ArrayList<>();
//		MY_CONSTANT_LIST = new ArrayList<>();//编译错误
		MY_CONSTANT_LIST.add("aa");

2 final方法

当一个方法被声明为final时,意味着该方法不能被子类覆盖重写(overridden)。

class BaseClazz{
	
	public final void method() {
		
	}
}

class ChildClazz extends BaseClazz{
	//编辑错误
//	public final void method() {
//		
//	}
}

同时,在执行上,final方法比final方法有着更高的效率,编译器会把对final方法的调用转换为内联(inline)方法调用,即忽略为执行方法调用机制(将自变量压入堆栈;跳至方法代码并执行它;跳回来;清除堆栈自变量;最后对返回值进行处理)而采取的常规代码嵌入方法。相反,它会用方法主体内实际代码的一个副本来替换方法调用。这样做可避免方法调用时的系统开销。当然,若方法体积太大,那么程序也会变得雍肿,可能感受不到嵌入代码所带来的任何性能提升。因为任何提升都被花在方法内部的时间抵消了。 Java 编译器能自动侦测这些情况,并颇为“明智”地决定是否嵌入一个 final 方法。
另外,类的 private 方法都自动成为 final方法。

3 final类

如果一个类被final修饰的话,则表明这个类是不可继承的,我们常用的String就是一个final修饰的类:

final class BaseClazz{
	
	public final void method() {
		
	}
}

//错误
//class ChildClazz extends BaseClazz{
//	
//}

另外,final类的方法都自动成为 final方法。

4 空白final

空白final是指,已经声明但并未进行初始化的final变量,但编译器会保证该变量在实际使用前得到正确的初始化。

	final int BLANK_FINAL_INT;//空白final
	BLANK_FINAL_INT = 2;

但如果空白final作为成员变量出现,那么如何保证它的初始化呢,两种方式:

public class BlankFinalTest {
	final int BLANK_FINAL_MEM_INT1;
	//代码块初始化
	{
		BLANK_FINAL_MEM_INT1 = 1;
	}
	
	final int BLANK_FINAL_MEM_INT2;
	//构造函数初始化
	public BlankFinalTest(int i) {
		BLANK_FINAL_MEM_INT2 = i;
	}
}

使用空白final创建一个不可变(内容不可变)的对象:

class ImmutableClazz{
	
	public final int CONSTAIN_II;

	public ImmutableClazz(int i) {
		CONSTAIN_II = i;
	}
	
}
//...
	public static void main(String[] args) {
		ImmutableClazz immutableClazz = new ImmutableClazz(11);
//		immutableClazz.CONSTAIN_II = 2;//编译错误
	}

5 final和static的区别

final和static修饰符常成对出现,用于声明常量,但final和static有着什么区别呢?
static成员变量表示只保存一份副本,并且所有对象共享该变量;而final的作用是用来保证变量不可变。

final class BaseClazz{
	
    public final double FINAL_DD = Math.random();
    public static double STATIC_DD = Math.random();
	
	public final void method() {
		
	}
	
	public static void main(String[] args) {
		BaseClazz b1 = new BaseClazz();
		BaseClazz b2 = new BaseClazz();
		System.out.println(b1.FINAL_DD);
		System.out.println(b2.FINAL_DD);
		System.out.println(b1.STATIC_DD);
		System.out.println(b2.STATIC_DD);
	}
}

输出:

0.17103733059790327
0.237554219342485
0.7814031755793921
0.7814031755793921

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值