Доступ к закрытому полю другого объекта в конструкторах копий. Действительно проблема?

В моем приложении Java у меня есть такие конструкторы-копии, как этот

public MyClass(MyClass src) {
    this.field1 = src.field1;
    this.field2 = src.field2;
    this.field3 = src.field3;
...
}

Теперь Netbeans 6.9 предупреждает об этом, и мне интересно, что не так с этим кодом?

Мои проблемы:

  • Использование геттеров может привести к нежелательным побочным эффектам. Новый объект больше не может считаться копией оригинала.
  • Если рекомендуется использовать геттеры, не было бы более последовательным, если бы вы использовали сеттеры для нового экземпляра?

РЕДАКТИРОВАТЬ: Фактическое предупреждение - "Доступ к закрытому полю другого объекта" и единственное доступное действие. Предложения Netbeans добавляют @SuppressWarnings("AccessingNonPublicFieldOfAnotherObject")

Мой код на самом деле такой же тривиальный, как в данном примере.

Ответ 1

Я не вижу проблем с кодом. Фактически, я разделяю ваши проблемы и предпочитаю не использовать геттеры.

Что именно вы получаете? Может быть, это связано с тем, что вы не показываете нам?

Обновление: Похоже, Netbeans действительно жалуется на это. Я думаю, это довольно противоречивое предупреждение для доставки с IDE.

Ответ 2

Это напоминает мне обсуждение ADT и Object.

ADT может получить доступ к внутреннему состоянию другого экземпляра ADT. Философия объекта предотвратит это и обеспечит доступ через getter/setter, чтобы обеспечить независимость представления.

Было высказано мнение, что переменная экземпляра на Java class-private, а не object-private (в более позднем случае разрешено использовать только this.privateInstVar, а не obj.privateInstVar).

У этого есть как сила, так и слабость. Это особенно удобно, когда дело доходит до клонирования и равенства. С другой стороны, это может быть неправильно использовано и сломать инкапсуляцию.

Это почти философская дискуссия. Но ИМХО, что вы делаете, прекрасно.

Ответ 3

Я не знаю, почему предупреждает NetBeans, но вы делаете мелкую копию. Ваша копия разделяет поле1, поле2 и поле3 с помощью src и как таковая модификация поля3, скажем, списка, будет отражена в оригинале.

private List field1;

public MyClass(MyClass src) {
    this.field1 = src.field1;
    this.field2 = src.field2;
    this.field3 = src.field3;

    field1.add(new Object()); // field1 of src also modified
...
}

Ответ 4

Возможно, класс может предоставить метод мелкой копии, который знает, какие данные будут возвращены в скопированном объекте. При необходимости вы также можете предоставить глубокую копию.

public MyClass shallowCopy() {
  MyClass aCopy = new MyClass();
  aCopy.field1 = this.field1;
  aCopy.field2 = this.field2;
  aCopy.field3 = this.field3;
}