public static final String BACE_INFO = "baseinfo";首先,先明确一下,
- final修饰的变量不可以重新赋值。
- final修饰的方法不可以被重写。
- final修饰的类不可以派生子类。
- final修饰的实例变量必须显式的指定初始值,并且只能在以下三个位置初始化。
public class FinalInstanceTest{ //定义变量时初始化 final int var1 = 2; final String var2; final double var3; //非静态初始化代码块 { var2 = "吃饭睡觉打豆豆"; } //构造器中初始化 public FinalInstanceTest(){ this.var3 = 3.14; }}
但是本质上final实例变量的初始化都是在构造器中进行的。
5. final修饰的类变量也必须在定义时或静态初始化块中显式初始化,而本质上都是在静态初始化块中进行的。 我们着重看以下final修饰的字符串,小伙伴们判断一下下面程序的输出结果public static void main(String[] args) { String str1 = "javacode"; String str2 = "java" + "code"; System.out.println(str1 == str2); ------------------A String str3 = "java"; String str4 = "code"; String str5 = str3 + str4; System.out.println(str1 == str5); ------------------B}
先公布结果:A 处代码会输出true 而B处代码会输出false。 先来研究下A处代码。有人会说明明是两个String对象怎么会输出true呢?java存在一个java字符串缓冲池,他会缓存所有使用过的字符串直接量。str1 = "javacode" 这里便会缓存javacode这个字符串对象,而str2 = "java" + "code";可以在编译时确定str2为"javacode"所以系统自动将str2指向字符串缓存的"javacode"。所以str1和 str2指向同一个字符串对象。而B处的代码,str5不能再编译时确定,系统就不会将str5指向缓存池中的"javacode",结果也就会输出false。 那么什么是编译时确定呢?我理解为变量的赋值中不访问普通变量,不调用方法,只是基本的算术运算表达式或字符串连接运算,这样的变量能够被系统编译时确定。显然上述代码中str1、str2符合,而str5不符合。 如何将B处也输出true 呢?我们用到了final关键字。 修改代码如下
public static void main(String[] args) { String str1 = "javacode"; String str2 = "java" + "code"; System.out.println(str1 == str2); ------------------A final String str3 = "java"; final String str4 = "code"; String str5 = str3 + str4; System.out.println(str1 == str5); ------------------B}
这时B处将输出true。 事实上final修饰的变量已经成为一个直接替换量(这是我自己起的名字),当后续代码再次用到这个变量时,系统会自动将其替换成相应的值,因此 String str5 = str3 + str4;相当于 String str5 = "java"+"code";str5也就可以编译时确定了。此外相对于实例变量而言,在定义时赋初始值,非静态初始化块中,构造器中赋初始值都是一样的,都将在构造器中执行,但是对于final变量只有在定义时赋初始值才会被直接替换。 另外关于final修饰的方法,主要强调在继承中存在的问题。被final修饰的方法子类不能重写,而且实际上子类也无法访问到父类中final修饰的方法。