1.final成员变量
final修饰的成员变量必须由程序员显示地指定初始值
类变量
必须在静态初始化块或声明时指定初始值,只能二者选一
实例变量
必须在非静态初始化,声明时或构造器中指定初始值,只能三者选一
注意:不要在final成员变量未初始化时访问其值
class TestClass{
//定义final成员变量,为进行初始化,系统也不会对其进行默认初始化
final int a;
//非静态初始化块
{
//a为进行初始化,此处代码报错
//System.out.println("a = "+ a);
a = 1;
System.out.println("a = "+ a);
}
public static void main(String[] args){
new TestClass();
}
}
2.final局部变量
可以在其声明时进行赋值,一旦赋值之后便不能再次更改其值
可以不在其声明时进行赋值,在后续代码中可以对其进行赋值,一旦赋值之后便不能再次更改其值
3.final修饰引用类型变量
final修饰引用类型变量,只能保证引用的地址不变,即只引用一个对象,但不能保证对象的内容不发生改变
class TestClass{
private int a;
public TestClass(){
a = 10;
}
public void seta(int a){
this.a = a;
}
public int geta(){
return a;
}
public static void main(String[] args){
final TestClass tc = new TestClass();
//更换引用对象,此处代码报错
//tc1 = new TestClass();
//输出:a = 10
System.out.println("a = "+ tc.geta());
//更改对象的内容,不报错
tc.seta(20);
//输出:a = 20
System.out.println("a = "+ tc.geta());
}
}
4.可执行“宏替换”的final变量
当满足以下3个条件时,这个final变量不再是一个变量,而是相当于一个直接量,变量被当作“宏变量”处理
- 使用final修饰符修饰
- 在声明该final变量时指定初始值
- 在编译阶段已经确定了变量的值
class TestClass{
public static void main(String []args){
final int a = 10;
System.out.println(a);
}
}
上述a变量满足“宏变量”原则。a在编译阶段已经确定了值,执行 System.out.println(a); 代码时,实际转换为 System.out.println(10); 执行。
除了上述final变量被直接赋值的情况外,如果被赋的表达式只是基本的算数表达式或字符串连接运算,没有访问普通变量,调用方法,java编译器同样将会把这种final变量当成“宏变量”处理
final int a = 1 + 2;//a被当作“宏变量”
final String str1 = "java" + "8";//str1被当作“宏变量”
final String str2 = "java" + String.valueOf(8);//str2不是“宏变量”,因为str2初始化时调用了方法
5.final方法
final修饰的public方法子类不能被重写
对于父类中一个private方法,子类是不能继承的,所以也不存在重写,即子类中可以定义一个与其同名,同参,同返回值的方法,该方法是完全独立于父类的,只是定义了一个新方法,并不是重写
class BaseClass{
public final void show1(){
System.out.println("BaseClass:public final");
}
private final void show2(){
System.out.println("BaseClass:private final");
}
}
class SubClass extends BaseClass{
//final方法不能被子类重写,报错
// public final void show1(){
// System.out.println("SubClass:public final");
// }
//此方法虽然同名,同参,同返回值。但该方法是完全独立于父类的,只是定义了一个新方法,并不是重写
private final void show2(){
System.out.println("SubClass:public final");
}
}
6.final类
final类不能被继承。例如java.lang.Math类是一个final类,不能被继承
参考:李刚《疯狂java讲义》(第2版)