Java开发笔记(五十三)关键字final的用法
前面介绍了多态的相关用法,可以看到一个子类从父类继承之后,便能假借父类的名义到处晃悠。这种机制在正常情况之下没啥问题,但有时为了预防意外发生,往往只接受当事人来处理,不希望它的儿子乃至孙子来瞎掺和。可是犹记得几种开放性修饰符,只能控制某个实体能否被外部访问,从未听说可决定某个类能否被其它类所继承。
毫无疑问,是否开放与能否继承是两种不同的概念,不管是被public修饰的公共类,还是被private修饰的私有类,它们默认都是允许继承的。要想让某个类不能被其它类继承,还得在类名前面额外添加一个关键字final,表示这个类已经是最终的类,请不要再去派生子类了。相对多态概念而言,final也可以理解为终态,即最终的状态,终态当然是不可改变的,否则就不叫终态了。
仍旧以鸡类为例,长大以后的鸡很容易区分是公鸡还是母鸡,不管是从鸡冠还是羽毛还是叫声,都能迅速分辨公鸡母鸡。但是对于小鸡来说,区分它的性别可不容易,要知道有一种职业叫做“小鸡性别鉴定师”,年薪高达4万英镑(折合人民币40万左右)。所以,与其花费九牛二虎之力去分辨小鸡的性别,不如直接忽略它们的区别,反正看起来都是一群毛茸茸的小家伙么。既然小鸡不再区别性别,那么小鸡类就无需派生什么公小鸡、母小鸡之类,如此一来,新定义的小鸡类必须是最终状态的类,不可被其它类继承。在一个类定义的最前面添加final修饰符,该类就变成了终态类,于是保持终态的小鸡类Chick的定义代码示例如下:
//定义一个小鸡类。因为小鸡的性别难以辨别,所以不再定义性别字段,小鸡类也不允许被继承
final public class Chick { // 定义一个名称属性
public String name; // 定义一个叫唤方法
public void call() {
System.out.println("叽叽喳喳");
}
}
上面的Chick类,与普通类的区别仅仅是多了个final,正因为有了final,它才成为无儿无女的终类。
关键字final除了用于修饰类,还能用来修饰类的成员属性和成员方法。当一个成员属性戴上了final的帽子,它就必须在变量声明的同时一块赋值,并且这个初始值也是该属性的终值。凡是被final修饰的成员属性,只能进行初始化赋值,事后不能再次给它赋值了。要是一个成员方法也戴上final的帽子,意味着该方法是最终方法,不可在子类中重写,即使它是public类型也无济于事。
总的来说,final存在的意义是为了维护某个实体的纯洁性,不允许外部肆意篡改该实体。下列是final可作用的实体及其产生的影响:
1、一旦某个类被final修饰,则该类无法再派生出任何子类。
2、一旦某个成员属性被final修饰,则该属性不能再次赋值了。
3、一旦某个成员方法被final修饰,则该方法禁止被子类重载。
接下来尝试给鸡类增加几个终态的final成员,原先在公鸡类中使用数字0表示雄性,在母鸡类中使用数字1表示雌性,显然数字取值很容易搞混淆。现在利用两个终态的整型变量MALE和FEMALE分别保存0和1,由于终态属性无法被再次修改,因此这两个变量形同常量。具体的性别常量定义代码如下所示:
// 以下利用final修饰成员属性和成员方法
public final int MALE = 0; // 雄性
public final int FEMALE = 1; // 雌性
假如Chicken原来有个canSwim方法,考虑到鸡类都不会游泳,那么该方法肯定返回false。故而canSwim方法完全可以披上final的护身符,不管公鸡类还是母鸡类,都不能重写该方法。于是包含终态属性和终态方法的鸡类定义代码变成了下面这样:
//定义一个鸡类
public class Chicken { // 定义一个名称属性
public String name;
// 定义一个性别属性
public int sex; // 定义一个叫唤方法
public void call() {
System.out.println("半夜鸡叫");
} // 以下利用final修饰成员属性和成员方法
public final int MALE = 0; // 雄性
public final int FEMALE = 1; // 雌性 // 定义一个能否游泳的方法
public final boolean canSwim() {
return false;
}
}
对于外部来说,访问终态属性和终态方法的方式没有改变,仍然是以“实例名称.成员名称”的形式。下面是外部调用新鸡类的代码例子:
// 创建一个鸡类的实例
Chicken chicken = new Chicken();
// Chicken类的MALE属性是个终属性,首次初始化后就不能再做修改
System.out.println("MALE="+chicken.MALE);
// Chicken类的FEMALE属性是个终属性,首次初始化后就不能再做修改
System.out.println("FEMALE="+chicken.FEMALE);
// Chicken类的canSwim方法是个终方法,子类不能重写该方法
System.out.println("Chicken canSwim="+chicken.canSwim());
更多Java技术文章参见《Java开发笔记(序)章节目录》
Java开发笔记(五十三)关键字final的用法的更多相关文章
- Java开发笔记(十三)利用关系运算符比较大小
前面在<Java开发笔记(九)赋值运算符及其演化>中提到,Java编程中的等号“=”表示赋值操作,并非数学上的等式涵义.Java通过等式符号“==”表示左右两边相等,对应数学的等号“=”: ...
- Java开发笔记(序)章节目录
现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...
- Java开发笔记(五十五)关键字static的用法
前面介绍嵌套类的时候讲到了关键字static,用static修饰类,该类就变成了嵌套类.从嵌套类的用法可知,其它地方访问嵌套类之时,无需动态创建外层类的实例,直接创建嵌套类的实例就行.其实static ...
- Java开发笔记(五十八)简单接口及其实现
前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...
- Java开发笔记(五十九)Java8之后的扩展接口
前面介绍了接口的基本用法,有心的朋友可能注意到这么一句话“在Java8以前,接口内部的所有方法都必须是抽象方法”,如此说来,在Java8之后,接口的内部方法也可能不是抽象方法了吗?之所以Java8对接 ...
- Java开发笔记(七十五)异常的处理:扔出与捕捉
前面介绍的几种异常(不包含错误),编码的时候没认真看还发现不了,直到程序运行到特定的代码跑不下去了,程序员才会恍然大悟:原来这里的代码逻辑有问题.像这些在运行的时候才暴露出来的异常,又被称作“运行时异 ...
- Java开发笔记(二十三)数组工具Arrays
数组作为一种组合形式的数据类型,必然要求提供一些处理数组的简便办法,包括数组比较.数组复制.数组排序等等.为此Java专门设计了Arrays工具,该工具包含了几个常用方法,方便程序员对数组进行加工操作 ...
- Java开发笔记(三十三)字符包装类型
正如整型int有对应的包装整型Integer那样,字符型char也有对应的包装字符型Character.初始化字符包装变量也有三种方式,分别是:直接用等号赋值.调用包装类型的valueOf方法.使用关 ...
- Java开发笔记(四十五)成员属性与成员方法
前面介绍了许多数据类型,除了基本类型如整型int.双精度型double.布尔型boolean之外,还有高级一些的如包装整型Integer.字符串类型String.本地日期类型LocalDate等等,那 ...
随机推荐
- PHP实现微信模板消息发送给指定用户
使用公众号的模板消息功能,必须是认证过的服务号,需要发送微信号的openid,同一微信号在不同公众号下的openid是不同的,在公众号下是唯一的,获取不到微信号 进入公众平台 功能->模板消息 ...
- eclipse上的maven,添加依赖后无法自动下载相应的jar包
报错信息: Failed to read artifact descriptor for org.quartz-scheduler:quartz-jobs:jar:2.2.3 org.eclipse ...
- Python基础之函数参数
一.实参 1.实参分类: 2.实参基础代码: def fun01(a, b, c): print(a) print(b) print(c) # 位置传参:实参与形参的位置依次对应 fun01(1, 2 ...
- react基础篇 整理(一)
备注不知道为啥不能到出图片,详细知识自己百度一下就可以了,很简单的.画这个是为了更好的梳理知识,公司有个App项目,项目可控,所以尝试一下用React-native去做一下试试.
- ueditorUE 去掉本地保存成功的提示框!
网上修改什么JS的太麻烦,这样比较暴力,仅供参考 这里直接修改的样式: ue.ready(function () { $(".edui-editor-mess ...
- Ansible配置免密登陆
0x01: 把远程服务器的公钥来获取到本地 #ssh-keyscan ip1 ip2 ip3 ip4 >> /root/.ssh/known_hosts 完成后,/root/.ssh/k ...
- 高级Java面试总结3
1,java堆,分新生代老年代,新生代有Eden,from surviver,to surviver三个空间,堆被所有线程共.eden内存不足时,发生一次minor GC,会把from survivo ...
- Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
一个音视频文件是由音频和视频组成的,我们可以通过MediaExtractor.MediaMuxer把音频或视频给单独抽取出来,抽取出来的音频和视频能单独播放: 一.MediaExtractor API ...
- [Swift]LeetCode848. 字母移位 | Shifting Letters
We have a string S of lowercase letters, and an integer array shifts. Call the shift of a letter, th ...
- jquery监听video标签视频播放暂停状态
由于jquery中没有video的paly,pause方法,所以在使用jquery来控制视频的播放的播放状态时会出现问题 之前的代码: let $video = $('#video'); $('.pl ...