有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

避免副作用的java最佳实践

我有一个关于如何避免对Java对象产生副作用的问题。 假设我有一个类myObject的实例myObject。我想通过一系列方法/命令处理myobject,在每个命令级别,我想用方法/命令计算的内容丰富myobject

这里,myObject的类是:

public class MyObject {
  private int resultOfCommand1;
  private int resultOfCommand2;
  private int resultOfCommand3;
  private int resultOfCommand4;
  ....
  ....
}

以下是myObject必须通过以下方式处理的方法/命令:

private MyObject command1(MyObject myObject) {
   return myObject.setRresultOfCommand1(1);
}
private MyObject command2(MyObject myObject) {
   return myObject.setRresultOfCommand2(2);
}
private MyObject command3(MyObject myObject) {
   return myObject.setRresultOfCommand3(3);
}
private MyObject command4(MyObject myObject) {
   return myObject.setRresultOfCommand4(4);
}

因此,上面显示的设计确实有副作用,我希望避免这种情况

有谁能告诉我避免副作用的最佳方法吗?始终创建作为参数传递的对象的副本(在本例中为myObject)是否更好,对副本进行更改,然后返回它? 有没有保证多线程安全性的最佳方法

任何帮助都将不胜感激。 霍勒斯


共 (1) 个答案

  1. # 1 楼答案

    如果要避免副作用,设置值的方法不能更改实例,而是返回一个新实例(副本)。在该方法中,使用构造函数设置所有(最终)值

    例如:

    class C {
        private final int x;
        private final int y;
    
        public C(int _x) {
            super();
            this.x = _x;
            this.y = -1;
        }
    
        public C(int _x, int _y) {
            super();
            this.x = _x;
            this.y = _y;
        }
    
        public C setY(int _y) {
            return new C(this.x, _y);
        }
    }
    

    为了防止副作用,只需将字段声明为final。如果所有字段都是final,则值(对于基元类型)和对象引用是不可变的。对于对象引用,该对象也必须是不可变的,以实现“完全不可变”

    因此,您不会更改副本,而是使用新值构建副本

    现在可以安全地传递不可变的实例;它无法更改,因此是线程安全的