Java final 类和方法(学习 Java 编程语言 041)
不允许扩展的类被称为 final 类。如果在定义类的时候使用了 final 修饰符就表明这个类是 final 类。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence, Constable, ConstantDesc { ... }
类中的某个特定方法也可以被声明为 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 在处理当前指令时,分支会扰乱预取指令的策略,所以,CPU 不喜欢分支。然而,如果 getName 在另外一个类中被覆盖,那么编译器就无法知道覆盖的代码将会做什么操作,因此也就不能对它进行内联处理了。
幸运的是,虚拟机中的即时编译器比传统编译器的处理能力强得多。这种编译器可以准确地知道类之间的继承关系,并能够检测出是否有类确实覆盖了给定的方法。如果方法很简短、被频繁调用而且确实没有被覆盖,那么及时编译器就会将这个方法进行内联处理。如果虚拟机加载了另一个子类,而且这个子类覆盖了一个内联方法,那么将会发生什么情况呢?优化器将取消这个方法的内联。这个过程很慢,不过很少会发生这个情况。
- JAVA(零碎)学习笔记(一)---字符串/对象和对象变量/LocalDate类/final实例域、final方法、final类/静态域与静态方法/方法参数
- Java final 实例字段(学习 Java 编程语言 030)
- java学习:构造方法、static、final
- java学习之旅43--final_修饰变量_方法_类
- Java学习记录 Day7(继承、方法重写、final、多态)
- java学习笔记6:构造方法、对象的创建、继承、重写、static、final关键字
- 学习Java前对过去学习编程语言的方法、经验和教训以及对Java平台的理解
- Java学习笔记之继承和接口(一) super关键字、final关键字、abstract类和方法
- JAVA学习day08 JavaSE基础——代码块、继承、方法重写和final关键字
- Java学习备忘录(四)方法篇(原创)
- java学习笔记九——构造函数、方法重写、重载
- 细说Java学习的捷径与方法
- 基于 Android NDK 的学习之旅----- Java 方法映射到C中的签名(附源码)
- java学习笔记(static和final关键字)
- JAVA学习笔记一:public和main方法
- java:log4j学习(5)-转帖:Log4j基本使用方法
- Java”方法“学习小结
- JAVA高级01_09 Math与Random类 学习API的方法 2011-4-21
- Java学习从入门到精通 4方法篇
- 我的java学习之路之接口,static,final,关键字