Java final 类和方法(学习 Java 编程语言 041)

不容许扩展的类被称为 final 类。若是在定义类的时候使用了 final 修饰符就代表这个类是 final 类。java

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,而不包括字段。ide

将方法或类声明为 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 在另一个类中被覆盖,那么编译器就没法知道覆盖的代码将会作什么操做,所以也就不能对它进行内联处理了。code

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

相关文章
相关标签/搜索