item 1 dodo4513 - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

μ•„μ΄ν…œ1 μƒμ„±μž λŒ€μ‹  정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό κ³ λ €ν•˜λΌ.

  • 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μ–»λŠ” 정톡적인 μˆ˜λ‹¨μ€ public μƒμ„±μžμ΄λ‹€. ν•˜μ§€λ§Œ κΌ­ μ•Œμ•„λ‘¬μ•Όν•  기법이 ν•˜λ‚˜ 더 μžˆλŠ”λ° λ°”λ‘œ μ•„λž˜μ™€ 같이 static factory methodλ₯Ό μ œκ³΅ν•˜λŠ” 것이닀.
public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

νŒ©ν„°λ¦¬ λ©”μ„œλ“œκ°€ μƒμ„±μžλ³΄λ‹€ 쒋은 이유

첫 번째, 이름을 κ°€μ§ˆ 수 μžˆλ‹€.

  • μƒμ„±μžμ— λ„˜κΈ°λŠ” λ§€κ°œλ³€μˆ˜μ™€ μƒμ„±μž 자체 λ§ŒμœΌλ‘œλŠ” λ°˜ν™˜λ  객체의 νŠΉμ„±μ„ μ œλŒ€λ‘œ μ„€λͺ…ν•˜μ§€ λͺ»ν•œλ‹€. 반면 static factory methodλŠ” μ΄λ¦„λ§Œ 잘 μ§€μœΌλ©΄ λ°˜ν™˜λ  객체의 νŠΉμ„±μ„ μ‰½κ²Œ λ¬˜μ‚¬ν•  수 μžˆλ‹€.
  • μ˜ˆμ»¨λŒ€ μƒμ„±μžμΈ BigInteger(int, int, Random)κ³Ό 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œμΈ BigInteger.probablePrime 쀑 μ–΄λŠ μͺ½μ΄ β€˜κ°’μ΄ μ†Œμˆ˜μΈ BigIntegerλ₯Ό λ°˜ν™˜ν•œλ‹€β€™λŠ” 의미λ₯Ό 더 잘 μ„€λͺ…ν•  것 같은지 생각해 보라.
  • ν΄λž˜μŠ€μ— μ‹œκ·Έλ‹ˆμ²˜κ°€ 같은 μƒμ„±μžκ°€ μ—¬λŸ¬ 개 ν•„μš”ν•  것 κ°™μœΌλ©΄, μƒμ„±μžλ₯Ό 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ‘œ λ°”κΎΈκ³  각각의 차이λ₯Ό 잘 λ“œλŸ¬λ‚΄λŠ” 이름을 μ§€μ–΄μ£Όμž.

두 번째, 호좜될 λ•Œλ§ˆλ‹€ μΈμŠ€ν„΄μŠ€λ₯Ό μƒˆλ‘œ μƒμ„±ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

  • 이 덕뢄에 λΆˆλ³€ ν΄λž˜μŠ€λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 미리 λ§Œλ“€μ–΄ λ†“κ±°λ‚˜ μƒˆλ‘œ μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€λ₯Ό μΊμ‹±ν•˜μ—¬ μž¬ν™œμš©ν•˜λŠ” μ‹μœΌλ‘œ λΆˆν•„μš”ν•œ 객체 생성을 ν”Όν•  수 μžˆλ‹€.
  • λŒ€ν‘œμ  예인 Boolean.valueOf(boolean) λ©”μ„œλ“œλŠ” 객체λ₯Ό μ•„μ˜ˆ μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ (특히 생성 λΉ„μš©μ΄ 큰) 같은 객체가 자주 μš”μ²­λ˜λŠ” 상황이라면 μ„±λŠ₯을 μƒλ‹Ήνžˆ λŒμ–΄μ˜¬λ € μ€€λ‹€. ν”ŒλΌμ΄μ›¨μ΄νŠΈ νŒ¨ν„΄λ„ 이와 λΉ„μŠ·ν•œ 기법이라 ν•  수 μžˆλ‹€.

