이번 포스팅은 이펙티브 자바의 아이템 중 "변경 가능성을 최소화하라"에 대한 내용입니다.
보통 변경 가능성을 줄이기 위해서 불변 클래스 사용을 권장하고 있습니다.
불변 클래스는 가변 클래스 보다 설계하고 구현하기 쉽고, 사용하기 좋고, 오류가 생길 여지도 적고 안전합니다.
그래서 이번 기회에 불변 클래스에 대한 내용을 정리하려고 합니다.
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