停止变量的重新分配
尽管这些答案在理论上很有趣,但我还没有阅读简短的简单答案:
如果希望编译器阻止将变量重新分配给其他对象,请使用关键字final。
无论变量是静态变量,成员变量,局部变量还是参数/参数变量,其效果都是完全相同的。
例
让我们看看实际效果。
考虑这个简单的方法,其中两个变量(arg和x)都可以重新分配给不同的对象。
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
将局部变量标记为final。这会导致编译器错误。
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
相反,让我们将参数变量标记为final。这也会导致编译器错误。
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
故事的道德启示:
如果要确保变量始终指向同一对象,请将该变量标记为final。
从不重新分配参数
作为一种良好的编程习惯(使用任何一种语言),都不要为调用方法传递的对象以外的对象重新分配参数/参数变量。在上面的示例中,永远不要写这行arg =
。由于人类会犯错误,而程序员是人类,所以让编译器为我们提供帮助。将每个参数/参数变量标记为“最终”,以便编译器可以找到并标记任何此类重新分配。
回想起来
正如其他答案所指出的那样……考虑到Java最初的设计目标是帮助程序员避免愚蠢的错误,例如读取数组末尾,Java应该被设计为自动将所有参数/参数变量强制为“最终”。换句话说,参数不应该是变量。但是事后的看法是20/20的愿景,而Java设计师当时全神贯注。
因此,总是添加final
所有参数吗?
我们应该添加final
到每个要声明的方法参数中吗?
- 从理论上讲,是的。
- 实际上,没有。only仅在方法的代码很长或很复杂时才
添加final
,其中参数可能会误认为是局部变量或成员变量,并且可能会重新分配。
如果您接受永不重新分配参数的做法,则倾向于final
在每个参数上添加一个。但这很乏味,并且使声明更难阅读。
对于简短的简单代码,其中的参数显然是一个参数,而不是局部变量或成员变量,我不必理会添加final
。如果代码很明显,我和任何其他程序员都没有机会进行维护或重构,就无意将参数变量误认为参数之外的其他东西,那就不要打扰。在我自己的工作中,我final
只添加了更长或更长时间的代码,其中参数可能会误认为是局部变量或成员变量。
为完整性起见增加了另一种情况
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}