๋ถ๋ณ ๊ฐ์ฒด (Immutable Class)๋?
๋ถ๋ณ ๊ฐ์ฒด๋ ๋ง ๊ทธ๋๋ก ๋ณ๊ฒฝ์ด ๋ถ๊ฐ๋ฅํ ๊ฐ์ฒด์ด๋ค.
๊ฐ์ฒด๋ฅผ ์์ฑ ํ ์ธ๋ถ์ ์ํด ๊ทธ ์ํ๋ฅผ ๋ฐ๊ฟ ์ ์๋ค.
์ฌ๊ธฐ์ ๋ฐ๊ฟ ์ ์๋ค๋ ๊ฒ์ heap ์์ญ์์ ๊ทธ ๊ฐ์ฒด๊ฐ ๊ฐ๋ฆฌํค๊ณ ์๋
๋ฐ์ดํฐ ์์ฒด์ ๋ณํ๊ฐ ๋ถ๊ฐ๋ฅ ํจ์ ์๋ฏธํ๋ฉฐ stack์ ์๋ ์ฃผ์๊ฐ์ ๋ค๋ฅธ ์ฃผ์๊ฐ์ ๊ฐ๋ฆฌํค๋๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ ๋ฌธ์ ์๋ค.
โ ์ฌ๊ธฐ์ ๋งํ๋ heap ์์ญ์ด๋ ๋ฌด์์ธ๊ฐ?
๊ฐ๋จํ๊ฒ ๋งํด ์์ํ์
(int, boolean ๋ฑ)์ ๊ทธ๋๋ก stack ์์ญ์ ์ฌ๋ผ๊ฐ์ง๋ง,
์ฐธ์กฐ๋ณ์๋ฅผ ๊ฐ์ง๊ณ ์๋ ํ์
(Object, Array ๋ฑ)์ ๊ทธ ์ค์ ๋ฐ์ดํฐ๋ค์ heap ์์ญ์ ์ ์ฅํ๊ณ ์ด ์ฃผ์๊ฐ์ Stack ์์ญ์ ๊ฐ์ง๊ณ ์๋ค.
์์๋ก String name = "amazzi";
์์ name = "newwisdom";
์ผ๋ก
name์ด ๊ฐ๋ฆฌํค๋ ์ฃผ์์ ๋ณ๊ฒฝ์ ๊ฐ๋ฅํ๋ค.
์ฌ๊ธฐ์ String์ ๋ถ๋ณ ๊ฐ์ฒด๋ก name์ ๊ฐ์ ๋ฐ๊ฟ์ค ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ์ค์ ๋ก๋
String ๊ฐ์ฒด์ "newwisdom"
์ ์ธ์คํด์ค ๋ณ์๋ก ๊ฐ์ง๊ณ ์๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ณ ์๋ ๊ฒ์ด๋ค.
์ฆ name์ด ์ฒ์์ ์ฐธ์กฐํ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋๋๊ฒ ์๋ ์์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ
์ด๋ฅผ name์ด ์ฐธ์กฐํ๊ณ ์๋ ๊ฒ์ด๋ค.
๋ถ๋ณ ๊ฐ์ฒด์ ํน์ง
์ฅ์
- ์์ฑ์, ์ ๊ทผ ๋ฉ์๋์ ๋ํ ๋ฐฉ์ด์ ๋ณต์ฌ๊ฐ ํ์์๋ค.
- ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์ด๋ผ๋ฉด ๋๊ธฐํ ์ฒ๋ฆฌ ์์ด ๊ฐ์ฒด๋ฅผ ๊ณต์ ํ ์ ์๋ค.
- ๋ถ๋ณ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด๋ฅผ ์ ๋ขฐํ ์ ์๋ค.
๋จ์
- ๊ฐ์ฒด๊ฐ ๊ฐ์ง๋ ๊ฐ๋ง๋ค ์๋ก์ด ์ธ์คํด์ค๋ฅผ ์์ฑํด์ผํ๋ค.
๊ทผ๋ฐ ์์ ์๊ฐ์์ ์ ์ด์จ์ด ๋งํ๊ธฐ๋ฅผ Oracle ๊ณต์ ๋ฌธ์์๋ โ๋ถ๋ณ ๊ฐ์ฒด๋ ์ฌ๋ฌ๋ถ์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฑฑ์ ํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ํฐ ์ด์ต์ ๊ฐ์ ธ์ต๋๋ค.โ ์ด๋ฐ ๋์์ค์ ๋ฌธ์ฅ์ด ์๋ค๊ณ ํ๋ค.
์ฌ๋ฌ ํ์ ์์์ ๋ถ๋ณ
์์ ํ์ ๋ง ์๋ ๊ฒฝ์ฐ์์ ๋ถ๋ณ
์์ ํ์
์์์ ๋ถ๋ณ์ ์ฝ๋ค.
์์ ํ์
์ ์ฐธ์กฐ ๊ฐ์ด ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ ๊ทธ๋๋ก ์ธ๋ถ์ ๋ด๋ณด๋ด๋ ๋ด๋ถ ๊ฐ์ฒด๋ ๋ถ๋ณ์ด๋ค.
Example
class Person {
private final int age;
private final int name;
public Person(int age, int name) {
this.age = age;
this.name = name;
}
}
์ธ์คํด์ค ๋ณ์๋ค์ด final
๋ก ์ ์ธ๋์๊ธฐ ๋๋ฌธ์ ์ธ์คํด์ค ๊ฐ์ ๋ณ๊ฒฝ์ด ๋ถ๊ฐ๋ฅํ๋ค.
๋ฐ๋ผ์ setter ๋ฉ์๋๋ ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ๋ค.
์ด ๊ฐ์ฒด์ ์ธ์คํด์ค ๋ณ์๋ค์ ๊ฐ์ ๋ณ๊ฒฝํ๋ ค๋ฉด ์๋ก์ด ์ธ์คํด์ค๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ ๋ฟ์ด๋ค.
์ฐธ์กฐ ํ์ ์ด ์๋ ๊ฒฝ์ฐ์์ ๋ถ๋ณ
โ์์ ํ์
๋ง ์๋ ๊ฒฝ์ฐ ์ฒ๋ผ ๋จ์ํ final
์ ๋ถ์ด๊ณ setter ๋ฉ์๋๋ง ์์ฌ์ฉํ๋ฉด ๋์ง ์์?โ๋ผ๋
์ง๋ฌธ์ ๋ํ ๋๋ต์ ์๋์ ๊ฐ์ ์์๋ฅผ ๋ณด๋ฉด ๋๋ค.
public class Car {
private final Position position;
public Car(final Position position) {
this.position = position;
}
public Position getPosition() {
return position;
}
}
public class Position {
private int value;
public Position(final int value) {
this.value = value;
}
public void setValue(final int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
์ฌ๊ธฐ์ Car๋ ๋ถ๋ณ ๊ฐ์ฒด์ธ๊ฐ?
์๋๋ค.
Car๋ final์ ์ฌ์ฉํ๊ณ , setter๊ฐ ์์ง๋ง ์ฐ๋ฆฌ๋ Car์ position์ ๋ณ๊ฒฝํ ์ ์๋ค.
public static void main(String[] args) {
Position position = new Position(1);
Car car = new Car(position);
System.out.println(car.getPosition().getValue());
// 1
car.getPosition().setValue(10);
System.out.println(car.getPosition().getValue());
// 10
}
๋ถ๋ณ ๊ฐ์ฒด๋ผ๊ณ ์๊ฐํ๋ Car ๋ด๋ถ์ ์ฐธ์กฐ๋ณ์ Position์ ๋ถ๋ณ ๊ฐ์ฒด๊ฐ ์๋์๊ธฐ ๋๋ฌธ์
Car ๋ํ ๋ถ๋ณ ๊ฐ์ฒด๊ฐ ๋ ์ ์์๋ค.
์ฆ, ๋ถ๋ณ ๊ฐ์ฒด์ ์ฐธ์กฐ ๋ณ์ ๋ํ ๋ถ๋ณ, ๋ถ๋ณ ๊ฐ์ฒด์ฌ์ผ ํ๋ค.
์ฐธ์กฐ ๋ณ์๊ฐ ์ผ๋ฐ ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ
์ ์์ ์์ ์ฐธ์กฐ ๋ณ์์ธ Position๋ ๋ถ๋ณ ๊ฐ์ฒด๋ก ๋ง๋ ๋ค.
public class Car {
private final Position position;
public Car(final Position position) {
this.position = position;
}
public Position getPosition() {
return position;
}
}
public class Position {
private final int value;
public Position(final int value) {
this.value = value;
}
public void setValue(final int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
์ฐธ์กฐ ๋ณ์๊ฐ List์ผ ๊ฒฝ์ฐ
์ฐธ์กฐ๋ณ์๊ฐ List์ผ ๊ฒฝ์ฐ๋ List์ ๋ด๊ณ ์๋ ๊ฐ์ฒด๊ฐ ๋ถ๋ณ ๊ฐ์ฒด์ฌ๋ ์ฃผ์ํด์ผํ๋ค.
์ด ๊ฒฝ์ฐ๋ ๋ค์๊ณผ ๊ฐ์ ์กฐ๊ฑด์ ๋ง์กฑ ์์ผ์ผ ํ๋ค.
์์ฑ ์ ์์ฑ ์ธ์๋ฅผ ๊ทธ๋๋ก ์ฐธ์กฐํ์ง ์์์ผ ํ๋ค. (new ArrayList<>())
์์ฑ๋ ๋ ์ธ์๋ก ๋์ด์จ List๋ฅผ ์ธ๋ถ์์ ๋ณ๊ฒฝํ๋ฉด List๋ฅผ ๊ฐ์ง ๊ฐ์ฒด์ ๋ด๋ถ ์ธ์คํด์ค ๋ํ ๋ณํ๋ค.
๋๋ฌธ์ ์์ฑ์๋ฅผ ํตํด ๊ฐ์ ์ ๋ฌ ๋ฐ์ ๋ new ArrayList<>()
๋ฅผ ํตํด
์๋ก์ด ๊ฐ์ ์ฐธ์กฐํ๋๋ก ๋ฐฉ์ด์ ๋ณต์ฌ๋ฅผ ๋์
ํด์ผ ํ๋ค.
์ด๋ฌ๋ฉด ์ธ๋ถ์์ ๋๊ฒจ์ฃผ๋ List์ ๊ฐ์ฒด ๋ด๋ถ์ ์ธ์คํด์ค ๋ณ์๊ฐ ์ฐธ์กฐํ๋ ๊ฐ์ด
๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ธ๋ถ์์ ์ ์ด๊ฐ ๋ถ๊ฐ๋ฅํ๋ค.
getter๋ฅผ ํตํด add/remove๊ฐ ๋ถ๊ฐ๋ฅํ๋๋ก Collectiions.unmodifiableList() ๋ฉ์๋๋ฅผ ์ฌ์ฉ
getter๋ฅผ ํตํด List์ ์ฐธ์กฐ๋ณ์๋ฅผ ๊ทธ๋๋ก ๋ด๋ณด๋ด๊ฒ ๋๋ฉด
Collections
์ API๋ฅผ ํตํด ์ด ๊ฐ์ ์ถ๊ฐ/์ญ์ ํ ์ ์๋ค.
๋๋ฌธ์ getter ๋ฉ์๋ ๊ตฌํ ์ ์ด๋ฅผ ํตํด add/remove๊ฐ ๋ถ๊ฐ๋ฅํ๋๋ก
List์ ๊ฐ ๋ณ๊ฒฝ์ ๋ง๋ Collectiions.unmodifiableList()
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
public class Positions {
private final List<Position> positions;
public Positions(final List<Position> positions) {
this.positions = new ArrayList<>(positions);
}
public Position getPosition() {
return Collections.unmodifiableList(position);
}
}