4.7 再谈final

img

扫码看视频

在Java中,final关键字代表“不能被改变的”,它可以用于修饰类、成员变量、方法和参数。当修饰成员变量时,就是我们在第3.10节介绍的常量。

4.7.1 final类

final类代表不能被继承的类。在面向对象程序设计中,有些类我们是作为标准类来使用的,这些类没有必要也不希望被当作基类使用,这时就可以使用final来声明这些类。我们看代码4.26

img

当我们试图继承FinalClass类时,Java编译器会报告错误:“无法从最终FinalClass进行继承”。

4.7.2 final方法

方法也可以声明为final,声明为final的方法不可以被子类所覆盖。我们看代码4.27。

img

上面的代码会出现编译错误,因为ExtednsFromFinalMethod类试图覆盖基类的final方法。

那什么时候需要将某个方法声明为final,以避免子类重写该方法呢?如果类中的某个方法用于实现固定的计算步骤,或实现某种标准操作,而不希望子类去改变,那么就可以将该方法声明为final。

例如,我们知道超市的商品经常打折,商品的最终价格由很多因素决定,比如是否是会员、当前商品是否参加了促销活动等,假定商品实际价格的计算逻辑是固定的,那么就可以在商品基类中编写一个final方法,该方法调用其他一些方法(如计算折扣的方法等)完成商品价格的计算逻辑。具体的某个商品类从基类派生,重写折扣方法,给出本商品的折扣,当计算具体某项商品(子类)价格的时候,调用继承的基类的final方法,由于多态性的缘故,在该final方法中,实际调用的是子类的折扣方法,从而计算出该项商品的实际价格。

某些时候,为了效率上的考虑,将方法声明为final,让编译器对此方法的调用进行优化。要注意的是:编译器会自行对final方法进行判断,并决定是否进行优化。通常,当方法的体积很小,且我们确实不希望它被覆盖时,才将它声明为final。

对于私有方法来说,它们是不能被其他任何类访问的,自然也就不能被覆盖,所以私有的方法也是final方法。当然,我们也可以显式地声明私有方法为final,不过,这样做无非是画蛇添足而已,并不能起到什么特殊效果。

类中的static方法也是不能被覆盖的,所以静态方法自然也是final方法。

4.7.3 final参数

还可以在方法的参数列表中声明参数为final,这意味着final参数无法在方法内部被修改。我们看代码4.28。

img

在上面的例子中,“a = 1;”和“g = new Game();”这两行代码试图修改final参数,是Java编译器所不允许的,但是修改g的prop字段则是可以的。