使用 final 关键字阻止继承

有时候,可能希望阻止人们利用某个类定义子类。不允许扩展的类被称为 final 类。如果在定义类的时候使用了 final 修饰符就表明这个类是 final 类。 例如, 假设希望阻止人们定义Executive类的子类,就可以在定义这个类的时候,使用 final 修饰符声明。声明格式如下所示:

public final class Executive extends Manager{...
}

类中的特定方法也可以被声明为 final。 如果这样做,子类就不能覆盖这个方法( final 类中的所有方法自动地成为 final 方法。) 例如:

public class Employee{...public final String getName(){return name;}...
}

注释:前面曾经说过,域也可以被声明为 final。对于 final 域来说,构造对象之后就不允许改变它们的值了。 不过, 如果将一个类声明为 final, 只有其中的方法自动地成为 final,而不包括域。

将方法或类声明为 final 主要目的是: 确保它们不会在子类中改变语义。例如, Calendar类中的 getTime 和 setTime 方法都声明为 final。这表明 Calendar 类的设计者负责实现 Date 类与日历状态之间的转换, 而不允许子类处理这些问题。同样地, String 类也是 final 类,这意味着不允许任何人定义 String 的子类。换言之, 如果有一个 String 的引用, 它引用的一定是一个 String 对象, 而不可能是其他类的对象。

有些程序员认为: 除非有足够的理由使用多态性, 应该将所有的方法都声明为 final。事实上,在 C++ 和 C# 中, 如果没有特别地说明, 所有的方法都不具有多态性。这两种做法可能都有些偏激。我们提倡在设计类层次时, 仔细地思考应该将哪些方法和类声明为 final。

在早期的 Java 中,有些程序员为了避免动态绑定带来的系统开销而使用 final 关键字。如果一个方法没有被覆盖并且很短, 编译器就能够对它进行优化处理, 这个过程为称为内联( inlining )。例如,内联调用 e.getName( ) 将被替换为访问 e.name 域。这是一项很有意义的改进, 这是由于 CPU 在处理调用方法的指令时, 使用的分支转移会扰乱预取指令的策略, 所以,这被视为不受欢迎的。然而, 如果 getName 在另外一个类中被覆盖, 那么编译器就无法知道覆盖的代码将会做什么操作, 因此也就不能对它进行内联处理了。

幸运的是, 虚拟机中的即时编译器比传统编译器的处理能力强得多。这种编译器可以准确地知道类之间的继承关系, 并能够检测出类中是否真正地存在覆盖给定的方法。 如果方法很简短、 被频繁调用且没有真正地被覆盖, 那么即时编译器就会将这个方法进行内联处理。如果虚拟机加载了另外一个子类,而在这个子类中包含了对内联方法的覆盖, 那么将会发生什么情况呢? 优化器将取消对覆盖方法的内联。这个过程很慢, 但却很少发生。