μ„Έ 번째, λ°˜ν™˜ νƒ€μž…μ˜ ν•˜μœ„ νƒ€μž… 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλŠ” λŠ₯λ ₯이 μžˆλ‹€.

  • λ°˜ν™˜ν•  객체의 클래슀λ₯Ό 자유둭게 선택할 수 있게 ν•˜λŠ” μ—„μ²­λ‚œ μœ μ—°μ„±μ„ μ„ λ¬Όν•œλ‹€.
  • APIλ₯Ό λ§Œλ“€ λ•Œ 이 μœ μ—°μ„±μ„ μ‘μš©ν•˜λ©΄ κ΅¬ν˜„ 클래슀λ₯Ό κ³΅κ°œν•˜μ§€ μ•Šκ³ λ„ κ·Έ 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆμ–΄ APIλ₯Ό μž‘κ²Œ μœ μ§€ν•  수 μžˆλ‹€. μ΄λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œμ˜ λ°˜ν™˜ νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€ 기반 ν”„λ ˆμž„μ›Œν¬λ₯Ό λ§Œλ“œλŠ” 핡심 κΈ°μˆ μ΄κΈ°λ„ ν•˜λ‹€.

λ„€ 번째, μž…λ ₯ λ§€κ°œλ³€μˆ˜μ— 따라 맀번 λ‹€λ₯Έ 클래슀의 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλ‹€.

  • λ°˜ν™˜ νƒ€μž…μ˜ ν•˜μœ„ νƒ€μž…μ΄κΈ°λ§Œ ν•˜λ©΄ μ–΄λ–€ 클래슀의 객체λ₯Ό λ°˜ν™˜ν•˜λ“  상관없닀. ν΄λΌμ΄μ–ΈνŠΈλŠ” νŒ©ν„°λ¦¬κ°€ κ±΄λ„€μ£ΌλŠ” 객체가 μ–΄λŠ 클래슀의 μΈμŠ€ν„΄μŠ€μΈμ§€ μ•Œ μˆ˜λ„ μ—†κ³  μ•Œ ν•„μš”λ„ μ—†λ‹€. ν•˜μœ„ 클래슀이기만 ν•˜λ©΄ λ˜λŠ” 것이닀.

λ‹€μ„― 번째, 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•˜λŠ” μ‹œμ μ—λŠ” λ°˜ν™˜ν•  객체의 ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

  • 이런 μœ μ—°ν•¨μ€ μ„œλΉ„μŠ€ 제곡자 ν”„λ ˆμž„μ›Œν¬(service provider framework)λ₯Ό λ§Œλ“œλŠ” 근간이 λœλ‹€.
  • λŒ€ν‘œμ μΈ μ„œλΉ„μŠ€ 제곡자 ν”„λ ˆμž„μ›Œν¬λ‘œλŠ” JDBC(Java Database Connectivity)κ°€ μžˆλ‹€. μ„œλΉ„μŠ€ 제곡자 ν”„λ ˆμž„μ›Œν¬μ—μ„œμ˜ 제곡자(provider)λŠ” μ„œλΉ„μŠ€μ˜ κ΅¬ν˜„μ²΄λ‹€. 그리고 이 κ΅¬ν˜„μ²΄λ“€μ„ ν΄λΌμ΄μ–ΈνŠΈμ— μ œκ³΅ν•˜λŠ” 역할을 ν”„λ ˆμž„μ›Œν¬κ°€ ν†΅μ œν•˜μ—¬, ν΄λΌμ΄μ–ΈνŠΈλ₯Ό κ΅¬ν˜„μ²΄λ‘œλΆ€ν„° 뢄리해쀀닀.

νŒ©ν„°λ¦¬ λ©”μ„œλ“œμ˜ 단점

첫 번째, 상속을 ν•˜λ €λ©΄ publicμ΄λ‚˜ protected μƒμ„±μžκ°€ ν•„μš”ν•˜λ‹ˆ 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ§Œ μ œκ³΅ν•˜λ©΄ ν•˜μœ„ 클래슀λ₯Ό λ§Œλ“€ 수 μ—†λ‹€.

  • μ•žμ„œ μ΄μ•ΌκΈ°ν•œ μ»¬λ ‰μ…˜ ν”„λ ˆμž„μ›Œν¬μ˜ μœ ν‹Έλ¦¬ν‹° κ΅¬ν˜„ ν΄λž˜μŠ€λ“€μ€ 상속할 수 μ—†λ‹€λŠ” 이야기닀. μ–΄μ°Œ 보면 이 μ œμ•½μ€ 상속보닀 μ»΄ν¬μ§€μ…˜μ„ μ‚¬μš©ν•˜λ„λ‘ μœ λ„ν•˜κ³  λΆˆλ³€ νƒ€μž…μœΌλ‘œ λ§Œλ“€λ €λ©΄ 이 μ œμ•½μ„ μ§€μΌœμ•Ό ν•œλ‹€λŠ” μ μ—μ„œ 였히렀 μž₯점으둜 받아듀일 μˆ˜λ„ μžˆλ‹€.

