Каков наилучший способ отправки защитной копии данных?

Я только что прочитал эффективное правило Java 39 (Защитная копия). В явном виде не указывается, что для каждой транзакции данных должно выполняться два раза копирования, чтобы следовать этому правилу. Ниже приведен пример кода, который я подумал. Это кажется несколько излишним. Я правильно понимаю? Есть ли лучший способ?

public class SomeClass {

    private MyData myData; 

    SomeClass() {
        myData = new MyData("1");
    }

    public MyData getData() {
        return new MyData(myData); // 1st Copy of data
    }

    public static void main(String[] args) {
        SomeClass someClass = new SomeClass();
        OtherClass otherClass = new OtherClass(someClass.getData()); //Pass data which is invariant
    }
}

class OtherClass {

    MyData myData; 

    OtherClass(MyData data) {
        myData = new MyData(data);  // 2nd Copy of data
    }
}

class MyData {
    private String name;
    public MyData(String name) { this.name = name; }
    public MyData(MyData data) { this.name = data.name; }
    public void setName(String name) { this.name = name; }
}

1 ответ

Решение

Ваше понимание верно, и конструктор, и метод делают защитные копии MyData, Они делают это по несколько другим причинам, которые обсуждаются ниже.

Есть две причины сделать защитную копию:

  1. Защита от изменения входящих данных - вызывающий абонент передает вам объект и решает изменить его позже. Поскольку вы сделали защитную копию, изменения, внесенные вызывающей стороной, не влияют на данные, которые вы храните внутри, и
  2. Защита от изменения исходящих данных - вызывающая сторона может решить изменить объект, полученный одним из ваших методов. Поскольку вы вернули защитную копию своего объекта, ваши внутренние данные остаются в безопасности.

Код демонстрирует обе ситуации - OtherClass(MyData data) конструктор демонстрирует проблему #1, в то время как MyData getData() демонстрирует проблему № 2.

Обратите внимание, что защитные копии требуются только из-за решения сделать MyData изменяемый класс (т.е. setName метод). Нет необходимости делать защитные копии объектов неизменяемых классов.

Другие вопросы по тегам