[Effective Java] Item 3. private μμ±μλ enum νμ μΌλ‘ μ±κΈν€μμ 보μ₯νμ.
μ±κΈν€μ΄λ?
μ±κΈν€μ΄λ μΈμ€ν΄μ€λ₯Ό λ¨ 1κ°λ§ μμ±ν μ μλ ν΄λμ€λ₯Ό λ§ν©λλ€.
ex) 무μν κ°μ²΄, μ€κ³ μ μ μΌν΄μΌ νλ μμ€ν μ»΄ν¬λνΈ (service, repository)
μ±κΈν€ μ₯μ
- ν λ²μ κ°μ²΄ μμ±μΌλ‘ μ¬μ¬μ©μ΄ κ°λ₯νκΈ° λλ¬Έμ, λ©λͺ¨λ¦¬ λλΉλ₯Ό μ€μΌ μ μμ΅λλ€.
- μ±κΈν€μΌλ‘ μμ±λ κ°μ²΄λ μ μμ±μ λκΈ° λλ¬Έμ λ€λ₯Έ κ°μ²΄μ 곡μ κ° μ©μ΄ν©λλ€.
μ±κΈν€ λ¨μ
- ν΄λΌμ΄μΈνΈλ₯Ό ν μ€νΈνκΈ° μ΄λ ΅μ΅λλ€.
- private μμ±μλ₯Ό κ°μ§κ³ μκΈ° λλ¬Έμ μμμ΄ λΆκ°λ₯ν©λλ€.
- μλ²μμ ν΄λμ€ λ‘λλ₯Ό μ΄λ»κ² ꡬμ±νκ³ μλμ§μ λ°λΌ λλ μ¬λ¬ κ°μ JVMμ λΆμ°λμ΄ μλ κ²½μ° μ±κΈν€ ν΄λμ€μ¬λ νλ μ΄μμ μΈμ€ν΄μ€κ° λ§λ€μ΄μ§ μ μμ΅λλ€.
- μ μ μνλ‘ μ¬μ©ν μ μκΈ° λλ¬Έμ λ°λμ§νμ§ λͺ»ν©λλ€.
- μ¬μ€ μ무 κ°μ²΄λ μμ λ‘κ² μ κ·Όνκ³ μμ νκ³ κ³΅μ ν μ μλ μ μ μνλ₯Ό κ°λ κ²μ κ°μ²΄ μ§ν₯ νλ‘κ·Έλ¨μ΄μμλ κΆμ₯λμ§ μμ΅λλ€.
μ±κΈν€ λ§λλ λ°©μ 1 - public static final
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis(){}
}
class ElvisTest {
@Test
void singleToneTest() {
Elvis elvis = Elvis.INSTANCE;
Elvis elvis2 = Elvis.INSTANCE;
assertEquals(elvis, elvis2);
}
}
- 첫 λ²μ§Έ λ°©λ²μ, ν΄λμ€ λ΄λΆμ public static λ©€λ²λ₯Ό νλ μμ±ν΄ λκ³ finalλ‘ μ€μ νμ¬ μ±κΈν€μΌλ‘ κ΄λ¦¬νλ λ°©λ²μ
λλ€.
- μ¬κΈ°μ private μμ±μλ public static final νλμΈ Elvis.INSTANCEλ₯Ό μ΄κΈ°ν ν λ λ± ν λ² νΈμΆλ©λλ€.
- publicμ΄λ protected μμ±μκ° μμΌλ―λ‘ λ€λ₯Έ ν¨ν€μ§μμ μμ±ν μ μμμ 보μ₯ν΄μ£Όλ©°, μ΄κΈ°ν ν λ λ± ν λ² νΈμΆν¨μΌλ‘μ¨ μΈμ€ν΄μ€κ° μ 체 μμ€ν μμ νλ λΏμμ΄ λ³΄μ₯λ©λλ€.
- μ΄ λ°©μμ ν΄λΉ ν΄λμ€κ° μ±κΈν€μμ νμ€ν λλ¬λ΄κ³ , κ°κ²°νλ€λ κ²μ΄ μ₯μ
μμΈ μΌμ΄μ€ : μλ μ½λμ κ°μ΄ 리νλ μ API ( AccessibleObject.setAccessible)μ μ¬μ©ν΄ private μμ±μλ₯Ό νΈμΆνλ λ°©λ²
@Test
void reflectionBreakSingleton()
throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Elvis elvis = Elvis.INSTANCE;
Constructor<Elvis> constructor = (Constructor<Elvis>) elvis.getClass().getDeclaredConstructor();
constructor.setAccessible(true);
Elvis elvis2 = constructor.newInstance();
assertNotSame(elvis, elvis2);
}
- μ΄λ° 곡격μ λ§κΈ° μν΄, μμ±μλ₯Ό μμ νμ¬ λ λ²μ§Έ κ°μ²΄κ° μμ±λλ € ν λ μμΈλ₯Ό λμ§μΌλ‘μ¨ λ§μ μ μκ² μ΅λλ€.
public class Presley {
public static final Presley INSTANCE = new Presley();
private Presley() {
if (INSTANCE != null) {
throw new RuntimeException("μμ±μλ₯Ό νΈμΆν μ μμ΅λλ€.");
}
}
}
μ±κΈν€ λ§λλ λ°©μ 2 - μ μ ν©ν 리 λ©μλλ₯Ό public static λ©€λ²λ‘ μ 곡νκΈ°
public class Greenday {
private static final Greenday INSTANCE = new Greenday();
private Greenday() {}
public static Greenday getInstance() {
return INSTANCE;
}
}
class GreendayTest {
@Test
void singletonTest() {
Greenday greenday1 = Greenday.getInstance();
Greenday greenday2 = Greenday.getInstance();
assertEquals(greenday1, greenday2);
}
}
- λ λ²μ§Έ λ°©λ²μ 첫 λ²μ§Έ λ°©μμ μ±κΈν€ κ°μ²΄λ₯Ό κ°μ Έμ€λ λ°©μμ μ μ ν©ν 리 λ©μλ λ°©μμΌλ‘ μ μν λ°©μμ λλ€.
- μ΄ λ°©μμ μ₯μ μ μ±κΈν€ λ°©μμ νκ³ μΆμ λ APIλ₯Ό λ°κΎΈμ§ μκ³ λ λ³κ²½ν μ μλ€λ μ μ
λλ€.
- μλ μ½λμ²λΌ λ΄λΆμμ INSTANCEκ° μλ μ μΈμ€ν΄μ€λ₯Ό μμ±ν΄μ£Όλ©΄ λκ² μ΅λλ€.
public class Greenday {
private static final Greenday INSTANCE = new Greenday();
private Greenday() {}
public static Greenday getInstance() {
return new Greenday();
}
}
class GreendayTest {
@Test
void singletonTest() {
Greenday greenday1 = Greenday.getInstance();
Greenday greenday2 = Greenday.getInstance();
assertNotEquals(greenday1, greenday2);
}
}
- λ λ²μ§Έ μ₯μ μ μνλ€λ©΄ μ μ ν©ν 리λ₯Ό μ±κΈν€ ν©ν λ¦¬λ‘ λ§λ€ μ μλ€λ μ μ λλ€. (Item 30 μ°Έκ³ )
- μ μ ν©ν 리μ λ©μλ μ°Έμ‘°λ₯Ό 곡κΈμλ‘ μ¬μ©ν μ μμ΅λλ€. (Item 43, Itme 44 μ°Έκ³ )
- Greenday::getInstanceλ₯Ό Supplier<Greenday>λ‘ μ¬μ©ν΄μ μλμ²λΌ μ¬μ©ν μ μμ
Supplier<Greenday> greendaySupplier = Greenday::getInstance;
Greenday greenday = greendaySupplier.get();
μ λκ°μ§ λ°©μμ λ¬Έμ μ
μ λ κ°μ§ λ°©μμ λ¬Έμ μ μ κ° ν΄λμ€λ₯Ό μ§λ ¬ν(κ°μ²΄λ₯Ό μ μ₯, μ μ‘ν μ μλ νΉμ ν¬λ§·μΌλ‘ λ³ννλ κ³Όμ )ν ν μμ§λ ¬ν(νΉμ ν¬λ§· μνμ λ°μ΄ν°λ₯Ό λ€μ κ°μ²΄λ‘ λ³ν)ν λ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό λ°ννλ€λ μ μ λλ€.
- μμ§λ ¬νλ κΈ°λ³Έ μμ±μλ₯Ό νΈμΆνμ§ μκ³ μΈμ€ν΄μ€μ κ°μ 볡μ¬ν΄μ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό λ°νν©λλ€.
μ΄λ₯Ό λ°©μ§νκΈ° μν΄ readResolve λ©μλλ₯Ό νλ λ§λ€μ΄ μ±κΈν€ μΈμ€ν΄μ€λ₯Ό λ°ννκ³ , λͺ¨λ νλμ transient ν€μλλ₯Ό λ£μ΄μ£Όλ λ°©μμ΄ μμ΅λλ€.
transient ν€μλ : νλμ μνκ°μ μ μ‘νμ§ μλλ€λ ν€μλ
public class Greenday {
// transient private static final Greenday INSTANCE = new Greenday();
private static final Greenday INSTANCE = new Greenday();
private Greenday() {}
public static Greenday getInstance() {
return INSTANCE;
}
private Greenday readResolve() {
// 'μ§μ§' Greendayλ₯Ό 리ν΄νκ³ , κ°μ§ Greendayλ κ°λΉμ§ 컬λ ν°μ λ§‘κΈ΄λ€.
return INSTANCE;
}
}
- readResolve λ©μλλ μμ§λ ¬ν κ³Όμ μμ λ°λμ νΈμΆλ©λλ€.
- μ΄λ κ² μ€μ νλ©΄ μμ§λ ¬ν κ³Όμ μμ μ±κΈν€μΌλ‘ λ§λ€μ΄λ μ§μ§ μΈμ€ν΄μ€λ₯Ό λ°ννλλ‘ μ€μ λμ΄, κ°μ 볡μ¬ν μλ‘μ΄ μΈμ€ν΄μ€λ κ°λΉμ§ 컬λ ν°λ‘ λμ΄κ°κ² λ©λλ€.
- λ°©μ΄μ μΌλ‘ transient ν€μλλ₯Ό λ£μ΄ μ§λ ¬ν κ³Όμ μμ νλμ μνκ° μ μ‘μ λ§μ μμ§λ ¬ν κ³Όμ μμ 볡μ¬ν κ° μ체λ₯Ό μμ 보λ΄μ§ μλλ‘ μ€μ ν μλ μκ² μ΅λλ€.
μ±κΈν€ λ§λλ λ°©μ 3 - enum νμ
public enum ColdBrew {
INSTANCE;
}
- μΈ λ²μ§Έ λ°©λ²μ enumνμ
μΌλ‘ μ±κΈν€μ μ μ©νλ λ°©λ²μΌλ‘ ,public νλ λ°©μκ³Ό λΉμ·νμ§λ§, ν¨μ¬ κ°κ²°νκ² μ¬μ©ν μ μλ λ°©μμΌλ‘, 볡μ‘ν μ§λ ¬ν μν©μ΄λ 리νλ μ
곡격μμλ μ 2μ μΈμ€ν΄μ€κ° μκΈ°λ μΌμ μλ²½ν λ§μμ€λλ€.
- μ΄κ±°ν νμ μΌλ‘ μ±κΈν€μ μ μ©νλ κ²μ΄ μ‘°κΈ μ΄μν μ μμ§λ§, λλΆλΆ μν©μμλ μμκ° νλλΏμΈ μ΄κ±° νλΉμ΄ μ±κΈν€μ λ§λλ κ°μ₯ μ’μ λ°©λ²μ λλ€.
- λ§λλ €λ μ±κΈν€μ΄ enumμΈμ ν΄λμ€λ₯Ό μμν΄μΌ νλ€λ©΄ μ΄ λ°©λ²μ μ¬μ©ν μ μμ΅λλ€. (μΈν°νμ΄μ€λ ꡬννλλ‘ μ μΈν μλ μμ)
- public enum ColdBrew extends ~ (X), public enum ColdBrew implements ~ (O)
<μ°Έκ³ μλ£>
[μ΄νν°λΈ μλ°] μμ΄ν 3. private μμ±μλ μ΄κ±° νμ μΌλ‘ μ±κΈν΄μμ 보μ¦νλΌ
μ±κΈν΄: μΈμ€ν΄μ€λ₯Ό μ€μ§ νλλ§ μμ±ν μ μλ ν΄λμ€ex) ν¨μ(무μν κ°μ²΄), μ€κ³μ μ μΌν΄μΌ νλ μμ€ν μ»΄ν¬λνΈprivate μμ±μλ₯Ό κ°μ§κ³ μκΈ° λλ¬Έμ μμν μ μλ€.private μμ±μλ μ€μ§ μ±
velog.io
[Java] μ§λ ¬ν(Serialization)μ μμ§λ ¬ν(Deserialization)λ? transient λ³μλ?
μ§λ ¬ν(Serializaion)λ? μμ§λ ¬ν(Deserialization)λ? μ§λ ¬νλ κ°μ²΄λ₯Ό μ μ₯ κ°λ₯ν μν(μλ₯Ό λ€μ΄ λμ€ν¬μ νμΌ νν λ±) νΉμ μ μ‘ κ°λ₯ν μν(λ€νΈμν¬ μμ λ°μ΄ν° μ€νΈλ¦Ό νν)λ‘ λ³ννλ κ²μ
code-lab1.tistory.com
[μμ΄ν 3] transientκ° μμ§λ ¬νμ μλ‘μ΄ μΈμ€ν΄μ€ μμ±μ λ°©μ§νλ μ΄μ · Issue #4 · Java-Bom/ReadingR
24p ν΄λμ€μ μΈμ€ν΄μ€ νλλ₯Ό transientλ‘ μ μΈνκ³ readResolve λ©μλλ₯Ό μ 곡ν΄μΌ νλ€. transientκ° μ§λ ¬νμ μ μΈμμΌμ£Όλ 건 μκ² λλ°, μ΄κ² μ μΈμ€ν΄μ€λ₯Ό μλ‘ μμ±νμ§ μλλ€λκ±Έ 보μ₯νλμ§
github.com