深入理解final

final

◆ ◆ ◆ ◆

java的关键字final的含义根据上下文会有一些细微的区别,通常是指“无法改变”。不想改变的原因一般有两种:设计、效率。一般用final来修饰数据、方法、类。

final数据

◆ ◆ ◆ ◆

数据恒定不变,比如

  1. 一个永不改变的编译时常量

  2. 一个在运行时被初始化的值,而你不希望它改变

对于编译器常量,编译器可以将该常量值带入任何可能用到它的计算式中。这类常量必须是级基本数据类型,并且以final表示,定义时必须赋值。一个既是static又是final的域只占据一段不能改变的存储空间。

注意,当对象是引用时,其含义就会有一些迷。因为对于final修饰的引用对象,使其引用不变。一旦引用呗初始化指向一个对象,就无法再改变它指向另一个对象。然而,该对象本身却是可以被修改的。

我们一般使用final数据的情况如下

对于valueOne和VAL_TWO,都是带有编译时数值的final基本类型,均可用作编译期常量,没有重大差别。对于VAL_THREE,首先为public,代表可以被用于包之外;static强调只有一份;final说明是一个常量。

然而并不是带有final就认为在编译时就可以知道它的值,比如

数值在运行时内被初始化时才会出现。i4和INT_5的差别是:i4值唯一,但是如果创建两个不同的对象,i4的值会不同;INT_5由于是static修饰,在加载时已经被初始化,不是每次创建新对象都会初始化,不会因为创建第二个对象而改变,所以无论创建几个对象,值都相同。

(以上说明的final数据都是在同一个类中成立。)

java中允许生成空白final,即声明为final但是又没给定初值,这种时候一般由不同的构造函数,在构造函数中赋初值。

final方法

◆ ◆ ◆ ◆

使用 final 方法,可能是出于对两方面理由的考虑:

  1. 为方法“上锁”,防止任何继承类改变它的本来含义。设计程序时,若希望一个方法的行为在继承期间保持不变,而且不可被覆盖或改写,就可以采取这种做法。

  2. 提高程序执行的效率。将一个方法设成 final 后,编译器就可以把对那个方法的所有调用都置入“嵌入”调用里。只要编译器发现一个 final 方法调用,就会(根据它自己的判断)忽略为执行方法调用机制而采取的常规代码插入方法(将自变量压入堆栈;跳至方法代码并执行它;跳回来;清除堆栈自变量;最后对返回值进行处理)。相反,它会用方法主体内实际代码的一个副本来替换方法调用。这样做可避免方法调用时的系统开销。

当然,若方法体积太大,那么程序也会变得雍肿,达不到到效果,因为任何提升都被花在方法内部的时间抵消了。 

Java 编译器能自动侦测这些情况,并颇为“明智”地决定是否嵌入一个 final 方法。然而,最好还是不要完全相信编译器能正确地作出所有判断。通常,只有在方法的代码量非常少,或者想明确禁止方法被覆盖的时候,才应考虑将一个方法设为final。

类内所有 private 方法都自动成为 final。由于我们不能访问一个 private 方法,所以它绝对不会被其他方法覆盖。

final类

◆ ◆ ◆ ◆

如果说整个类都是 final,就表明自己不希望从这个类继承,或者不允许其他类继承该类。
除此以外,我们或许还考虑到执行效率的问题,并想确保涉及这个类各对象的所有行动都要尽可能地有效。

以上错得很明显。

注意:

  1. 数据成员既可以是 final,也可以不是,取决于我们具体选择。应用于 final 的规则同样适用于数据成员,无论类是否被定义成 final。

  2. 将类定义成 final 后,结果只是禁止进行继承—— 没有更多的限制。由于它禁止了继承,所以一个 final 类中的所有方法都默认为 final。

  - end -  

祝各位人人都能涨20K!

每个人都是技术大牛!

点击关注,不要走开哟~

- TEN END -

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值