参考笔记:java的final关键字-CSDN博客
目录
1.final关键字使用范围
在Java中声明类、变量和方法时,可使用关键字 final 来修饰,表示“最后的,最终的”
2.final修饰类
用 final 关键字修饰类,表示这个类不能被继承,没有子类。不希望别的类去修改或者重写它的方法,例如 String、StringBuffer
案例
3.final修饰方法
用 final 关键字修饰方法,表示这个方法不能被子类重写,但可以被子类继承
语法格式
[修饰符] final 返回值类型 方法名(参数列表){
//程序代码
}
4.final修饰变量
用 final 关键字修饰的变量(成员变量或局部变量)称为常量,一旦赋值,它的值就不能被修改。常量名建议使用大写字母,例如:final double MY_PI = 3.14
语法格式
[修饰符] final type var = value;
//type是Java数据类型,var是变量名,value是变量的值
特点
① 成员变量用 final 修饰后,该变量不会有 set 方法,只有 get 方法
② 用 final 修饰的实例变量必须作初始化操作(可以显式赋值、普通代码块赋值、构造器中赋值),否则编译不通过
③ 用 final 修饰的静态变量作初始化操作时,必须在声明时或静态代码块中显式初始化,不能使用构造器作初始化
原因:为什么不能用构造器赋值呢?在前面已经学过,使用 static 的变量在类加载的时候就会创建并且作初始化。但是若用 final 修饰 static 变量,那么此时该变量又必须作赋值操作。而构造器只有在 new 对象的时候才会调用,类加载又一定先于构造器执行,所以类加载时,构造器是来不及为 final static 变量作赋值操作的。所以这里报错的主要原因是:在构造器里为 final static 变量赋值时机可能会比较晚
5.final使用注意事项
① 使用 final 修饰类,只是表示该类不能被继承,类内部的属性和方法不会自动具有 final 修饰符
② final 类不能继承,但能正常实例化对象
③ 如果不是 final 类,但是有 final 方法,该方法不能被重写,但是可以被继承
public class demo {
public static void main(String[] args) {
Student student = new Student();
student.run();
}
}
class Person{
public final void run(){
System.out.println("running");
}
}
class Student extends Person{}
/*输出结果
running
*/
④ final 不能修饰构造器
⑤ final 和 static 往往搭配使用,效率更高,因为底层编译器做了优化
(1)调用 final 和 static 修饰的变量,不会导致类加载
(2)调用单用 static 修饰的变量,会导致类加载
public class Test {
public static void main(String[] args) {
System.out.println(Person.num);//不会导致类加载,所以不执行静态代码块
System.out.println(Cat.n);//导致类加载,执行静态代码块
}
}
class Person{
public final static int num = 20;
static{
System.out.println("Person static block");
}
}
class Cat{
public static int n = 300;
static{
System.out.println("Cat static block");
}
}
/*输出结果
20
300
Cat static block
*/
⑥ 包装类 Integer、Double、Float、Boolean 等都是 final 类
6.练习题
6.1 题1
排错
public class Something {
public int addOne(final int x) {
return ++x;//x是用final修饰的,不能修改,++x相当于x=x+1,所以报错,应该改为return x+1;
}
}
x 是用 final 修饰的,不能修改,++x 相当于 x = x + 1,所以报错,应该改为 return x + 1
6.2 题2
排错
class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
o = new Other();//X,这行去掉就行了。o为final修饰的形参,为一个引用数据类型,所以需要保证其引用地址不变,其内部的i属性++不会有任何问题
o.i++;
}
}
class Other {
public int i;
}
o 为 final 修饰的形参,为一个引用数据类型,所以需要保证其引用地址不变,其内部的 i 属性 ++ 不会有任何问题