购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

陷阱16

损失惨重
——不小心隐藏父类的final字段

一个Java应用程序是由许多类组成的,而某些类又有一定的继承关系,为了使数据具有一定的通用性,对于一些使用频率较高的数据,需要在父类中将其定义为常量,即定义一些静态的final字段,这时如果子类中定义的某个常量与父类中的重名,则子类就会将父类中的重名常量隐藏,导致父类中的重名常量的值不能被正确使用。

说 明

如果父类中的常量存储的是一些重要的数据,如金额、价格或面积等信息,而子类将父类中的重名常量隐藏了,就可能会造成巨大的经济损失,为此,在子类中定义常量时一定要特别小心,不要定义与父类中具有相同名称的常量。

示例:

假设房屋每平方米的单价固定是 4800元,可以将房屋单价定义为常量,如果将该常量定义在父类中,这样在其子类中就可以直接使用该常量了。

定义父类House:

定义子类TotalMoney,该类是House类的子类:

运行本示例,程序将在控制台输出如图3.11 所示的信息,显示70平方米房屋的总金额是 140000元。

图3.11 输出70平方米房屋的总金额

说 明

本示例之所以输出如图3.11 所示的信息,是由于在子类TotalMoney中定义的常量隐藏了父类House中定义的常量,即在标记 处定义的UNIT_PRICE隐藏了标记 处定义的UNIT_PRICE,所以当程序在标记 处调用getTotalMoney(int squareMeter)方法并为其传递实参70后,将执行该方法的方法体代码,而此时标记 处的HouseTotalMoney.UNIT_PRICE恰好是子类TotalMoney中(即在标记 处)定义的UNIT_PRICE,其值是 2 000,而不是父类中定义的UNIT_PRICE的值 4 800,所以程序输出的房屋总价是 140 000,而不是所期待的正确结果 336 000。

从该实例的输出结果不难看出,由于子类中定义的常量UNIT_PRICE隐藏了父类中定义的常量UNIT_PRICE,从而造成了 196000元的损失。

编程准则:在类中应避免使用公共常量

在程序中应尽量不要定义具有相同名称的常量,而应该将这些常量定义为私有的,然后通过定义获得常量值的final修饰的Getter方法来获得常量的值,这时,如果子类重写父类中final修饰的Getter方法,程序就会发生编译错误,就需要修改代码,所以可以极大地减少或消除由于常量使用不当而给企业造成的损失。

对上面的示例进行更改,将父类和子类中的常量都定义为私有的,并用final修饰的Getter方法来获得常量的值,更改后的代码如下。

定义父类House:

说 明

这里对上个示例中的父类House进行了更改,将常量定义为私有的,即在标记 处使用private对常量进行修饰,并在标记 处添加了一个final修饰的方法,该方法用于获得常量UNIT_PRICE的值。

定义子类TotalMoney(该子类中存在错误):

说 明

由于在父类House中用final对获得常量值的方法进行了修饰,所以在子类TotalMoney中重写父类中final修饰的方法时会发生编译错误,因此必须要对该方法进行更改,即将标记 处标识的方法改名,如将标记 处的方法名getUnitPrice改为getPrice,这样就可以避免由于子类隐藏父类的方法而造成损失,最后还要将标记 处的黑体字的代码“UNIT_PRICE”改为从父类继承的方法getUnitPrice(),这样,程序就不会出错了。

对子类TotalMoney进行修改,修改后的代码用黑体字标识,将子类TotalMoney修改正确后的代码如下:

这样修改后,程序就可以正常执行了,并能输出70平方米房屋的真正总金额 336 000元,如图3.12 所示。

图3.12 输出70平方米房屋的正确总金额 C4HcXSqGgTT/JwWB0AjBNWa5xWEyMKqVdcpINMKJsLpWpQoTd19xLo+CufW/YWD1

点击中间区域
呼出菜单
上一章
目录
下一章
×