说明: 该系列笔记不包括语法层面的基础,比如if,for语句的语法等等,仅记录在阅读过程中觉得比较值得记录的东西。
概念
final关键字表示“不可变”,需要在编译时初始化。(初始化代码块,构造器中,静态初始化代码块不能初始化非静态字段)类似C++ 里的const,相较于C++,没有什么顶层const和底层const的区别。final可以作用于字段,方法,类上,具有不同的效果。
作用在字段上
public Car {
public Car(double speed) {
this.speed = speed;
}
private double speed;
public void setSpeed(double speed) {
this.speed = speed;
}
}
public Test{
private final int finalInt = 5;
private final double finalDouble = Math.random() * 100;
public final Car car = new Car(150); //方便起见,这里就直接设置成public
}
以上是连个简单例子,finlaInt 是int类型(基本类型),这里直接进行初始化了,实在编译期就能确定值的,首次初始化完毕后将不能被改变。例如,不能这样做:
finalInt = 6; //编译器报错
finalDouble 和 finalDouble差不多,不同的是,他并不能在编译期就确定值,要等到运行时才能确定值。
最后看一下car,car本质上是一个Car的引用,这时候final的效果仅仅是使得Car类型的引用不能被改变,即不能指向其他,但是其内部值(比如这里的speed)是可以被改变的。看下面的例子:
Test test = new Test();
Car newCar = new Car(100);
test.car = newCar; //编译器会报错,不能对final变量car赋值
test.car.setSpeed(200); //没有问题,并且如果输出的话,speed已经变成200.0
作用在方法上
作用在方法上就没有那么多“规矩了”,主要作用是使子类不能重写该方法了。带来的好处是静态编译期就绑定了,不需要动态绑定,这样效率就高了(可以“插入”代码执行,就不存在调用栈的消耗,类似于C++的内联函数,不过和C++一样,这是有编译器决定的,并不总是能“插入”代码块中)
作用在类上
作用在类上仅仅有一个作用,那就是禁止继承。可以看看java.lang.String,这个String就是final类,final类里的方法都默认是final,即使显式的指定final也毫无意义。
总结
final在业务逻辑中虽然用的不多,即使用了大多数时候也仅仅是作为常量来使用,但是理解他还是很有意义的,比如当需要写一些工具类的时候,可以优化效率。