最后

Java 中的 final 可以引用变量,方法和类。有三个简单的规则:

  • 最终变量无法重新分配
  • 最终方法无法覆盖
  • 最后一堂课不能延期

用法

良好的编程实践

一些开发人员认为在可能的情况下标记变量 final 是一种很好的做法。如果你有一个不应更改的变量,则应将其标记为 final。

final 关键字 if 的重要用途是方法参数。如果要强调方法不更改其输入参数,请将属性标记为 final。

public int sumup(final List<Integer> ints);

这强调了 sumup 方法不会改变 ints

内部类访问

如果你的匿名内部类想要访问变量,则该变量应标记为 final

  public IPrintName printName(){
    String name;
    return new IPrintName(){
        @Override
        public void printName(){
            System.out.println(name);
        }
    };
}

这个类不编译,因为变量 name 不是 final。

Version >= Java SE 8

有效的最终变量是一个例外。这些局部变量只写入一次,因此可以作为最终变量。有效的最终变量也可以从匿名类中访问。

final static 变量

即使 final 变量 foo 不是 static,下面的代码完全合法,但是如果是 static 则不会编译:

class TestFinal {
    private final static List foo;

    public Test() {
        foo = new ArrayList();
    }
}

原因是,让我们再说一遍,最后的变量不能重新分配。由于 foo 是静态的,因此它在 TestFinal 的所有实例之间共享。当创建类 TestFinal 的新实例时,将调用其构造函数,因此将重新分配 foo,而编译器不允许这样做。在这种情况下初始化变量 foo 的正确方法是:

class TestFinal {
    private static final List foo = new ArrayList();
    //..
}

或者使用静态初始化程序:

class TestFinal {
    private static final List foo;
    static {
        foo = new ArrayList();
    }
    //..
}

当基类实现派生类不应该更改它的一些重要功能时,final 方法很有用。它们也比非最终方法更快,因为没有涉及虚拟表的概念。

Java 中的所有包装类都是最终的,例如 IntegerLong 等。这些类的创建者不希望任何人都可以将 Integer 扩展到他自己的类中并改变 Integer 类的基本行为。使类不可变的要求之一是子类不能覆盖方法。最简单的方法是将类声明为 final