在Java中,有一种惯例,将每个变量(局部变量或类)声明为final参数(如果它们确实是final的话)。

虽然这会使代码更加冗长,但这有助于容易阅读/掌握代码,也可以防止错误,因为意图被清晰地标记出来。

你对此有何看法?


当前回答

对于将所有可能的变量都声明为final,我非常武断。这包括方法参数、局部变量,以及很少的值对象字段。我有三个在任何地方声明最终变量的主要原因:

Declaring Intention: By declaring a final variable, I am stating that this variable is meant to be written to only once. It's a subtle hint to other developers, and a big hint to the compiler. Enforcing Single-use Variables: I believe in the idea that each variable should have only one purpose in life. By giving each variable only one purpose, you reduce the time it takes to grok the purpose of that particular variable while debugging. Allows for Optimization: I know that the compiler used to have performance enhancement tricks which relied specifically on the immutability of a variable reference. I like to think some of these old performance tricks (or new ones) will be used by the compiler.

然而,我确实认为final类和方法远不如final变量引用有用。最后一个关键字,当与这些声明一起使用时,只是为自动化测试和以您从未预料到的方式使用代码提供了障碍。

其他回答

有效的Java有一个条目写着“偏爱不可变对象”。将字段声明为final可以帮助您在这方面迈出一小步,但是对于真正的不可变对象来说,当然还有更多的事情要做。

如果您知道对象是不可变的,那么可以在多个线程/客户端之间共享它们以供读取,而无需担心同步问题,并且更容易推断程序的运行方式。

我从不在局部变量上使用它们,没有什么意义。即使您不认为变量应该被重新赋值,这对于下一个改变代码的人来说也没有什么区别,而且由于代码正在被更改,任何使其最终的原始目的都可能不再有效。如果只是为了清晰,我认为它失败了,因为冗长的负面影响。

对于成员变量也是如此,因为它们提供的好处很少,除了常量的情况。

它也与不可变无关,因为不可变的最好指标是它被这样记录并且/或没有可以改变对象的方法(这与使类为final是保证它是不可变的唯一方法)。

但是,嘿,这只是我的观点:-)

将类标记为final还可以使一些方法绑定发生在编译时而不是运行时。 考虑下面的“v2.foo()”——编译器知道B不能有子类,所以foo()不能被重写,所以要调用的实现在编译时是已知的。如果类B没有被标记为final,那么v2的实际类型可能是某个扩展B并重写foo()的类。

class A {
    void foo() {
        //do something
    }
}
final class B extends A {
    void foo() {
    }
}
class Test {
    public void t(A v1, B v2) {
        v1.foo();
        v2.foo();
    }
}

Final显然应该用在常量上,并加强不可变性,但在方法上还有另一个重要的用途。

Effective Java在这方面有一个完整的项目(项目15),指出了意外继承的陷阱。实际上,如果您没有为继承而设计和记录您的类,那么从它继承可能会带来意想不到的问题(该项目提供了一个很好的例子)。因此,建议在不打算继承的任何类和/或方法上使用final。

That may seem draconian, but it makes sense. If you are writing a class library for use by others then you don't want them inheriting from things that weren't designed for it - you will be locking yourself into a particular implementation of the class for back compatibility. If you are coding in a team there is nothing to stop another member of the team from removing the final if they really have to. But the keyword makes them think about what they are doing, and warns them that the class they are inheriting from wasn't designed for it, so they should be extra careful.

对于将所有可能的变量都声明为final,我非常武断。这包括方法参数、局部变量,以及很少的值对象字段。我有三个在任何地方声明最终变量的主要原因:

Declaring Intention: By declaring a final variable, I am stating that this variable is meant to be written to only once. It's a subtle hint to other developers, and a big hint to the compiler. Enforcing Single-use Variables: I believe in the idea that each variable should have only one purpose in life. By giving each variable only one purpose, you reduce the time it takes to grok the purpose of that particular variable while debugging. Allows for Optimization: I know that the compiler used to have performance enhancement tricks which relied specifically on the immutability of a variable reference. I like to think some of these old performance tricks (or new ones) will be used by the compiler.

然而,我确实认为final类和方法远不如final变量引用有用。最后一个关键字,当与这些声明一起使用时,只是为自动化测试和以您从未预料到的方式使用代码提供了障碍。