前言
在Java中声明类、变量和方法时, 可使用关键字final来修饰,表示“最终的”,一旦你将引用声明为final,你将不能改变这个引用了。
1、使用final关键字的规则
final
标记的类不能被继承。提高安全性,提高程序的可读性。
比如:String
类、System
类、StringBuffer
类final
标记的方法不能被子类重写。
比如:Object
类中的getClass()
。final
标记的变量(成员变量或局部变量)即称为常量,只能被赋值一次。名称一般全大写,用下划线分隔。final
标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋值,否则编译报错。
final double MY_PI = 3.14;
2、final修饰类
修饰类: 修饰的类不能被继承,这样可以提高安全性, 提高程序的可读性。
比如:Math
、String
等。
final class A{
}
class B extends A{//错误,不能被继承。
}
3、final修饰方法
修饰方法:该方法不可被子类重写。但是可以被重载!
final
方法比非final方法要快,因为在编译的时候已经静态绑定
了,不需要在运行时再动态绑定。
被final
修饰的方法,JVM 会尝试将其内联,以提高运行效率。
class A{
public final void print(){
System.out.println("A");
}
}
class B extends A{
public void print() {//错误, 不能被重写。
System.out.println("哈哈");
}
}
4、final修饰变量
修饰变量: 被它修饰的变量不可改变,即为常量(Constant),只能被赋值一次。常量名一般全大写,单词之间用下划线分隔。
使用static final
修饰成员变量则为全局常量
final
修饰成员变量:不会被默认初始化,所以必须显式赋值,否则无法通过编译。-
声明时赋值(推荐)
final double MY_PI = 3.14;
-
初始化块中赋值
-
每个构造器中赋值:如果只在一个构造器中进行赋值,那么调用其他构造器时该常量无法进行初始化。或者在其中一个构造器中赋值,其他构造器使用
this()
调用该构造器也可以。
-
class A{
private final String
INFO = "haha";//声明常量
public void print() {
//The final field A.INFO_can not be assigned
//INFO="heihei";
}
}
final
修饰局部变量:使用final
修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
public void show(final int num) {
// num = 20;//编译不通过
System.out.println(num);
}
5、final关键字的好处
- final关键字提高了性能。JVM和Java应用都会缓存final变量。
- 被 final 修饰的常量,在编译阶段会存入常量池中
- final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
- 使用final关键字,JVM会对方法、变量及类进行优化。
- 创建不可变类要使用final关键字。不可变类是指它的对象一旦被创建了就不能被更改了。String是不可变类的代表。不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销等等。
6、关于final的重要知识点
- 在匿名类中所有变量都必须是final变量。
- final关键字不同于finally关键字,后者用于异常处理。
- final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。
- 接口中声明的所有变量本身是final的。
- final和abstract这两个关键字是反相关的,final类就不可能是abstract的。
- final方法在编译阶段绑定,称为静态绑定(static binding)。
- 没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。
- 对于集合对象声明为final指的是引用不能被更改,但是你可以向其中增加,删除或者改变内容
private final List list= new ArrayList();
list.add("haha"); //valid
list.add("heihei"); //valid
list= new Vector(); //not valid