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