두 번째, 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλŠ” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ°ΎκΈ° μ–΄λ ΅λ‹€.

  • μƒμ„±μžμ²˜λŸΌ API μ„€λͺ…에 λͺ…ν™•νžˆ λ“œλŸ¬λ‚˜μ§€ μ•ŠμœΌλ‹ˆ μ‚¬μš©μžλŠ” 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œ 방식 클래슀λ₯Ό μΈμŠ€ν„΄μŠ€ν™”ν•  방법을 μ•Œμ•„λ‚΄μ•Ό ν•œλ‹€.

ν”νžˆ μ‚¬μš©λ˜λŠ” λͺ…λͺ… 방식듀

  • from: λ§€κ°œλ³€μˆ˜λ₯Ό ν•˜λ‚˜ λ°›μ•„μ„œ ν•΄λ‹Ή νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ” ν˜•λ³€ν™˜ λ©”μ„œλ“œ
Date d = Date.from(instant);
  • of: μ—¬λŸ¬ λ§€κ°œλ³€μˆ˜λ₯Ό λ°›μ•„ μ ν•©ν•œ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ” 집계 λ©”μ„œλ“œ
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
  • valueOf: fromκ³Ό of의 더 μžμ„Έν•œ 버전
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
  • instance ν˜Ήμ€ getInstance: (λ§€κ°œλ³€μˆ˜λ₯Ό λ°›λŠ”λ‹€λ©΄) λ§€κ°œλ³€μˆ˜λ‘œ λͺ…μ‹œν•œ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜μ§€λ§Œ, 같은 μΈμŠ€ν„΄μŠ€μž„μ„ 보μž₯ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€.
StackWalker luke = StackWalker.getInstance(options);
  • create ν˜Ήμ€ newInstance: instance ν˜Ήμ€ getInstance와 κ°™μ§€λ§Œ, 맀번 μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό 생성해 λ°˜ν™˜ν•¨μ„ 보μž₯ν•œλ‹€.
Object newArray = Array.newInstance(classObject, arrayLen);
  • getType: getInstance와 κ°™μœΌλ‚˜, 생성할 ν΄λž˜μŠ€κ°€ μ•„λ‹Œ λ‹€λ₯Έ ν΄λž˜μŠ€μ— νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•  λ•Œ μ“΄λ‹€. β€œType”은 νŒ©ν„°λ¦¬ λ©”μ„œλ“œκ°€ λ°˜ν™˜ν•  객체의 νƒ€μž…μ΄λ‹€.
FileStore fs = Files.getFileStore(path)
  • newType: newInstance와 κ°™μœΌλ‚˜, 생성할 ν΄λž˜μŠ€κ°€ μ•„λ‹Œ λ‹€λ₯Έ ν΄λž˜μŠ€μ— νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•  λ•Œ μ“΄λ‹€. β€œType”은 νŒ©ν„°λ¦¬ λ©”μ„œλ“œκ°€ λ°˜ν™˜ν•  객체의 νƒ€μž…μ΄λ‹€.
BufferedReader br = Files.newBufferedReader(path);
  • type: getTypeκ³Ό newType의 κ°„κ²°ν•œ 버전
List<Complaint> litany = Collections.list(legacyLitany);

핡심정리

정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œμ™€ public μƒμ„±μžλŠ” 각자의 μ“°μž„μƒˆκ°€ μžˆμœΌλ‹ˆ μƒλŒ€μ μΈ μž₯단점을 μ΄ν•΄ν•˜κ³  μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€. κ·Έλ ‡λ‹€κ³  ν•˜λ”λΌλ„ 정적 νŒ©ν„°λ¦¬λ₯Ό μ‚¬μš©ν•˜λŠ” 게 μœ λ¦¬ν•œ κ²½μš°κ°€ 더 λ§ŽμœΌλ―€λ‘œ λ¬΄μž‘μ • public μƒμ„±μžλ₯Ό μ œκ³΅ν•˜λ˜ μŠ΅κ΄€μ΄ μžˆλ‹€λ©΄ 고치자.

끝

이름을 잘만 μ§“λŠ”λ‹€λ©΄ public new 보닀 훨씬 더 가독성 쒋은 μ½”λ“œλ₯Ό λ§Œλ“€μ–΄ λ‚Ό 수 μžˆλŠ” 방법이라 μƒκ°λœλ‹€. λ‹€μ–‘ν•œ λͺ…λͺ… 방식 κ΄€λ‘€λ₯Ό λˆˆμ— μ΅ν˜€λ‘¬μ•Όμ§€.

⚠️ **GitHub.com Fallback** ⚠️