是否可以将对象设置为“只读”方法

如果将对象引用传递给方法,是否可以使对象“只读”到该方法?

严格来说,不是。 也就是说,可以改变对象的引用不能转换为不能改变对象的引用。 此外,除了使用约定之外,没有办法表明类型是不可变的或可变的。

确保某种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; }