Java 什么时候应该对方法参数和局部变量使用 final?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/154314/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should one use final for method parameters and local variables?
提问by eaolson
I've found a couple of references (for example) that suggest using final
as much as possible and I'm wondering how important that is. This is mainly in the the context of method parameters and local variables, not final methods or classes. For constants, it makes obvious sense.
我找到了一些建议尽可能多地使用的参考文献(例如),final
我想知道这有多重要。这主要是在方法参数和局部变量的上下文中,而不是在最终方法或类中。对于常量,这是显而易见的。
On one hand, the compiler can make some optimizations and it makes the programmer's intent clearer. On the other hand, it adds verbosity and the optimizations may be trivial.
一方面,编译器可以做一些优化,让程序员的意图更加清晰。另一方面,它增加了冗长并且优化可能是微不足道的。
Is it something I should make an effort to remember?
这是我应该努力记住的事情吗?
采纳答案by Alex Miller
Obsess over:
执着于:
- Final fields - Marking fields as final forces them to be set by end of construction, making that field reference immutable. This allows safe publication of fields and can avoid the need for synchronization on later reads. (Note that for an object reference, only the field reference is immutable - things that object reference refers to can still change and that affects the immutability.)
- Final static fields - Although I use enums now for many of the cases where I used to use static final fields.
- Final 字段 - 将字段标记为 final 强制它们在构造结束时设置,使该字段引用不可变。这允许安全地发布字段,并且可以避免在以后读取时需要同步。(请注意,对于对象引用,只有字段引用是不可变的 - 对象引用所指的事物仍然可以更改并影响不变性。)
- 最终静态字段 - 尽管我现在在许多过去使用静态最终字段的情况下使用枚举。
Consider but use judiciously:
考虑但明智地使用:
- Final classes - Framework/API design is the only case where I consider it.
- Final methods - Basically same as final classes. If you're using template method patterns like crazy and marking stuff final, you're probably relying too much on inheritance and not enough on delegation.
- 最终类 - 框架/API 设计是我考虑的唯一情况。
- Final 方法 - 与 final 类基本相同。如果您正在使用诸如 crazy 和将内容标记为 final 之类的模板方法模式,那么您可能过多地依赖于继承而对委托的依赖还不够。
Ignore unless feeling anal:
忽略除非感觉肛门:
Method parameters and local variables - I RARELY do this largely because I'm lazy and I find it clutters the code. I will fully admit that marking parameters and local variables that I'm not going to modify is "righter". I wish it was the default. But it isn't and I find the code more difficult to understand with finals all over. If I'm in someone else's code, I'm not going to pull them out but if I'm writing new code I won't put them in. One exception is the case where you have to mark something final so you can access it from within an anonymous inner class.
Edit: note that one use case where final local variables are actually very useful as mentioned by @adam-gentis when value gets assigned to the var in the
if
/else
branches.
方法参数和局部变量 - 我很少这样做,主要是因为我很懒,而且我发现它使代码混乱。我完全承认标记参数和局部变量我不打算修改是“正确的”。我希望它是默认的。但事实并非如此,而且我发现代码更难理解为 finals。如果我在别人的代码中,我不会把它们拉出来,但如果我在写新代码,我不会把它们放进去。 一个例外是你必须将某些东西标记为 final 以便你可以访问它来自匿名内部类。
编辑:请注意,@adam-gent提到的最终局部变量实际上非常有用的一个用例是,当值被分配给
if
/else
分支中的 var 时。
回答by Peter Hilton
Is it something I should make an effort to remember to do?
这是我应该努力记住的事情吗?
No, if you are using Eclipse, because you can configure a Save Action to automatically add these finalmodifiers for you. Then you get the benefits for less effort.
不,如果您使用 Eclipse,因为您可以配置一个保存操作来自动为您添加这些最终修饰符。然后,您以更少的努力获得好处。
回答by Mike Stone
Well, this all depends on your style... if you LIKE seeing the final when you won't be modifying the variable, then use it. If you DON'T LIKE seeing it... then leave it out.
好吧,这完全取决于您的风格……如果您喜欢在不修改变量的情况下看到最终结果,请使用它。如果你不喜欢看到它……那就别管它了。
I personally like as little verbosity as possible, so I tend to avoid using extra keywords that aren't really necessary.
我个人喜欢尽可能少的冗长,所以我倾向于避免使用不必要的额外关键字。
I prefer dynamic languages though, so it's probably no surprise I like to avoid verbosity.
不过我更喜欢动态语言,所以我喜欢避免冗长可能也就不足为奇了。
So, I would say just pick the direction you are leaning towards and just go with it (whatever the case, try to be consistent).
所以,我会说只要选择你倾向于的方向,然后顺其自然(无论如何,尽量保持一致)。
As a side note, I have worked on projects that both use and don't use such a pattern, and I have seen no difference in the amount of bugs or errors... I don't think it is a pattern that will hugely improve your bug count or anything, but again it is style, and if you like expressing the intent that you won't modify it, then go ahead and use it.
附带说明一下,我曾参与过使用和不使用这种模式的项目,并且我发现错误或错误的数量没有差异......我不认为这是一种会极大地改进你的错误数量或任何东西,但它又是一种风格,如果你喜欢表达你不会修改它的意图,那么继续使用它。
回答by Sean
Somewhat of a trade-off as you mention, but I prefer explicit use of something over implicit use. This will help remove some ambiguity for future maintainers of code - even if it is just you.
正如你提到的,有点权衡,但我更喜欢显式使用某些东西而不是隐式使用。这将有助于为未来的代码维护者消除一些歧义——即使只有你自己。
回答by anjanb
If you have inner (anonymous) classes, and the method needs to access variable of the containing method, you need to have that variable as final.
如果您有内部(匿名)类,并且该方法需要访问包含方法的变量,则需要将该变量作为最终变量。
Other than that, what you've said is right.
除此之外,你说的都是对的。
回答by Eric R. Rath
The development-time benefits of "final" are at least as significant as the run-time benefits. It tells future editors of the code something about your intentions.
“final”在开发时的好处至少与运行时的好处一样重要。它告诉未来的代码编辑者一些关于你的意图的信息。
Marking a class "final" indicates that you've not made an effort during design or implementation of the class to handle extension gracefully. If the readers can make changes to the class, and want to remove the "final" modifier, they can do so at their own risk. It's up to them to make sure the class will handle extension well.
将类标记为“final”表示您在类的设计或实现过程中没有努力优雅地处理扩展。如果读者可以对类进行更改,并希望删除“final”修饰符,他们可以自行承担风险。由他们来确保该类能够很好地处理扩展。
Marking a variable "final" (and assigning it in the constructor) is useful with dependency injection. It indicates the "collaborator" nature of the variable.
将变量标记为“final”(并在构造函数中分配它)对于依赖注入很有用。它表示变量的“合作者”性质。
Marking a method "final" is useful in abstract classes. It clearly delineates where the extension points are.
将方法标记为“final”在抽象类中很有用。它清楚地描述了扩展点的位置。
回答by Alvin
If you are writing a application that someone will have to read the code after, say, 1 year, then yes, use final on variable that should not be modified all the time. By doing this, your code will be more "self-documenting" and you also reduce the chance for other developers to do silly things like using a local constant as a local temporary variable.
如果您正在编写一个应用程序,有人必须在 1 年后阅读代码,那么是的,请在不应一直修改的变量上使用 final。通过这样做,您的代码将更加“自我记录”,并且您还可以减少其他开发人员做一些愚蠢的事情的机会,例如使用局部常量作为局部临时变量。
If you're writing some throwaway code, then, nah, don't bother to identify all the constant and make them final.
如果您正在编写一些一次性代码,那么,不用费心识别所有常量并将它们设为最终代码。
回答by Javamann
I will use final as much as I can. Doing so will flag if you unintentionally change the field. I also set Method parameters to final. Doing so I have caught several bug from code I have taken over when they try to 'set' a parameter forgetting Java passes by value.
我会尽可能多地使用final。如果您无意中更改了该字段,则这样做会进行标记。我还将 Method 参数设置为 final。这样做时,我从我接管的代码中发现了几个错误,当他们尝试“设置”一个忘记 Java 按值传递的参数时。
回答by ykaganovich
It's not clear from the question whether this is obvious, but making a method parameter final affects only the body of the method. It does NOTconvey any interesting information about the method's intentions to the invoker. The object being passed in can still be mutated within the method (finals are not consts), and the scope of the variable is within the method.
从问题中不清楚这是否很明显,但是使方法参数 final 仅影响方法的主体。它不传达方法的意图给调用任何有趣的信息。传入的对象仍然可以在方法内进行变异(finals 不是 consts),并且变量的作用域在方法内。
To answer your precise question, I wouldn't bother making an instance or local variable (including method parameters) final unless the code required it (e.g. the variable is referenced from an inner class), or to clarify some really complicated logic.
为了回答您的确切问题,除非代码需要(例如从内部类引用变量),否则我不会费心将实例或局部变量(包括方法参数)设为 final,或者澄清一些非常复杂的逻辑。
For instance variables, I would make them final if they are logically constants.
例如变量,如果它们是逻辑常量,我会将它们设为 final。
回答by Sam Stokes
I've found marking method parameters and locals as final
is useful as a refactoring aid when the method in question is an incomprehensible mess several pages long. Sprinkle final
liberally, see what "cannot assign to final variable" errors the compiler (or your IDE) throws up, and you just might discover why the variable called "data" ends up null even though several (out of date) comments swear that can't happen.
我发现将方法参数和局部变量标记final
为有助于重构的方法,当所讨论的方法是几页长的难以理解的混乱时。final
随意洒一些,看看编译器(或你的 IDE)抛出什么“无法分配给最终变量”错误,你可能会发现为什么名为“数据”的变量最终为空,即使有几个(过时的)评论发誓可以不会发生。
Then you can fix some of the errors by replacing the reused variables with new variables declared closer to the point of use. Then you find you can wrap whole parts of the method in scoping braces, and suddenly you're one IDE keypress away from "Extract Method" and your monster just got more comprehensible.
然后,您可以通过使用更接近使用点的新变量来替换重用的变量来修复一些错误。然后你会发现你可以将方法的整个部分包裹在范围大括号中,突然间你离“提取方法”只有一个 IDE 按键,你的怪物变得更容易理解了。
If your method is notalready an unmaintainable wreck, I guess there might be value in making stuff final to discourage people from turning it into said wreck; but if it's a short method (see: not unmaintainable) then you risk adding a lot of verbosity. In particular, Java function signatures are hard enough to fit into 80 characters as it is without adding six more per argument!
如果你的方法还不是一个无法维护的残骸,我想把东西做成最终以阻止人们把它变成所说的残骸可能是有价值的;但如果它是一个简短的方法(请参阅:并非不可维护),那么您可能会增加很多冗长的内容。特别是,Java 函数签名很难容纳 80 个字符,因为它不会为每个参数增加 6 个字符!