final关键字可用于修饰类、变量和方法。
修饰变量时,一旦获得初始值就不可改变。
final成员变量
final修饰的成员变量必须由程序员显示指定初始值。
指定初始值的位置:
- 类变量:需要在静态初始化块中或在声明该变量时这两种情况中的一种情况指定初始值。
- 实例变量:需要在非静态初始化块、声明该变量或构造器中的一种地方中指定初始值。
final局部变量
局部变量必须由程序员显示指定初始值。
final修饰的形参不能被赋值。
public void test(final int a)
{
//不能对final修饰形参赋值,下面语气将报错。
//a=5;
}
final修饰基本类型变量和引用类型变量区别
修饰引用类型变量时,final只保证引用类型变量所引用的地址不会改变,但这个对象可以改变。
final int[] iArr = {5, 6, 12, 9};
System.out.println(Arrays.toString(iArr));
// 对数组元素进行排序,合法
Arrays.sort(iArr);
System.out.println(Arrays.toString(iArr));
// 对数组元素赋值,合法
iArr[2] = -8;
System.out.println(Arrays.toString(iArr));
// 下面语句对iArr重新赋值,非法
// iArr = null;
“宏替换”的final变量
满足以下三个条件,就相当于一个直接量
- 使用final修饰符修饰
- 在定义该final变量时指定了初始值
- 该初始值可以在编译时就被确定下来
编译器会把程序中所有用到该变量的地方直接替换成该变量的值。
final int a = 5;
//实际转换为执行System.out.println(5)
System.out.println(a);
如果被赋的表达式只是基本的算术表达式或字符串连接运算,没有访问普通变量,调用方法,同样相当于“宏替换”
public static void main(String[] args)
{
// 下面定义了2个final“宏变量”
final String str = "csdn" + "博客";
final String book = "CSDN博客:" + 99.0;
// 下面的book2变量的值因为调用了方法,所以无法在编译时被确定下来
final String book2 = "CSDN博客:" + String.valueOf(99.0); //①
System.out.println(book == "CSDB博客:99.0");//true
System.out.println(book2 == "CSDN博客:99.0");//false
}
java会使用常量池保存曾经用过字符串直接量。
public static void main(String[] args)
{
String s1 = "csdn博客";
// s2变量引用的字符串可以编译时就确定出来,
// 因此s2直接引用常量池中已有的"csdn博客"字符串
String s2 = "csdn" + "博客";
System.out.println(s1 == s2);//true
String str1 = "csdn";
String str2 = "博客";
// 将str1和str2进行连接运算
String s3 = str1 + str2;
System.out.println(s1 == s3);//false
}
final方法
final修饰方法无法被重写,但是可以被重载。
如果父类中一个方法被private final修饰,在其子类中可以出现一个与父类private方法有相同名,相同形参列表,相同返回值类型的方法,但这是新方法
public class finalMethod extends finalTest
{
//新方法,不是方法重写。
public void test()
{}
}
public class finalTest
{
private final void test()
{}
}
final类
final修饰的类不能有子类。