深入理解final关键字以及一些建议

引子:一说到final关键字,相信大家都会立刻想起一些基本的作用,那么我们先稍微用寥寥数行来回顾一下。

一、final关键字的含义

final是Java中的一个保留关键字,它可以标记在成员变量、方法、类以及本地变量上。一旦我们将某个对象声明为了final的,那么我们将不能再改变这个对象的引用了。如果我们尝试将被修饰为final的对象重新赋值,编译器就会报错。

 

二、用法

1.修饰变量

final修饰在成员变量或者局部变量上,那么我们可以称这个变量是final变量,这可能使我们用到最多的地方,举个栗子:常量(虽然现在建议使用枚举类来代替常量)。

深入理解final关键字以及一些建议

如果我们将被final修饰的变量重新赋值,编译器就会报出如图:cannot assign a value to final variable.(不能给final变量赋值)

 

2.修饰方法

被final所修饰的方法将无法被子类重写。

使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。” -- 摘自《Java编程思想》

因此如果你认为一个方法的功能已经足够完整了,子类中不需要改变的话,你可以声明此方法为final。final方法比非final方法要快,因为在编译的时候已经静态绑定了,不需要在运行时再动态绑定(正如编程思想中所提到的,在现在几版较新的JDK中,已经几乎没有性能差别了)。

深入理解final关键字以及一些建议

(当我们尝试重写的时候编译器就会报错)。

注:类的private方法会隐式地被指定为final方法。

 

3.修饰类

如果某个类被final所修饰,那么表明这个的功能通常是完整的;该类将不能被继承。并且final类的所有方法都会被隐式的修饰成final

 

4.ps:匿名类中的所有变量都必须是final的。

 

三、关键字final的好处小结

final关键字提高了性能。JVM和Java应用都会缓存final变量。

final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。

使用final关键字,JVM会对方法、变量及类进行优化。

对于不可变类,它的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销。

 

四、来自《Effective Java》中的一些建议

该书的第17条:要么为了继承而设计,并提供文档说明,要么就禁止继承

该条目提醒我们,如果类不是被设计用来继承的,那么这个类就应该被禁止继承(听起来有点绕,但细想下来的设计思想是很好的),否则就应该提供足够的文档及注释(具体可参考java.util.AbstractCollection这个骨架实现里的注释文档规范)。

而禁止类被子类化的方法通常有两个:

1.将所有的构造器设为私有的(private)或者包级私有的(default),并使用静态工厂方法来代替构造器;

2.将类标记为final。

 

五、思考

1.一些思考回头再来审视我们日常中的程序,我们可能已经习惯了不去那么刻意的使用final,顶多在写常量的时候用一用,但实际上我们很多的类,方法或者变量是不需要被改变的,或者说不会被继承的。比如我在刚读到《Effective Java》中的这个条目后,回首自己正在做的一个项目中审视了一下,我首先将自己的domain层中的一些类标为了final,因为我觉得这些类是不可能被继承的,如果继承了是不太符合设计的,并且程序运行没有异常,同时修改的还有我的依赖注入方式(参考我的上一篇博客:Spring注解依赖注入的三种方式的优缺点以及优先选择)

我重新纠正了一下自己在设计类的时候的思想顺序:之前自己在准备写一个类的时候(虽然通常我是不给类加final的= =),可能觉得这个类(变量或者方法)不能被改变,有很强烈的这种想法时才会加上final,但现在是:这个类需不需要使他可以被子类化?如果在以后的项目更新,迭代中,并不需要,那么我会毫不犹豫的给他加上final。

 

2."final关键字能提升性能"

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsyyg.html