是否可以将对象设置为“只读”方法
如果将对象引用传递给方法,是否可以使对象“只读”到该方法?
严格来说,不是。 也就是说,可以改变对象的引用不能转换为不能改变对象的引用。 此外,除了使用约定之外,没有办法表明类型是不可变的或可变的。
确保某种forms的不变性的唯一特征是final
字段 – 一旦写入就无法修改。
也就是说,有一些方法可以设计类, 以防止不必要的突变 。 以下是一些技巧:
-
防御性复制 。 传递对象的副本,这样如果它被突变,它不会破坏你的内部不变量。
-
使用访问修饰符和/或接口仅显示只读方法。 您可以使用访问修改(
public
/private
/protected
),可能与接口结合使用,以便只有某些方法对另一个对象可见。 如果暴露的方法本质上是只读的,那么您就是安全的。 -
默认情况下,使对象不可变 。 对象上的任何操作实际上都返回该对象的副本。
另请注意,SDK中的API有时会返回对象的不可变版本的方法,例如Collections.unmodifiableList
。 尝试改变不可变列表将引发exception。 这不会静态地强制实现不变性(在编译时使用静态类型系统),但它是一种廉价而有效的方法(在运行时)动态强制执行它。
已经有许多关于Java扩展的研究提议,以更好地控制别名和可访问性。 例如,添加readonly
关键字。 据我所知,它们都没有包含在未来的Java版本中。 如果您有兴趣,可以查看这些指针:
- 为什么我们不应该向Java添加”只读” – 它列出并比较了大多数提案
- Checker Framework:Java的自定义可插入类型 – 扩展类型系统的非侵入式方法,特别是使用不可变类型。
Checker Framework非常有趣。 在Checker Framework中,查看Generic Universe Types checker,IGJ immutability checker和Javari immutability checker。 该框架使用注释工作,因此它不具有侵入性。
不,不是没有装饰,合成,克隆等。
没有一般的机制。 您需要编写特殊情况代码来实现它,比如编写一个不可变的包装器(请参阅Collections.unmodifiableList
)。
在大多数情况下,您可以通过将Object
克隆为方法的第一个语句来实现类似的操作,例如…
public void readOnlyMethod(Object test){ test = test.clone(); // other code here }
因此,如果您调用readOnlyMethod()
并传入任何Object
,则将获取Object
的克隆。 克隆使用与方法参数相同的名称,因此不存在意外更改原始Object
风险。
不。但是您可以尝试在传递之前克隆该对象,因此该方法所做的任何更改都不会影响原始对象。
使它实现一个只有只读方法的接口(没有setter方法),它给出了一个对象的副本(仅限道路的副本)并返回只读的接口实例而不是返回一个对象本身的实例
您可以将对象的所有参数定义为final
但这会使对象只读给每个人。
取决于您希望规则强制执行的位置。 如果您正在协作处理项目,请使用final
和评论告诉下一个人他们不打算修改此值。 否则你不会简单地写方法不触摸对象?
public static void main(String[] args) { cantTouchThis("Cant touch this"); } /** * * @param value - break it down */ public static void cantTouchThis(final String value) { System.out.println("Value: " + value); value = "Nah nah nah nah"; //Compile time error }
特别是对于这种方法,该值永远不会被写入,并且在编译时强制执行,使得解决方案非常健壮。 在此方法的范围之外,对象保持不变,而不必创建任何类型的包装器。
private boolean isExecuteWriteQueue = false; public boolean isWriting(){ final boolean b = isExecuteWriteQueue; return b; }