변경 불가능 클래스
변경 불가능 클래스는 말 그대로 내부의 정보를 수정할 수 없는 클래스이다. 객체 내부의 정보는 객체가 생성될 때 주어진 것이며 객체가 만들어 지고 없어질 때까지 변경되지 않는다. 이러한 클래스를 만드는 이유는 다양하다. 변경 가능 클래스보다 설계 및 구현 하기가 쉽고, 오류가 적으며, 사용하기도 쉽다.
변경 불가능 클래스를 만들기 위한 규칙
- 객체 상태를 변경하는 메소드를 제공하지 않는다.
- 상속하지 못하게 final로 클래스를 만든다. 상속을 받아서 클래스를 정의하게 되면 객체 상태가 변경된 것처럼 동작할 수 있기 때문이다.
- 모든 필드를 final로 선언한다. 시스템이 강제하는 형태대로 프로그래머의 의도가 분명히 드러나고 새로 생성된 객체에 대한 참조가 동기화 없이 다른 스레드로 전달 되어도 안전하기 때문이다.
- 모든 필드를 private로 선언한다. 이 객체를 사용하는 다른 사용자가 필드를 변경할 수 없기 때문이다.
- 변경 가능 컴포넌트에 대한 독점적 접근권을 보장한다. 클래스에 포함된 변경 가능 객체에 대한 참조를 클라이언트는 획득할 수 없어야 한다.
변경 불가능 클래스 예시
public final class Complex {
// 많이 사용하는 것들은 미리 만들어서 사용하는 것이 좋다
public static final Complex ZERO = new Complex(0, 0);
public static final Complex ONE = new Complex(1, 0);
public static final Complex I = new Complex(0, 1);
private final double re;
private final double im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
// 대응되는 수정자가 없는 접근자들
public double realPart() {
return re;
}
public double imginaryPart() {
return im;
}
public Complex add(Complex c) {
return new Complex(re + c.re, im + c.im);
}
public Complex subtract(Complex c) {
return new Complex(re - c.re, im - c.im);
}
public Complex multiply(Complex c) {
return new Complex(re * c.re - im * c.im, re * c.im + im * c.re);
}
public Complex divide(Complex c) {
double tmp = c.re * c.re + c.im * c.im;
return new Complex((re * c.re + im * c.im) / tmp, (im * c.re - re * c.im) / tmp);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Complex)) {
return false;
}
Complex c = (Complex) o;
return Double.compare(re, c.re) == 0 && Double.compare(im, c.im) == 0;
}
@Override
public int hashCode() {
int result = 17 + hashDouble(re);
result = 31 * result + hashDouble(im);
return result;
}
private static int hashDouble(double val) {
long longBits = Double.doubleToLongBits(val);
return (int) (longBits ^ (longBits >>> 32));
}
@Override
public String toString() {
return "(" + re + " + " + im + "i)";
}
}
- 간단하게 작성된 것이며 실제로 사용하기에는 부적합할 것이다.
단점
유일한 단점은 만약 반환해야 한다면 새로운 객체를 만들어서 반환해햐 한다. 이러면 많은 메모리가 낭비 될수도 있다.