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 to do?
这是我应该努力记住的事情吗?
16 个解决方案
#1
149
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.
- 最后的静态字段——尽管我现在对许多使用静态最后字段的情况使用enum。
Consider but use judiciously:
考虑但明智的使用:
- Final classes - Framework/API design is the only case where I consider it.
- 最后的类——我只考虑框架/API设计。
- 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.
- 最后的方法——基本上和最后的类一样。如果您正在使用模板方法模式,比如crazy和markstuff 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.
- 方法参数和局部变量——我很少这样做,主要是因为我很懒,而且我发现它会使代码混乱。我完全承认,标记参数和我不打算修改的局部变量是“正确的”。我希望是违约。但事实并非如此,而且我发现在期末考试中,代码更难理解。如果我在别人的代码中,我不会把它们拖出来,但是如果我在写新代码,我不会把它们放进去。一个例外是您必须标记一些最终的东西,以便您可以从一个匿名内部类中访问它。
#2
42
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 final modifiers for you. Then you get the benefits for less effort.
不,如果您正在使用Eclipse,因为您可以配置一个Save操作来自动为您添加这些最终的修饰符。这样你就能少花点力气就得到好处。
#3
12
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”是有用的。它清楚地描述了扩展点的位置。
#4
7
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对于重构很有用,因为问题中的方法有好几页长,难以理解。最后*地撒下,看看“不能分配到最终变量”的错误,编译器(或者你的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 not already 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个参数!
#5
6
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.
作为补充说明,我曾在使用和不使用这种模式的项目中工作过,我发现bug和错误的数量没有差别……我不认为这是一种模式,它将极大地改善您的bug数或其他任何东西,但它还是风格,如果您喜欢表达您不会修改它的意图,那么就继续使用它。
#6
5
I use final
all the time to make Java more expression based. See Java's conditions (if,else,switch
) are not expression based which I have always hated especially if your used to functional programming (ie ML, Scala or Lisp).
我一直使用final来使Java更基于表达式。请参见Java的条件(if,else,switch)不是基于表达式的,我一直讨厌这种情况,尤其是如果您习惯于函数式编程(ie ML, Scala或Lisp)的话。
Thus you should try to always (IMHO) use final variables when using conditions.
因此,在使用条件时,应该始终(IMHO)使用最终变量。
Let me give you an example:
我举个例子:
final String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
case JOB_POSTING_IMPORT:
name = "Blah";
break;
default:
throw new IllegalStateException();
}
Now If add another case
statement and do not set name
the compiler will fail. The compiler will also fail if you do not break on every case (that you set the variable). This allows you to make Java very similar to Lisp's let
expressions and makes it so your code is not massively indented (because of lexical scoping variables).
现在,如果添加另一个case语句而不设置名称,编译器将失败。如果不破坏每个情况(设置变量),编译器也会失败。这使您可以使Java非常类似于Lisp的let表达式,并使您的代码不会出现大的缩进(因为词汇范围变量)。
And as @Recurse noted (but apparently -1 me) you can do the preceding with out making String name
final
to get the compiler error (which I never said you couldn't) but you could easily make the compiler error go away setting name after the switch statement which throws away the expression semantics or worse forgetting to break
which you cannot cause an error (despite what @Recurse says) without using final
:
@Recurse指出(但显然1我)你可以做前面的字符串名称最终得到编译器错误(我从来没有说过你不能),但是你可以很容易地使编译器错误消失设置名称后扔掉的switch语句表达语义或者更糟忘记休息不能导致一个错误(尽管@Recurse所说的),而不使用最终:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
//break; whoops forgot break..
//this will cause a compile error for final ;P @Recurse
case JOB_POSTING_IMPORT:
name = "Blah";
break;
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
Because of the bug setting name (besides forgetting to break
which also another bug) I can now accidentally do this:
由于错误的设置名称(除了忘记破坏另一个错误),我现在可以不小心这样做:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
//should have handled all the cases for pluginType
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
The final variable forces a single evaluation of what name should be. Similar to how a function that has a return value must always return a value (ignoring exceptions) the name switch block will have to resolve name and thus bound to that switch block which makes refactoring chunks of code easier (ie Eclipe refactor: extract method).
最后的变量强制对名称进行单独的评估。与具有返回值的函数必须总是返回值(忽略异常)类似,name switch块必须解析名称,从而绑定到那个switch块,这使得重构代码块更容易(即Eclipe refactor: extract method)。
The above in OCaml:
上述在OCaml:
type plugin = CandidateExport | JobPostingImport
let p = CandidateExport
let name = match p with
| CandidateExport -> "Candidate Stuff"
| JobPostingImport -> "Blah" ;;
The match ... with ...
evaluates like a function ie expression. Notice how it looks like our switch statement.
这场比赛……与…像函数ie表达式那样计算。注意它看起来像我们的switch语句。
Here is an example in Scheme (Racket or Chicken):
下面是Scheme(球拍或鸡肉)中的一个例子:
(define name
(match b
['CandidateExport "Candidate Stuff"]
['JobPostingImport "Blah"]))
#7
4
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 on变量,这个变量不应该一直被修改。通过这样做,您的代码将更加“自我记录”,并且您也减少了其他开发人员做傻事的机会,比如使用本地常量作为本地临时变量。
If you're writing some throwaway code, then, nah, don't bother to identify all the constant and make them final.
如果您正在编写一些一次性的代码,那么,不,不要费事去识别所有的常量并使它们成为最终的。
#8
4
It is useful in parameters to avoid change the parameter value by accident and introduce a subtle bug. I use to ignore this recommendation but after spending some 4 hrs. in a horrible method ( with hundreds of lines of code and multiple fors, nested ifs and all sort of bad practices ) I would recommend you to do it.
在参数中避免意外地更改参数值并引入一个细微的错误是很有用的。我过去常常忽略这个建议,但在花了大约4个小时之后。在一个可怕的方法中(有数百行代码、多个fors、嵌套的ifs和所有的糟糕实践),我建议您这样做。
public int processSomethingCritical( final int x, final int y ){
// hundreds of lines here
// for loop here...
int x2 = 0;
x++; // bug aarrgg...
// hundreds of lines there
// if( x == 0 ) { ...
}
Of course in a perfect world this wouldn't happen, but.. well.. sometimes you have to support others code. :(
当然,在一个完美的世界里,这是不可能发生的。嗯. .有时您必须支持其他代码。:(
#9
3
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。如果您无意中更改了字段,那么这样做将标记。我还将方法参数设置为final。这样做时,我从我接手的代码中发现了几个错误,它们试图“设置”一个参数,而忘记了Java通过值传递。
#10
2
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 NOT convey 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只影响方法的主体。它不会向调用者传递任何关于方法意图的有趣信息。传入的对象仍然可以在方法中发生突变(final不是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。
#11
2
There are many uses for the variable final
. Here are just a few
变量final有很多用途。这里有一些
Final Constants
最后一个常量
public static class CircleToolsBetter {
public final static double PI = 3.141;
public double getCircleArea(final double radius) {
return (Math.pow(radius, 2) * PI);
}
}
This can be used then for other parts of your codes, or accessed by other classes, that way if you would ever change the value you wouldn't have to change them one by one.
然后,它可以用于代码的其他部分,或者被其他类访问,这样,如果您想要更改值,您就不必逐个更改它们。
Final Variables
最后一个变量
public static String someMethod(final String environmentKey) {
final String key = "env." + environmentKey;
System.out.println("Key is: " + key);
return (System.getProperty(key));
}
}
In this class, you build a scoped final variable that adds a prefix to the parameter environmentKey. In this case, the final variable is final only within the execution scope, which is different at each execution of the method. Each time the method is entered, the final is reconstructed. As soon as it is constructed, it cannot be changed during the scope of the method execution. This allows you to fix a variable in a method for the duration of the method. see below:
在这个类中,您将构建一个作用域最终变量,该变量向参数环境键添加前缀。在这种情况下,最终变量仅在执行范围内是最终变量,在方法的每次执行中都是不同的。每次输入方法时,都会重构最终方法。一旦构造了它,就不能在方法执行的范围内更改它。这允许您在方法的持续时间内固定一个变量。见下文:
public class FinalVariables {
public final static void main(final String[] args) {
System.out.println("Note how the key variable is changed.");
someMethod("JAVA_HOME");
someMethod("ANT_HOME");
}
}
Final Constants
最后一个常量
public double equation2Better(final double inputValue) {
final double K = 1.414;
final double X = 45.0;
double result = (((Math.pow(inputValue, 3.0d) * K) + X) * M);
double powInputValue = 0;
if (result > 360) {
powInputValue = X * Math.sin(result);
} else {
inputValue = K * Math.sin(result); // <= Compiler error
}
These are especially useful when you have really long lines of codes, and it will generate compiler error so you don't run in to logic/business error when someone accidentally changes variables that shouldn't be changed.
当您有很长的代码行时,这些代码特别有用,并且它将生成编译器错误,因此当某人意外地更改不应该更改的变量时,您不会运行到逻辑/业务错误中。
Final Collections
最后的集合
Different case when we are talking about Collections, you need to set them as an unmodifiable.
在讨论集合时,您需要将它们设置为不可修改的。
public final static Set VALID_COLORS;
static {
Set temp = new HashSet( );
temp.add(Color.red);
temp.add(Color.orange);
temp.add(Color.yellow);
temp.add(Color.green);
temp.add(Color.blue);
temp.add(Color.decode("#4B0082")); // indigo
temp.add(Color.decode("#8A2BE2")); // violet
VALID_COLORS = Collections.unmodifiableSet(temp);
}
otherwise, if you don't set it as unmodifiable:
否则,如果您不设置为不可修改:
Set colors = Rainbow.VALID_COLORS;
colors.add(Color.black); // <= logic error but allowed by compiler
Final Classes and Final Methods cannot be extended or overwritten respectively.
不能分别扩展或覆盖最终类和最终方法。
EDIT:TO ADDRESS THE FINAL CLASS PROBLEM REGARDING ENCAPSULATION:
编辑:解决关于封装的最终类问题:
There are two ways to make a class final. The first is to use the keyword final in the class declaration:
有两种方法可以让课堂期末考试。第一个是在类声明中使用关键字final:
public final class SomeClass {
// . . . Class contents
}
The second way to make a class final is to declare all of its constructors as private:
第二种使类成为最终类的方法是将其所有构造函数声明为私有:
public class SomeClass {
public final static SOME_INSTANCE = new SomeClass(5);
private SomeClass(final int value) {
}
Marking it final saves you the trouble if finding out that it is actual a final, to demonstrate look at this Test class. looks public at first glance.
如果发现它是一个真正的期末考试,那么在这个测试类中演示一下,那么标记它为final就省去了麻烦。第一眼就能看到公众。
public class Test{
private Test(Class beanClass, Class stopClass, int flags)
throws Exception{
// . . . snip . . .
}
}
Unfortunately, since the only constructor of the class is private, it is impossible to extend this class. In the case of the Test class, there is no reason that the class should be final. The Test class is a good example of how implicit final classes can cause problems.
不幸的是,由于类的惟一构造函数是私有的,所以不可能扩展这个类。对于测试类,没有理由认为类应该是final的。测试类是一个很好的例子,说明隐式最终类是如何引起问题的。
So you should mark it final when you implicitly make a class final by making it's constructor private.
因此,当隐式地将类设置为final时,应该将它标记为private。
#12
1
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.
就像你提到的那样,这是一种权衡,但我更喜欢用显式的东西,而不是用隐式的东西。这将有助于为将来的代码维护人员消除一些歧义——即使只有您自己。
#13
1
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.
除此之外,你说的是对的。
#14
0
Use final
keyword for a variable if you are making that variable as immutable
如果要使变量成为不可变的,则对变量使用final关键字
By declaring the variable as final, it aids developers to rule out possible modification issues of variables in highly multi-threaded environment.
通过将变量声明为final,它可以帮助开发人员排除高多线程环境中可能存在的变量修改问题。
With java 8 release, we have one more concept called "effectively final variable
". A non-final variable can heave as final variable.
在java 8发行版中,我们还有一个概念叫做“有效的最终变量”。非最终变量可以升腾为最终变量。
local variables referenced from a lambda expression must be final or effectively final
从lambda表达式引用的局部变量必须是最终的或有效的最终的
A variable is considered effective final if it is not modified after initialization in the local block. This means you can now use the local variable without final keyword inside an anonymous class or lambda expression, provided they must be effectively final.
如果变量在本地块中初始化后未被修改,则视为有效的最终变量。这意味着您现在可以在匿名类或lambda表达式中使用不带final关键字的局部变量,前提是它们必须是有效的final。
Till Java 7, you cannot use a non-final local variable inside an anonymous class, but from Java 8 you can
在Java 7之前,您不能在匿名类中使用非最终本地变量,但是从Java 8可以使用
Have a look at this article
看看这篇文章好吗
#15
0
A very simple answer we have 3 cases with Final with variables ,Final with methods && Final with classes..
一个非常简单的答案,我们有三种情况,带变量的Final,带方法的Final,带类的Final。
1.Final with variable: u can`t assign this variable more than one time..
1。最后是变量:你不能分配这个变量超过一次。
2.Final with methods : u can`t override this method..
2。最后是方法:你不能重写这个方法。
3.Final with classes : u can`t extend any final class
3所示。期末课程:你不能延长任何期末课程
#16
-1
First of all, the final keyword is used to make a variable constant. Constant means it does not change. For example:
首先,final关键字用于创建一个变量常量。常数意味着它不会改变。例如:
final int CM_PER_INCH = 2.54;
You would declare the variable final because a centimeter per inch does not change.
你会声明变量final,因为每英寸1厘米不会改变。
If you try to override a final value, the variable is what it was declared first. For example:
如果您试图重写最终值,则该变量是首先声明的变量。例如:
final String helloworld = "Hello World";
helloworld = "A String"; //helloworld still equals "Hello World"
There is a compile error that is something like:
有这样一个编译错误:
local variable is accessed from inner class, must be declared final
If your variable cannot be declared final or if you don't want to declare it final try this:
如果您的变量不能声明为final,或者您不想声明为final,请尝试以下操作:
final String[] helloworld = new String[1];
helloworld[0] = "Hello World!";
System.out.println(helloworld[0]);
helloworld[0] = "A String";
System.out.println(helloworld[0]);
This will print:
这将打印:
Hello World!
A String
#1
149
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.
- 最后的静态字段——尽管我现在对许多使用静态最后字段的情况使用enum。
Consider but use judiciously:
考虑但明智的使用:
- Final classes - Framework/API design is the only case where I consider it.
- 最后的类——我只考虑框架/API设计。
- 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.
- 最后的方法——基本上和最后的类一样。如果您正在使用模板方法模式,比如crazy和markstuff 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.
- 方法参数和局部变量——我很少这样做,主要是因为我很懒,而且我发现它会使代码混乱。我完全承认,标记参数和我不打算修改的局部变量是“正确的”。我希望是违约。但事实并非如此,而且我发现在期末考试中,代码更难理解。如果我在别人的代码中,我不会把它们拖出来,但是如果我在写新代码,我不会把它们放进去。一个例外是您必须标记一些最终的东西,以便您可以从一个匿名内部类中访问它。
#2
42
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 final modifiers for you. Then you get the benefits for less effort.
不,如果您正在使用Eclipse,因为您可以配置一个Save操作来自动为您添加这些最终的修饰符。这样你就能少花点力气就得到好处。
#3
12
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”是有用的。它清楚地描述了扩展点的位置。
#4
7
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对于重构很有用,因为问题中的方法有好几页长,难以理解。最后*地撒下,看看“不能分配到最终变量”的错误,编译器(或者你的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 not already 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个参数!
#5
6
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.
作为补充说明,我曾在使用和不使用这种模式的项目中工作过,我发现bug和错误的数量没有差别……我不认为这是一种模式,它将极大地改善您的bug数或其他任何东西,但它还是风格,如果您喜欢表达您不会修改它的意图,那么就继续使用它。
#6
5
I use final
all the time to make Java more expression based. See Java's conditions (if,else,switch
) are not expression based which I have always hated especially if your used to functional programming (ie ML, Scala or Lisp).
我一直使用final来使Java更基于表达式。请参见Java的条件(if,else,switch)不是基于表达式的,我一直讨厌这种情况,尤其是如果您习惯于函数式编程(ie ML, Scala或Lisp)的话。
Thus you should try to always (IMHO) use final variables when using conditions.
因此,在使用条件时,应该始终(IMHO)使用最终变量。
Let me give you an example:
我举个例子:
final String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
case JOB_POSTING_IMPORT:
name = "Blah";
break;
default:
throw new IllegalStateException();
}
Now If add another case
statement and do not set name
the compiler will fail. The compiler will also fail if you do not break on every case (that you set the variable). This allows you to make Java very similar to Lisp's let
expressions and makes it so your code is not massively indented (because of lexical scoping variables).
现在,如果添加另一个case语句而不设置名称,编译器将失败。如果不破坏每个情况(设置变量),编译器也会失败。这使您可以使Java非常类似于Lisp的let表达式,并使您的代码不会出现大的缩进(因为词汇范围变量)。
And as @Recurse noted (but apparently -1 me) you can do the preceding with out making String name
final
to get the compiler error (which I never said you couldn't) but you could easily make the compiler error go away setting name after the switch statement which throws away the expression semantics or worse forgetting to break
which you cannot cause an error (despite what @Recurse says) without using final
:
@Recurse指出(但显然1我)你可以做前面的字符串名称最终得到编译器错误(我从来没有说过你不能),但是你可以很容易地使编译器错误消失设置名称后扔掉的switch语句表达语义或者更糟忘记休息不能导致一个错误(尽管@Recurse所说的),而不使用最终:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
//break; whoops forgot break..
//this will cause a compile error for final ;P @Recurse
case JOB_POSTING_IMPORT:
name = "Blah";
break;
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
Because of the bug setting name (besides forgetting to break
which also another bug) I can now accidentally do this:
由于错误的设置名称(除了忘记破坏另一个错误),我现在可以不小心这样做:
String name;
switch(pluginType) {
case CANDIDATE_EXPORT:
name = "Candidate Stuff";
break;
//should have handled all the cases for pluginType
}
// code, code, code
// Below is not possible with final
name = "Whoops bug";
The final variable forces a single evaluation of what name should be. Similar to how a function that has a return value must always return a value (ignoring exceptions) the name switch block will have to resolve name and thus bound to that switch block which makes refactoring chunks of code easier (ie Eclipe refactor: extract method).
最后的变量强制对名称进行单独的评估。与具有返回值的函数必须总是返回值(忽略异常)类似,name switch块必须解析名称,从而绑定到那个switch块,这使得重构代码块更容易(即Eclipe refactor: extract method)。
The above in OCaml:
上述在OCaml:
type plugin = CandidateExport | JobPostingImport
let p = CandidateExport
let name = match p with
| CandidateExport -> "Candidate Stuff"
| JobPostingImport -> "Blah" ;;
The match ... with ...
evaluates like a function ie expression. Notice how it looks like our switch statement.
这场比赛……与…像函数ie表达式那样计算。注意它看起来像我们的switch语句。
Here is an example in Scheme (Racket or Chicken):
下面是Scheme(球拍或鸡肉)中的一个例子:
(define name
(match b
['CandidateExport "Candidate Stuff"]
['JobPostingImport "Blah"]))
#7
4
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 on变量,这个变量不应该一直被修改。通过这样做,您的代码将更加“自我记录”,并且您也减少了其他开发人员做傻事的机会,比如使用本地常量作为本地临时变量。
If you're writing some throwaway code, then, nah, don't bother to identify all the constant and make them final.
如果您正在编写一些一次性的代码,那么,不,不要费事去识别所有的常量并使它们成为最终的。
#8
4
It is useful in parameters to avoid change the parameter value by accident and introduce a subtle bug. I use to ignore this recommendation but after spending some 4 hrs. in a horrible method ( with hundreds of lines of code and multiple fors, nested ifs and all sort of bad practices ) I would recommend you to do it.
在参数中避免意外地更改参数值并引入一个细微的错误是很有用的。我过去常常忽略这个建议,但在花了大约4个小时之后。在一个可怕的方法中(有数百行代码、多个fors、嵌套的ifs和所有的糟糕实践),我建议您这样做。
public int processSomethingCritical( final int x, final int y ){
// hundreds of lines here
// for loop here...
int x2 = 0;
x++; // bug aarrgg...
// hundreds of lines there
// if( x == 0 ) { ...
}
Of course in a perfect world this wouldn't happen, but.. well.. sometimes you have to support others code. :(
当然,在一个完美的世界里,这是不可能发生的。嗯. .有时您必须支持其他代码。:(
#9
3
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。如果您无意中更改了字段,那么这样做将标记。我还将方法参数设置为final。这样做时,我从我接手的代码中发现了几个错误,它们试图“设置”一个参数,而忘记了Java通过值传递。
#10
2
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 NOT convey 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只影响方法的主体。它不会向调用者传递任何关于方法意图的有趣信息。传入的对象仍然可以在方法中发生突变(final不是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。
#11
2
There are many uses for the variable final
. Here are just a few
变量final有很多用途。这里有一些
Final Constants
最后一个常量
public static class CircleToolsBetter {
public final static double PI = 3.141;
public double getCircleArea(final double radius) {
return (Math.pow(radius, 2) * PI);
}
}
This can be used then for other parts of your codes, or accessed by other classes, that way if you would ever change the value you wouldn't have to change them one by one.
然后,它可以用于代码的其他部分,或者被其他类访问,这样,如果您想要更改值,您就不必逐个更改它们。
Final Variables
最后一个变量
public static String someMethod(final String environmentKey) {
final String key = "env." + environmentKey;
System.out.println("Key is: " + key);
return (System.getProperty(key));
}
}
In this class, you build a scoped final variable that adds a prefix to the parameter environmentKey. In this case, the final variable is final only within the execution scope, which is different at each execution of the method. Each time the method is entered, the final is reconstructed. As soon as it is constructed, it cannot be changed during the scope of the method execution. This allows you to fix a variable in a method for the duration of the method. see below:
在这个类中,您将构建一个作用域最终变量,该变量向参数环境键添加前缀。在这种情况下,最终变量仅在执行范围内是最终变量,在方法的每次执行中都是不同的。每次输入方法时,都会重构最终方法。一旦构造了它,就不能在方法执行的范围内更改它。这允许您在方法的持续时间内固定一个变量。见下文:
public class FinalVariables {
public final static void main(final String[] args) {
System.out.println("Note how the key variable is changed.");
someMethod("JAVA_HOME");
someMethod("ANT_HOME");
}
}
Final Constants
最后一个常量
public double equation2Better(final double inputValue) {
final double K = 1.414;
final double X = 45.0;
double result = (((Math.pow(inputValue, 3.0d) * K) + X) * M);
double powInputValue = 0;
if (result > 360) {
powInputValue = X * Math.sin(result);
} else {
inputValue = K * Math.sin(result); // <= Compiler error
}
These are especially useful when you have really long lines of codes, and it will generate compiler error so you don't run in to logic/business error when someone accidentally changes variables that shouldn't be changed.
当您有很长的代码行时,这些代码特别有用,并且它将生成编译器错误,因此当某人意外地更改不应该更改的变量时,您不会运行到逻辑/业务错误中。
Final Collections
最后的集合
Different case when we are talking about Collections, you need to set them as an unmodifiable.
在讨论集合时,您需要将它们设置为不可修改的。
public final static Set VALID_COLORS;
static {
Set temp = new HashSet( );
temp.add(Color.red);
temp.add(Color.orange);
temp.add(Color.yellow);
temp.add(Color.green);
temp.add(Color.blue);
temp.add(Color.decode("#4B0082")); // indigo
temp.add(Color.decode("#8A2BE2")); // violet
VALID_COLORS = Collections.unmodifiableSet(temp);
}
otherwise, if you don't set it as unmodifiable:
否则,如果您不设置为不可修改:
Set colors = Rainbow.VALID_COLORS;
colors.add(Color.black); // <= logic error but allowed by compiler
Final Classes and Final Methods cannot be extended or overwritten respectively.
不能分别扩展或覆盖最终类和最终方法。
EDIT:TO ADDRESS THE FINAL CLASS PROBLEM REGARDING ENCAPSULATION:
编辑:解决关于封装的最终类问题:
There are two ways to make a class final. The first is to use the keyword final in the class declaration:
有两种方法可以让课堂期末考试。第一个是在类声明中使用关键字final:
public final class SomeClass {
// . . . Class contents
}
The second way to make a class final is to declare all of its constructors as private:
第二种使类成为最终类的方法是将其所有构造函数声明为私有:
public class SomeClass {
public final static SOME_INSTANCE = new SomeClass(5);
private SomeClass(final int value) {
}
Marking it final saves you the trouble if finding out that it is actual a final, to demonstrate look at this Test class. looks public at first glance.
如果发现它是一个真正的期末考试,那么在这个测试类中演示一下,那么标记它为final就省去了麻烦。第一眼就能看到公众。
public class Test{
private Test(Class beanClass, Class stopClass, int flags)
throws Exception{
// . . . snip . . .
}
}
Unfortunately, since the only constructor of the class is private, it is impossible to extend this class. In the case of the Test class, there is no reason that the class should be final. The Test class is a good example of how implicit final classes can cause problems.
不幸的是,由于类的惟一构造函数是私有的,所以不可能扩展这个类。对于测试类,没有理由认为类应该是final的。测试类是一个很好的例子,说明隐式最终类是如何引起问题的。
So you should mark it final when you implicitly make a class final by making it's constructor private.
因此,当隐式地将类设置为final时,应该将它标记为private。
#12
1
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.
就像你提到的那样,这是一种权衡,但我更喜欢用显式的东西,而不是用隐式的东西。这将有助于为将来的代码维护人员消除一些歧义——即使只有您自己。
#13
1
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.
除此之外,你说的是对的。
#14
0
Use final
keyword for a variable if you are making that variable as immutable
如果要使变量成为不可变的,则对变量使用final关键字
By declaring the variable as final, it aids developers to rule out possible modification issues of variables in highly multi-threaded environment.
通过将变量声明为final,它可以帮助开发人员排除高多线程环境中可能存在的变量修改问题。
With java 8 release, we have one more concept called "effectively final variable
". A non-final variable can heave as final variable.
在java 8发行版中,我们还有一个概念叫做“有效的最终变量”。非最终变量可以升腾为最终变量。
local variables referenced from a lambda expression must be final or effectively final
从lambda表达式引用的局部变量必须是最终的或有效的最终的
A variable is considered effective final if it is not modified after initialization in the local block. This means you can now use the local variable without final keyword inside an anonymous class or lambda expression, provided they must be effectively final.
如果变量在本地块中初始化后未被修改,则视为有效的最终变量。这意味着您现在可以在匿名类或lambda表达式中使用不带final关键字的局部变量,前提是它们必须是有效的final。
Till Java 7, you cannot use a non-final local variable inside an anonymous class, but from Java 8 you can
在Java 7之前,您不能在匿名类中使用非最终本地变量,但是从Java 8可以使用
Have a look at this article
看看这篇文章好吗
#15
0
A very simple answer we have 3 cases with Final with variables ,Final with methods && Final with classes..
一个非常简单的答案,我们有三种情况,带变量的Final,带方法的Final,带类的Final。
1.Final with variable: u can`t assign this variable more than one time..
1。最后是变量:你不能分配这个变量超过一次。
2.Final with methods : u can`t override this method..
2。最后是方法:你不能重写这个方法。
3.Final with classes : u can`t extend any final class
3所示。期末课程:你不能延长任何期末课程
#16
-1
First of all, the final keyword is used to make a variable constant. Constant means it does not change. For example:
首先,final关键字用于创建一个变量常量。常数意味着它不会改变。例如:
final int CM_PER_INCH = 2.54;
You would declare the variable final because a centimeter per inch does not change.
你会声明变量final,因为每英寸1厘米不会改变。
If you try to override a final value, the variable is what it was declared first. For example:
如果您试图重写最终值,则该变量是首先声明的变量。例如:
final String helloworld = "Hello World";
helloworld = "A String"; //helloworld still equals "Hello World"
There is a compile error that is something like:
有这样一个编译错误:
local variable is accessed from inner class, must be declared final
If your variable cannot be declared final or if you don't want to declare it final try this:
如果您的变量不能声明为final,或者您不想声明为final,请尝试以下操作:
final String[] helloworld = new String[1];
helloworld[0] = "Hello World!";
System.out.println(helloworld[0]);
helloworld[0] = "A String";
System.out.println(helloworld[0]);
This will print:
这将打印:
Hello World!
A String