如何允许在java中只设置一次变量
我需要在java中实现一个类,它的字段只需要设置一次,但在字段声明中它的值是未知的。为此,我必须:如何允许在java中只设置一次变量,java,final,setter,Java,Final,Setter,我需要在java中实现一个类,它的字段只需要设置一次,但在字段声明中它的值是未知的。为此,我必须: public class MyClass { private String field1 = null; public void setField1(String value) { if (field1 == null) { field1 = value; } } } 但是,我所做的并不能阻止用户多次调用setFi
public class MyClass {
private String field1 = null;
public void setField1(String value) {
if (field1 == null) {
field1 = value;
}
}
}
但是,我所做的并不能阻止用户多次调用setField1
。这可能会导致混淆,用户试图设置它(不知道它已在其他地方设置),然后用户会被field1
没有给出他们设置的值而混淆-直到他们进入setField1
方法查看发生了什么
我不喜欢的另一个解决方案是,让构造函数考虑field1
的值,然后不提供setter。因为它使类更难扩展,当需要多个字符串字段时-在这种方法中,构造函数需要将一对String
作为参数,然后用户很容易被参数混淆/丢失参数
显然,将field1
设置为final
也不起作用
我应该怎么做来防止我上面提到的问题?这种情况下的常见做法是抛出
运行时异常。在您的情况下,最适合:
public void setField1(String value) {
if (field1 != null) {
throw new IllegalStateException("setField1 was already called");
}
field1 = Objects.requireNonNull(value);
}
还要注意,最好检查传递的字符串是否为null(我为此添加了)
您无法在编译时控制这一点,因为在不实际运行程序的情况下,无法分析程序以准确说明方法是否调用了一次或多次。对于以下情况,您通常应该使用生成器模式:
生成器对象允许您设置所有喜欢的字段和选项,但它生成的MyClass实例不允许设置这些字段和选项。如果不为null,则引发异常。然后调用方就会知道他们做错了什么;您可以在同一个实例上多次成功调用setField1。@Davidermann说得很好,谢谢您的提醒。虽然这样做很有效,但构建器模式更好—我喜欢不必抛出运行时异常的想法。生成器模式防止编码器走错方向。谢谢你!
MyClass instance = (new MyClassBuilder())
.setField1(...)
.setField2(...)
.build();