불변의 POJO는 다음과 같이 작성되었습니다.
public class MyObject {
private final String foo;
private final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
그러나 나는 이것을 다음과 같이 쓰는 경향이 있습니다.
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
참조는 최종적이므로 Object는 여전히 불변입니다. 더 적은 코드를 작성하고 더 짧은 (5 자 : get
and and ()
) 액세스를 허용합니다.
내가 볼 수있는 유일한 단점은 getFoo()
미친 짓을하기 위해 길 아래로 구현을 변경하려는 경우 할 수 없다는 것입니다. 그러나 현실적으로 이것은 Object가 불변이기 때문에 발생하지 않습니다. 당신은 인스턴스화 중에 확인 (구아바의 참조 인스턴스화하는 동안 불변의 방어 복사본을 만들 수 있습니다 ImmutableList
예를 들어), 그리고 얻을 foo
또는 bar
준비 개체를 get
호출.
내가 놓친 단점이 있습니까?
편집하다
필자가 놓친 또 다른 단점은 get
or로 시작하는 메소드에 대한 리플렉션을 사용하는 직렬화 라이브러리라고 생각 is
하지만 꽤 끔찍한 사례입니다 ...
String
, int
또는 MyObject
. 첫 번째 버전에서는 final
클래스 내의 생성자 이외의 메서드 bar = 7;
가 예를 들어 시도하지 않도록하는 것 입니다. 두 번째 버전에서는 final
소비자가 다음을 수행하지 못하도록해야합니다 MyObject x = new MyObject("hi", 5); x.bar = 7;
..
Object
여전히 불변입니다. "는 오해의 소지가 있습니다 final Object
. 오해해서 죄송합니다.
myObj.getFoo().setFrob(...)
.
final
변수를 객체를 불변으로 만들지 않습니다. 나는 일반적으로final
콜백이 해당 필드에 액세스 할 수 있도록 콜백을 만들기 전에 필드를 정의하는 디자인을 사용 합니다. 물론 모든 메소드를 포함한 모든 메소드를 호출 할 수 있습니다setX
.