《Java 核心技术卷1 第10版》学习笔记------ 组织继承:final类和方法【编译器优化:内联( inlining );】相关推荐

  1. Java 核心技术卷 II(第 8 版) – 读书笔记 – 第 1 章(下)

    22.一旦获得了一个 Charset,就可以在 Java 的 Unicode 和指定的编码格式之间进行转化,下面以 GBK 和 Unicode 之间做为例子. 从 Unicode 到 GBK: imp ...

  2. 《Java 核心技术卷1 第10版》学习笔记------异常

    异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种情况的错误处理器 . 7.1.1 异常分类 在 Java 程序设计语言中, 异常对象都是派生于 Throwable 类的一个实例 . 稍后还 ...

  3. 《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【进阶】

    这部分主要是结合 Java 虚拟机实现泛型的原理进一步研究如何更好的使用泛型. 8.5 泛型代码和虚拟机 虚拟机没有泛型类型对象---所有对象都属于普通类.所以编译器在编译的时候会进行类型擦除操作. ...

  4. 《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【基础】

    泛型从Java SE 5.0 中开始出现,是 Java 程序设计语言从 1.0 版本发布以来,变化最大的部分. 使用泛型机制编写的程序代码要比那些杂乱地使用 Object 变量,然后再进行强制类型转换 ...

  5. 《Java 核心技术卷1 第10版》学习笔记------调试技巧

    调试器是 Eclipse . NetBeans 这类专业集成开发环境的一部分 . 在启动调试器之前, 本节先给出一些有价值的建议 . 1 ) 可以用下面的方法打印或记录任意变量的值 : System. ...

  6. 《Java 核心技术卷1 第10版》学习笔记------日志

    日志 API 的优点: 可以很容易地取消全部日志记录, 或者仅仅取消某个级别的日志, 而且打开和关闭这个操作也很容易 . 可以很简单地禁止日志记录的输出, 因此, 将这些日志代码留在程序中的开销很小 ...

  7. 《Java 核心技术卷1 第10版》学习笔记------对象克隆【对象拷贝】

    由于克隆并不太常见,而且有关的细节技术性很强,你可能只是想稍做了解,等真正需要时再深人学习. 先来回忆为一个包含对象引用的变量建立副本时会发生什么 .原变量和副本都是同一个对象的引用: Employe ...

  8. 《Java 核心技术卷1 第10版》学习笔记------ 接口(Interface)

    接口技术作用:主要描述类具有什么功能,而并不给出每个功能的是的实现. Java的继承(inheritance)是不支持的多继承的,但是Java接口是支持多继承的. 一个 Java 类实现一个接口类就必 ...

  9. 《Java 核心技术卷1 第10版》学习笔记------ 对象包装器、自动装箱、拆箱

    有时, 需要将 int 这样的基本类型转换为对象. 所有的基本类型都冇一个与之对应的类.例如,Integer 类对应基本类型 int.通常, 这些类称为包装器 ( wrapper ) 这些对象包装器类 ...

最新文章

  1. scrolling=no 无法根据坐标获取元素_汽车制造行业如何选择三坐标测量仪?
  2. Firefox 50优化Electrolysis
  3. Dask.distributed创建client时出现报错
  4. nodejs sqlite3_NodeJS 使用 better-sqlite3 操作sqlite 数据库
  5. 机器视觉-halcon学习笔记1
  6. 项目版本管理的最佳实践:云效飞流Flow篇
  7. 编写C语言代码,实现以下功能:有N名学生,每个人的信息包括学号、姓名和语文、数学、英语、平均分等内容(用结构体表示 ),输出平均分排名倒数第2的学生信息。
  8. linux程序默认启动项,windows和linux双系统,设置默认启动项
  9. 编辑WCF配置不出现
  10. java 读取Zip文件进行写入
  11. base64图裁剪 php_3分钟短文 | 有挑战!PHP用1个函数实现post请求,你用哪个?
  12. Unicode与UTF8:字符集与字符编码的关系
  13. Office 365系列(6)------Stage Migrate 搬迁方式至O365上来方法及步骤总结
  14. 树莓派制作内网dns服务器,树莓派使用dnsmasq搭建DNS服务器
  15. Mysql占用CPU过高排查过程及可能优化方案
  16. 苹果自研M1芯片跑分曝光-新MacBook Air超2019款顶配MacBook Pro
  17. 由DRM引起的ORA-00481错误
  18. Nebula Exchange 从Hive导入 NoSuchMethodError
  19. 艾司博讯:拼多多机器人客服在哪里
  20. python %d, %f, %s占位符的使用(学习笔记)

热门文章

  1. 工程制图 (零件图)
  2. 知识图谱还有哪些方向值得深入研究?这 6 篇最新论文给你答案
  3. 搜出来的文本:从MCMC到模拟退火
  4. ​CVPR 2020雾天条件下物体检测挑战赛冠军DeepBlueAI团队技术分享
  5. 追一科技热招职位来袭:AI新世界,不做旁观者
  6. AI 玩微信跳一跳的正确姿势:跳一跳 Auto-Jump 算法详解
  7. wandb: 深度学习轻量级可视化工具入门教程
  8. HDU1247 字典树 Hat’s Words(Tire Tree)
  9. ios 内存深度优化_iOS 25个性能优化/内存优化常用方法
  10. LeetCode两数相加