4

我在 Servlet 中有两个选项,用于初始化我不想在 @Singleton Servlet 的生命周期内更改的变量,我们称之为:

Field a;

字段 a 将仅由 servlet 在内部使用,没有访问器方法,并且为简单起见,字段 a 是不可变的,例如字符串。

选项 1 - 利用从 ServletContext 的依赖注入中获得的信息初始化构造函数内的字段,以便该字段变为:

private final Field a;

选项 2 - 利用从 ServletConfig(和 ServletContext)获得的信息,在重写的 init(ServletConfig cfg) 方法中设置变量,以便该字段变为:

private Field a;

显然,我更希望将字段设为 final,但该字段是私有的,并且没有附加任何访问器方法,所以我是否仍应尝试将其设为 final?

所以,总而言之,一个字段应该在构造函数中初始化并成为最终的,还是在 init 方法中初始化并保留为非最终的没有访问器?

谢谢你。

4

3 回答 3

2

显然,我更希望将字段设为 final,但该字段是私有的,并且没有附加任何访问器方法,所以我是否仍应尝试将其设为 final?

是的。它使您的意图更加清晰。如果它不是最终的,你愿意打赌,以后没有人会添加一个改变它的方法,仍然留下有效假设它不会被改变的代码?

于 2012-05-17T15:56:54.923 回答
2

声明它的好处final是您不会无意中在代码中的某处更改它。

于 2012-05-17T15:57:14.477 回答
1

In addition to documenting your intent clearly and making your code easier to understand and maintain, a final modifier provides some important assurances in a multi-threaded application.

While I'm not sure if it's guaranteed by the Servlet specification, it seems that in practice, servlet engines should use some memory barrier that will ensure that the internal state of a new servlet instance is visible to all of the threads that will use it to process servlet requests. This is called "safe publication."

However, in general, this is not the case. What you describe as "Option 2" is "effective immutability." The object has a field that isn't final, but doesn't allow modification of that field after construction or some initialization step. But, if other threads access this object without going through a memory barrier, they might not see the value assigned to that field by the initializing thread—even if this field was set in the object's constructor!

A value assigned during object construction to a final field, however, is guaranteed to be visible to all other threads, even if the object itself is not "safely published."

于 2012-05-17T16:17:54.190 回答