Доступ к закрытому полю другого объекта в конструкторах копий. Действительно проблема?
В моем приложении 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;
}