我在Servlet中有两个关于变量初始化的选项,我不想在@Singleton Servlet的生命周期内改变它,我们称之为:
Field a;
字段a将仅由servlet在内部使用,没有访问器方法,为简单起见,字段a是不可变的,如String。
选项1 - 使用从ServletContext的依赖注入获得的信息初始化构造函数内的字段,以便该字段变为:
private final Field a;
选项2 - 使用从ServletConfig(和ServletContext)获取的信息在覆盖的init(ServletConfig cfg)方法中设置变量,以便该字段变为:
private Field a;
显然,我更喜欢将该字段设为final,但该字段是私有的,并且没有附加的访问方法,所以我是否应该尝试将其作为最终版本?
因此,总结一下,是否应该在构造函数中初始化一个字段并使其成为最终字段,或者在init方法中初始化并保留为非final字段而没有访问者?
谢谢。
答案 0 :(得分:2)
显然,我更喜欢将该字段设为final,但该字段是私有的,并且没有附加的访问方法,所以我是否应该尝试将其作为最终版本?
是。它使你的意图更清晰。如果它不是最终的,你愿意多少赌注,没有人会在后来添加一个改变它的方法,仍然留下有效地假设它不会被改变的代码?
答案 1 :(得分:2)
声明它final
的好处是你不会无意中在代码中的某处更改它。
答案 2 :(得分:1)
除了清楚地记录您的意图并使代码更易于理解和维护之外,final
修饰符还可在多线程应用程序中提供一些重要保证。
虽然我不确定它是否由Servlet规范保证,但似乎在实践中,servlet引擎应该使用一些内存屏障来确保新servlet实例的内部状态对于所有线程都是可见的将使用它来处理servlet请求。这被称为“安全出版物”。
但是,一般而言,情况并非如此。你所描述的“选项2”是“有效的不变性”。该对象的字段不是final
,但在构造或某些初始化步骤后不允许修改该字段。但是,如果其他线程在没有通过内存屏障的情况下访问此对象,则它们可能看不到初始化线程分配给该字段的值 - 即使在对象的构造函数中设置了此字段!
但是,在对象构造期间为final
字段分配的值保证对所有其他线程可见,即使对象本身未“安全发布”。