public class Adventurer{
private String name = "새싹";
}
public class Artifact {
public int data;
public Artifact(int data) {
this.data = data;
}
}
public class FakeArtifact extends Artifact {
public FakeArtifact(int data) {
super(data);
}
}
public class TreasureChamber {
private Artifact magicObj = new Artifact(1); // 💎💎💎
public Artifact findArtifact(Adventurer adventurer) {
return artifact;
}
}
public class Labyrinth {
private final TreasureChamber chamber;
public Labyrinth(TreasureChamber chamber) {
this.chamber = chamber;
}
public Artifact navigate(Adventurer adventurer) {
Artifact artifact = chamber.findArtifact(adventurer);
return artifact;
}
}
public class Entrance {
private final Labyrinth labyrinth;
public Entrance(Labyrinth labyrinth) {
this.labyrinth = labyrinth;
}
public Artifact enterDungeon(Adventurer adventurer) {
Artifact artifact = labyrinth.navigate(adventurer);
return artifact;
}
}
public class Main {
public static void main(String[] args) {
// 던전 인스턴스화
TreasureChamber chamber = new TreasureChamber();
Labyrinth labyrinth = new Labyrinth(chamber);
Entrance entrance = new Entrance(labyrinth);
}
}
만든 던전의 입구,미로,보물의 방을 연결해줍니다.
노트
던전을 구성하기 위해 입구,미로,보물의 방을 만들어준다.
public class Main {
public static int UNKOWN_FORCE = 1; // 신비로운 힘
public static void <main(String[] args) {
...
}
}
노트
static으로 선언된 변수와 메서드는 클래스 로딩 시점에 JVM 메모리 영역인 메타스페이스에 저장된다.
public class Labyrinth {
...
public Artifact navigate(Adventurer adventurer) {
...
artifact.data += Main.UNKOWN_FORCE;
...
}
}
public class Entrance {
...
public Artifact enterDungeon(Adventurer adventurer) {
...
artifact.data += Main.UNKOWN_FORCE;
...
}
}
public class TreasureChamber {
...
public Artifact findMagicObject(Adventurer adventurer) {
artifact.data += Main.UNKOWN_FORCE;
...
}
}
public class Main {
public static int UNKOWN_FORCE = 1;
public static void main(String[] args) {
TreasureChamber chamber = new TreasureChamber();
Labyrinth labyrinth = new Labyrinth(chamber);
Entrance entrance = new Entrance(labyrinth);
Adventurer saeSsak = new Adventurer();
Artifact artifact = entrance.enterDungeon(saeSsak);
System.out.println("찾은 유물: " + artifact.data);
}
}
위 코드에서 Artifact
의 데이터가 계속 변경되는데 이 데이터를 어떻게 보호할 수 있을까?
public class TreasureChamber {
private final Artifact artifact = new Artifact(1);
public Artifact findMagicObject(Adventurer adventurer) {
artifact.data += Main.UNKOWN_FORCE;
return artifact;
}
}
final 키워드를 사용해 데이터를 보호하려고 하지만 원하는 결과를 얻지못했다
public class Artifact {
public int data; // <- 변경 가능
public Artifact(int data) {
this.data = data;
}
}
artifact.data += Main.UNKOWN_FORCE; // <- 계속 변경이 일어납니다.
public class Artifact {
public final int data; // <- final 키워드 추가
public Artifact(int data) {
this.data = data;
}
}
객체의 상태를 완전히 불변으로 만들려면, 모든 필드도
final
로 선언하고, 객체가 한 번 생성된 후에는 변경할 수 없도록 해야한다. 예로, MagicObject
의 data
필드를 final
로 선언하면 객체의 불변성을 보장할 수 있다.
public final class Artifact { // final 키워드 추가
public final int data;
public Artifact(int data) {
this.data = data;
}
}
public class FakeArtifact extends Artifact {
public FakeArtifact(int data) {
super(data);
}
}
final
키워드를 클래스 선언에 추가하면, 해당 클래스를 다른 클래스가 상속할 수 없게 된다. 이러한 방식은 클래스의 설계를 고정시키고, 의도치 않은 확장을 방지하여 객체의 일관성을 유지하는 데 유용하다.
노트
왜 final
필드를 생성할까?
1. 메모리 효율성
2. 코드의 안전성
String strA = "hello"; // 리터럴
String strB = new String("hello"); // new 키워드
String strC = new String("hello");
String strD = "hello";
System.out.println(strB==strC);
System.out.println(strA==strD);
노트
B와C는 false 결과값이 나온다
String concat = strA.concat(strB);
System.out.println(concat);