一、作用:
1.修饰类时,该类不可以被继承
2.修饰方法时,该方法不可以被重写
3.修饰Java基本数据类型变量时,该变量的值不可再改变;修饰引用变量时,该引用变量的指向不能再改变,但引用对象的值可以改变。
4.注意final不可以修饰接口
二、final修饰变量的初始化时机
1.类变量:
在定义时赋值,或在静态块中赋值
2.实例变量:
在定义时赋值,在非静态块中赋值,或在构造器中赋值
3.注意:
a:final修饰变量只能进行一次赋值,原因很简单,final修饰变量不可变,这也保证了final线程安全。
b:final修饰的变量必须进行显示赋值。JVM不会对final修饰变量进行默认赋值,因为JVM赋值也属于赋值,若是JVM为其赋了值,就无法为其再次进行赋值,那么其值只能是默认值,也就没有了意义。
三、final常量与字符串常量
private String s1="hello";
private String s2="world";
private String s3="hello"+"world";
private String s4=s1+s2;
private String s5=s1.concat(s2);
private static final String s6="hello";
private static final String s7="world";
private String s8=s6+s7;
private String s="helloworld";
void fun() {
System.out.println(s3==s);//true
System.out.println(s4==s);//false
System.out.println(s5==s);//false
System.out.println(s8==s);//true
}
final 修饰变量只有在初始化时赋值才会被当做常量。对于类变量定义后在静态块中赋值不会被当做常量。以下代码说明了这个问题:
private static final String s1;
static {
s1="hello";
}
private static String s2=s1+"world";
private final String s3;
{
s3="hello";
}
private String s4=s3+"world";
private static final String s5="hello";
private static final String s6=s5+"world";//这里的s5被替换成"hello"
private final String s7="hello";
private final String s8=s7+"world";//这里的s7被替换成"hello"
public static void main(String[] args) {
System.out.println(s2=="helloworld");//false
Debug d=new Debug();
System.out.println(d.s4=="helloworld");//false
System.out.println(s6=="helloworld");//true
System.out.println(d.s8=="helloworld");//true
}
注意事项:
1.final不能与abstract一起使用。
当final修饰类,方法时该类不可以同时用abstract修饰。当然,final不可以修饰接口。
abstract不可以修饰变量,也就不存在与final同时修饰同一个变量的冲突。
2.对于下面的程序,A的静态块并不会被执行,也就说类A不会被加载。因为JVM会在编译时期对A.a进行传播优化,将其放入B常量池中。以后B在访问A.a时实际访问的是B中常量池的引用,也就是说B的class文件中并没有对A类的符号引用入口。这两个类在编译成class文件后就再也没有联系了。
public class A {
final static String a=“aaa”;
static {
System.out.println("doing");
}
}
public class B {
public static void main(String[] args) {
System.out.println(A.a);
}
}
3.对于下面程序:
class A{
private static String s1="123";
private static final String s2="123";
}
在类加载的准备阶段,会为静态变量分配内存并赋零值,也就是说类加载准备完成后,s1=null.
但这里,s2却是s2="123"