准备知识点:
- final可以修饰字段、方法、类。
- 当修饰字段的时候该字段值不能被改变
- 当修饰方法的时候该方法不能被覆盖
- 当修饰类的时候表示该类是终态类,该类不能够被继承换言之它没有子类。
笔试题目如下:
public class FinalTest {
public final int a;
public String name;
public FinalTest() {
a = 10;
}
public FinalTest(String name) {
name = "zhangsan";
}
}
问:该程序能否编译通过?
答:该程序无法编译通过。因为final修饰的成员变量有两种初始化方式一种是在声明final成员变量的时候直接赋值,第二种在构造方法中完成赋值,如果一个类有多个构造方法就要保证在每个构造方法中都要完成对该final类型成员变量的初始化工作。
如果是如下代码呢?
public class FinalTest {
public static final int a;
public String name;
public FinalTest() {
a = 10;
}
public FinalTest(String name) {
a = 11;
name = "zhangsan";
}
public static void main(String[] args) {
}
}
问:编译能否通过?
答:编译同不过。因为static final修饰的常量(需要在类初始化阶段完成赋值)一种是在声明的时候直接显式的初始化,另一种是在static块中完成初始化。不能在构造器中完成初始化(类的实例化阶段)。
那如果代码如下能编译通过吗?
public class FinalTest {
public static final int a = 12;
public String name;
public FinalTest() {
a = 10;
}
public FinalTest(String name) {
a = 11;
name = "zhangsan";
}
public static void main(String[] args) {
}
}
答:不能。因为常量a已经完成了初始化工作,它已经不能够被改变,构造器中的做法明显是试图去改它的值,故编译通不过。
代码如下能编译通过吗?
public class FinalTest {
static final StringBuffer sb = new StringBuffer();
public static void main(String[] args) {
sb.append("abc"); //能编译通过
//sb = new StringBuffer(); //不能够编译通过
}
}
答案:能编译通过,这题是考察当final修饰引用类型变量时,那么是该变量的引用不能改变还是引用的对象的内容不能改变,答案是引用不能改变,引用对象的内容可以改变。
总结:
- 对于final 修饰的成员变量既可以在声明的时候初始化也可以在所有的构造器中对其完成初始化(注:所有的构造器方法里都必须有对其初始化的语句)
- 对于static final修饰的常量只能在声明的时候完成初始化或者在static块中对其完成初始化。
- 对于final修饰的引用类型变量指的是引用不能够改变而不是引用的对象的内容不能够改变。