对于 Java 中的 final 关键字, 我们首先可以从字面意思上去理解, 百度翻译显示如下:
也就是说 final 英文意思表示是最后的, 不可更改的. 那么对应在 Java 中也是表达这样的意思, 可以用 final 关键字修饰变量, 方法和类. 不管是用来修饰什么, 其本意都是指 "它是无法更改的", 这是我们需要牢记的, 为什么要无法更改? 无非就是设计所需或者能提高效率, 与前面介绍 static 关键字需要记住其与对象无关的理念一样, 牢记 final 的不可变的设计理念后再来了解 final 关键字的用法, 便会顺其自然了.
1, 修饰变量
稍微有点 Java 基础的都知道用 final 关键字修饰的变量称为常量, 常量的意思是不可更改. 变量为基本数据类型, 不可更改很容易理解, 那么对于引用类型呢? 不可能改的是其引用地址, 还是对象的内容?
我们首先构造一个实体类: Person
- package com.ys.bean;
- /**
- * Create by YSOcean
- */
- public class Person {
- private String name;
- public Person(String name) {
- this.name = name;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- View Code
接着根据创建一个 Person 对象:
可以看到, 首先通过 final 关键字修饰一个对象 p, 然后接着将 p 对象指向另一个新的对象, 发现报错, 也就是说 final 修饰的引用类型是不能改变其引用地址的.
接着我们改动 p 对象的 name 属性:
发现程序没有报错.
结论: 被 final 修饰的变量不可更改其引用地址, 但是可以更改其内部属性.
2, 修饰方法
final 关键字修饰的方法不可被覆盖.
在Java 编程思想第 4 版 7.8.2 章节 final 方法 p176 页这样描述: 使用 final 方法原因有两个:
, 第一个原因是把方法锁定, 以防止任何继承类修改它的含义, 这是出于设计的考虑: 想要确保在继承中使方法的行为保持不变, 并且不会被覆盖.
, 第二个原因是效率, 在 Java 的早期实现中, 如果将一个方法声明为 final, 就是同意编译器将针对该方法的所有调用都转为内嵌调用, 内嵌调用能够提高方法调用效率, 但是如果方法很大, 内嵌调用不会提高性能. 而在目前的 Java 版本中 (JDK1.5 以后), 虚拟机可以自动进行优化了, 而不需要使用 final 方法.
所以 final 关键字只有明确禁止覆盖方法时, 才使用其修饰方法.
PS:Java 编程思想中指出类中所有的 private 方法都隐式指定为 final 的, 所以对于 private 方法, 我们显式的声明 final 并没有什么效果. 但是我们创建一个父类, 并在父类中声明一个 private 方法, 其子类中是能够重写其父类的 private 方法的, 这是为什么呢?
父类: Parent.class
- package com.ys.bean;
- /**
- * Create by YSOcean
- */
- public class Parent {
- private void say(){
- System.out.println("parent");
- }
- }
子类: Son.class
- package com.ys.bean;
- /**
- * Create by YSOcean
- */
- public class Son extends Parent {
- private void say(){
- System.out.println("son");
- }
- }
其实仔细看看, 这种写法是方法的覆盖吗? 我们通过多态的形式并不能调用到父类的 say() 方法:
并且, 如果我们在子类的 say() 方法中, 添加 @Override 注解也是会报错的.
所以这种形式并不算方法的覆盖.
3, 修饰类
final 修饰类表示该类不可被继承.
也就是说不希望某个类有子类的时候, 用 final 关键字来修饰. 并且由于是用 final 修饰的类, 其类中所有的方法也被隐式的指为 final 方法.
在 JDK 中有个最明显的类 String , 就是用 final 修饰的, 将 String 类用 final 修饰很重要的一个原因是常量池. 关于 String 类的描述, 可以参考我的这篇博客.
来源: https://www.cnblogs.com/ysocean/p/9202015.html