在Java中,有一种做法是声明每个变量(本地或类),如果确实是参数final.
虽然这使得代码更加冗长,但这有助于轻松阅读/掌握代码,并且还可以防止错误,因为意图已明确标记.
您对此有何看法,您对此有何看法?
痴迷于:
最终字段 - 将字段标记为最终强制它们在构造结束时设置,使该字段引用不可变.这样可以安全地发布字段,并且可以避免在以后的读取时进行同步.(请注意,对于对象引用,只有字段引用是不可变的 - 对象引用引用的内容仍然可以更改并影响不变性.)
最终的静态字段 - 虽然我现在使用枚举用于我曾经使用静态最终字段的许多情况.
考虑但明智地使用:
最终类 - 框架/ API设计是我认为的唯一案例.
最终方法 - 与最终类基本相同.如果你正在使用模板方法模式,如疯狂和标记最终的东西,你可能过分依赖继承而不是委托.
忽略除非感觉肛门:
方法参数和局部变量 - 我很可能这样做很大程度上是因为我很懒,我发现它使代码混乱.我将完全承认,我不打算修改的标记参数和局部变量是"更严格".我希望这是默认的.但事实并非如此,而且我发现整个决赛的代码更难以理解.如果我在别人的代码中,我不会把它们拉出去,但是如果我正在编写新的代码,我就不会把它们放进去.一个例外是你需要标记最终的东西以便你可以访问它来自一个匿名的内部类.
我认为这一切都与良好的编码风格有关.当然,你可以编写好的,健壮的程序而不需要在final
任何地方使用很多修饰符,但是当你想到它时......
添加final
所有不应改变的东西只会缩小您(或下一个程序员,处理您的代码)会误解或误用导致您的代码的思维过程的可能性.当他们现在想要改变你以前不可改变的东西时,至少应该响起一些钟声.
首先,final
在你的代码中看到很多关键字看起来很尴尬,但很快你就会停止注意这个词本身,并且只会想到,这件事情将永远不会改变 - 从这一点 -在(你可以从我这里拿走;-)
我认为这是一个很好的做法.我并不是一直都在使用它,但是当我可以并且标记某些东西时final
我会这样做是有意义的.
在使用之前,您确实需要了解final关键字的完整用法.它可以应用于变量,字段,方法和类,并对其有不同的影响
我建议查看下面链接的文章了解更多详情.
关于最终关键字的最后一句话
该final
修改,特别是变量,是可以让编译器强制执行约定,一般是明智的手段:确保(本地或实例)变量分配一次(不多不少).通过确保在使用变量之前明确赋值,可以避免常见的情况NullPointerException
:
final FileInputStream in; if(test) in = new FileInputStream("foo.txt"); else System.out.println("test failed"); in.read(); // Compiler error because variable 'in' might be unassigned
通过防止变量被多次分配,您可以阻止过于宽泛的范围.而不是这个:
String msg = null; for(int i = 0; i < 10; i++) { msg = "We are at position " + i; System.out.println(msg); } msg = null;
我们鼓励您使用此:
for(int i = 0; i < 10; i++) { final String msg = "We are at position " + i; System.out.println(msg); }
一些链接:
最后的故事("Hardcore Java"一书的免费章节)
一些最终模式
明确的任务
我非常教条宣称每个可能的变量final
.这包括方法参数,局部变量和很少的值对象字段.我有三个主要原因可以在任何地方声明最终变量:
声明意图:通过声明一个最终变量,我声明这个变量只能写入一次.这是对其他开发人员的一个微妙暗示,也是编译器的一个重要提示.
强制执行一次性变量:我相信每个变量在生活中应该只有一个目的.通过给每个变量只有一个目的,可以减少在调试时理解该特定变量的目的所需的时间.
允许优化:我知道编译器曾经有过性能增强技巧,它特别依赖于变量引用的不变性.我喜欢认为编译器会使用这些旧的性能技巧(或新的).
但是,我确实认为最终的类和方法几乎没有最终变量引用那么有用.final
与这些声明一起使用时,关键字只会为自动化测试提供障碍,并以您从未预料到的方式使用您的代码.
Effective Java有一个项目"赞成不可变对象".将字段声明为final可以帮助您对此采取一些小步骤,但对于真正不可变的对象,当然还有更多.
如果您知道对象是不可变的,则可以共享它们以便在没有同步担忧的情况下在许多线程/客户端之间进行读取,并且更容易推断出程序的运行方式.
我从来没有遇到过变量上的最终关键字阻止我犯错误的情况,所以目前我认为这是浪费时间.
除非有这样做的真正原因(因为你想要对该变量做出最终的具体观点),我宁愿不这样做,因为我发现它使代码的可读性降低.
但是,如果你没有发现它会使代码更难以阅读或更长时间地写入,那么一定要去寻找它.
编辑:作为一个澄清(并尝试赢回选票),我不是说不要将常数标记为最终,我说不要做的事情如下:
public String doSomething() { final String first = someReallyComplicatedExpressionToGetTheString(); final String second = anotherReallyComplicatedExpressionToGetAnother(); return first+second; }
它只是使代码(在我看来)更难阅读.
值得记住的是,所有最终的做法都是阻止你重新分配一个变量,它不会让它变成不可变的或类似的东西.
Final应始终用于常量.当定义变量的规则很复杂时,它对于短期变量(在单个方法中)甚至有用.
例如:
final int foo; if (a) foo = 1; else if (b) foo = 2; else if (c) foo = 3; if (d) // Compile error: forgot the 'else' foo = 4; else foo = -1;
我final
一直用于对象属性.
final
在对象属性上使用时,关键字具有可见性语义.基本上,在构造函数返回之前设置最终对象属性的值.这意味着,只要你不要让this
参考逃脱的构造和使用final
的所有您的属性,你的目标是(在Java 5的语义)保证的广告进行适当构造,并且因为它是不可变的也可以放心地发布到其他线程.
不可变对象不仅仅是线程安全.它们还可以更容易地推断出程序中的状态转换,因为可以改变的空间是有意识的,并且如果一致地使用,则仅限于应该改变的事物.
我有时也会把方法做成最终,但不是经常.我很少把课程定稿.我一般这样做是因为我没有必要这样做.我通常不会使用很多继承.我更喜欢使用接口和对象组合 - 这也适用于我发现通常更容易测试的设计.当您对接口而不是具体类进行编码时,在使用jMock等框架进行测试时,不需要使用继承,使用接口创建模拟对象比使用具体类更容易.
我想我应该让我的大部分班级最终完成,但我还没有进入habbit.
听起来,反对使用final关键字的最大争论之一是“这是不必要的”,并且“浪费了空间”。
如果我们承认此处许多出色的文章所指出的“ final”的许多好处,同时承认它需要更多的键入和空间,那么我认为Java应该默认将变量设为“ final”,并要求将事物标记为“可变”。