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等等,那 ...
随机推荐
- excel写入操作
字典列表类型数据写入excel. #导入xlwt库 import xlwt import os # 步骤1:获取excel文件的绝对路径 dirPath = os.path.join(os.getcw ...
- Java后期拓展(一)之Redis
1.NoSQL数据库简介 2.Redis的介绍及安装启动 3.Redis的五大数据类型 4.Redis的相关配置 5.Redis的Java客户端Jedis 6.Redis的事务 7.Redis的持久化 ...
- http://www.layui.com/doc/modules/laydate.html实时通信\日期、==插件
8520**ali chengyouli http://www.layui.com/doc/modules/laydate.html实时通信\日期.==插件
- [SQL]LeetCode262.行程和用户 | Trips and Users
SQL架构 Create table If Not Exists Trips (Id )) Create table If Not Exists Users (Users_Id ), Role ENU ...
- [Swift]LeetCode673. 最长递增子序列的个数 | Number of Longest Increasing Subsequence
Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1: I ...
- [Swift]LeetCode722. 删除注释 | Remove Comments
Given a C++ program, remove comments from it. The program source is an array where source[i] is the ...
- [Swift]LeetCode973. 最接近原点的 K 个点 | K Closest Points to Origin
We have a list of points on the plane. Find the K closest points to the origin (0, 0). (Here, the d ...
- MiniProfiler监控Asp.Net MVC5和EF性能
1. 安装依赖包 在web项目打开nuget包管理器搜索 MiniProfiler.Mvc5和MiniProfiler.EF6安装. 2. 在Global.asax中添加配置代码 protected ...
- linux终端文本编辑神器vi的使用
vi —— 终端中的编辑器 目标 vi 简介 打开和新建文件 三种工作模式 常用命令 分屏命令 常用命令速查图 01. vi 简介 1.1 学习 vi 的目的 在工作中,要对 服务器 上的文件进行 简 ...
- 【T-SQL】系列文章全文目录(2017-06-26更新)
本系列[T-SQL]主要是针对T-SQL的总结. SQL基础 [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]0 ...