final一个重要的用途就是定义宏变量,当定义final变量就为变量指定初始值,而这个值在编译时期就确定下来,那么这个变量就是一个宏变量,编译器会把所有使用改变量的地方直接替换改变量的值。
public class Demo{
public static void main(String[] args) {
final String a="java"+"liahuai";
final String b="lishuai"+18;
final String b2="lishuai"+String.valueOf(18);
System.out.println(b=="lishuai18");
System.out.println(b2=="lishuai18");
String s1="java1";
String s2="java2";
String s3=s1+s2;
System.out.println(s3=="java1java2");
final String s4="java4";
final String s5="java5";
String s6=s4+s5;
System.out.println(s6=="java4java5");
}
}
上面代码b,b2没有什么太大区别,只是在定义b2变量时显示将数值18转化成字符串型,由于该变量的值需要调用Stringt类型的方法,因此编译器无法在编译时期就确定b2的值,所以b2不会被当成宏变量来处理。
由于s1,s2是两个普通变量,编译器不会执行宏变量,因此编译器不会在编译时期确定s3的值,不会让s3指向字符串池中缓存的“java1java2”。
对于final实例而言,只有定义该变量的指定初始值才会有宏变量的效果,在非静态初始化块中,构造器中对final变量制指定初始值都不会有这种效果。
如果程序需要在匿名内部类中使用局部变量,那么这个局部变量必须使用final修饰符修饰。
public class Demo {
public static void main(String[] args) {
final String s = "java";
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(s + " " + i);
}
try {
Thread.sleep(100);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
}