이번 포스팅은 이펙티브 자바의 아이템 중 "변경 가능성을 최소화하라"
에 대한 내용입니다.
보통 변경 가능성을 줄이기 위해서 불변 클래스
사용을 권장하고 있습니다.
불변 클래스
는 가변 클래스 보다 설계하고 구현하기 쉽고, 사용하기 좋고, 오류가 생길 여지도 적고 안전합니다.
그래서 이번 기회에 불변 클래스
에 대한 내용을 정리하려고 합니다.
public class Test{
private int x;
public void setX(int x){
this.x = x; //이런 로직 x
}
}
//Test가 불변 객체라고 가정
public class Test2 extends Test{
private int y;
public Test2(final int x, final int y) {
super(x);
this.y = y;
}
public int getY() {
return y;
}
public void setY(final int y) { //가변 객체가 되지만 Test의 타입을 사용할 수 있다.
this.y = y;
}
}
getAddress()
를 통해서 외부에서 가변 클래스에 접근할 수 있습니다.public final class Person {
private final int age;
private final Address address;
public Person(final int age, final Address address) {
this.age = age;
this.address = address;
}
public int getAge() {
return age;
}
public Address getAddress() {
return address;
}
}
public class Address {
private String city;
public Address(final String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setCity(final String city) {
this.city = city;
}
}
public static void main(String[] args) {
Person person = new Person(13, new Address("city"));
Address address = person.getAddress();
System.out.println(person.getAddress().getCity()); // city
address.setCity("new City");
System.out.println(person.getAddress().getCity());// new city
}
public BigInteger negate() {
return new BigInteger(this.mag, -this.signum); // 내부 데이터를 사용하여 다시 불변객체를 리턴합니다.
}
한 꺼번에 연산을 수행하게 하여 인스턴스 생성을 줄일 수 있습니다.
+
, -
, *
연산을 한다고 가정하면, 세 번의 연산을 하기 때문에 세 개의 불변 객체가 생성됩니다.가변 동반 클래스
를 제공하여 대처할 수 있습니다.
private, private-package 생성자와 정적 팩터리 메서드를 사용할 수 있습니다.
이렇게 되면, 클래스 내부에서 내부 클래스를 상속해 활용할 수 있습니다. 즉, 확장이 가능해 집니다.
private static class MyComplex extends Complex {
private MyComplex(double re, double im) {
super(re, im);
}
}
자주 사용되는 객체라면 static으로 캐싱을 적용할 수 있습니다.
재정의가 가능한 클래스는 방어적인 복사를 사용해야 합니다.
public static BigInteger safeInstance(BigInteger val) {
return val.getClass() == BigInteger.class ? val : new BigInteger(val.toByteArray()); <--방어적 복사
}
외부에 공개해야하는 필드는 final이어야 한다.
reference