Java final

示例

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

  • final变量不能重新分配

    final方法不能被重写

    final类不能被扩展

用法

良好的编程习惯

一些开发人员认为,最好在可能的时候标记一个变量final。如果您有一个不应更改的变量,则应将其标记为最终变量。

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

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

这强调了summup方法不会改变int。

内部类访问

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

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

该类不会编译,因为变量name不是最终的。

Java SE 8

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

final static 变量

即使final变量foonot为static,即使下面的代码是完全合法的,在这种情况下static也无法编译:

class TestFinal {
    private final static List foo;

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

原因是,让我们再重复一次,不能重新分配最终变量。由于foo是静态的,因此它在class的所有实例之间共享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方法很有用。它们也比非final方法快,因为不涉及虚拟表的概念。

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