文章目录
- final关键字基本用法
- 修饰类
- 修饰方法
- 修饰变量
- final变量 与 普通变量 区别
- final 与 static 区别
- final关键字作用
- final修饰变量能够提供性能
- final修饰的变量是线程安全的
final关键字基本用法
修饰类
final修饰的类:类不能被继承;所有成员方法都会被隐式地指定为final方法。
常见的String、Long、Integer等包装类都是final修饰的类。
修饰方法
final修饰的方法:子类无法重写该方法。
修饰变量
final修饰的变量:基本数据类型一旦赋值便无法变更;引用类型一旦初始化便无法指向其他对象。
注意:引用类型被修饰成final后,其内部的变量依旧是普通变量。
final变量 与 普通变量 区别
String str = "aabb";
final String a1 = "aa";
String test1 = a1 + "bb";
System.out.println((str == test1)); //输出 -> true
String a2 = "aa";
String test2 = a2 + "bb";
System.out.println((str == test2)); //输出 -> false
final String a3;
a3 = "aa";
String test3 = a3 + "bb";
System.out.println((str == test3)); //输出 -> false
/* 编译后的class
String str = "aabb";
String a1 = "aa";
String test1 = "aabb";
System.out.println(str == test1);
String a2 = "aa";
String test2 = a2 + "bb";
System.out.println(str == test2);
String a3 = "aa";
String test3 = a3 + "bb";
System.out.println(str == test3);
*/
当final修饰基本数据类型或String类型的时候,在编译期间能确切知道final成员变量的值的情况下,编译器会进行优化,直接把引用了final成员变量的地方替换成实际值。
例如test1的情况,在编译期就直接把拼接给做好。
final 与 static 区别
public static class TT{
public static double a = Math.random();
public final double b = Math.random();
}
TT t1 = new TT();
//输出 -> t1 static=0.35115282629834366 final=0.13670857341151854
System.out.println("t1 static=" + t1.a + " final=" + t1.b);
TT t2 = new TT();
//输出 -> t2 static=0.35115282629834366 final=0.12446163355351891
System.out.println("t2 static=" + t2.a + " final=" + t2.b);
static变量被所有的对象所共享在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
final是保证变量不可变而已,并不会所有的对象共享。
final关键字作用
final修饰变量能够提供性能
在编译期,编译器会对final修饰的变量进行优化。
//TT.java
public class TT{
private final int j = 100;
public void t(){
if (j < 100){
System.out.println("aaaaaaa");
}else {
System.out.println("bbbbbbb");
}
}
}
//TT.class
//final修饰的变量j参与的判断语句直接被简化
public class TT {
private final int j = 100;
public TT() {
}
public void t() {
System.out.println("bbbbbbb");
}
}
final修饰的变量是线程安全的
由于final的不可变机制。final修饰的变量无需担心出现并发问题。
但是需要注意,final修饰实例对象时只能保证该对象线程安全,并不能保证该对象内的非final变量也是线程安全,因为内部的这些变量还是可以被修改的。