λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

πŸ“šμ½μ€ μ±… 정리/μ΄νŽ™ν‹°λΈŒμžλ°”

[μ΄νŽ™ν‹°λΈŒ μžλ°”] 2μž₯ : 객체 생성과 파괴

2μž₯ 객체 생성과 파괴

객체λ₯Ό ‘λ§Œλ“€μ–΄μ•Ό ν•˜λŠ” μ‹œκΈ°'λ₯Ό κ΅¬λΆ„ν•˜λŠ” 방법

λΆˆν•„μš”ν•œ 생성을 ν”Όν•˜λŠ” 방법

μ œλ•Œ νŒŒκ΄΄λ¨μ„ 보μž₯ν•˜κ³  νŒŒκ΄΄μ „μ— μˆ˜ν–‰ν•΄μ•Όν•  μž‘μ—… 처리 방법

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

ν΄λž˜μŠ€λŠ” μƒμ„±μžμ™€ λ³„λ„λ‘œ 정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•  수 μžˆλ‹€.

정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œ

  1. 이름을 κ°€μ§ˆ 수 μžˆλ‹€. (λ°˜ν™˜ 객체의 νŠΉμ„± μ„€λͺ… κ°€λŠ₯)
  2. 호좜 μ‹œλ§ˆλ‹€ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.
  3. λ°˜ν™˜ νƒ€μž…μ˜ ν•˜μœ„ νƒ€μž… 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλŠ” λŠ₯λ ₯이 μžˆλ‹€.
    1. λ°˜ν™˜ν•  객체의 클래슀λ₯Ό 자유둭게 선택할 수 μžˆλŠ” ‘μœ μ—°μ„±'을 제곡
      1. νŒ©ν† λ¦¬ λ©”μ„œλ“œ 이름에 따라 각기 λ‹€λ₯Έ κΈ°λŠ₯의 κ΅¬ν˜„μ²΄ 생성 κ°€λŠ₯ (λ°˜ν™˜ μ°Έμ‘° κ°μ²΄λŠ” κ°™λ‹€)
    → μ΄λŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œ λ°˜ν™˜ νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•˜λŠ μΈν„°νŽ˜μ΄μŠ€ 기반 ν”„λ ˆμž„μ›Œν¬(μ•„μ΄ν…œ20)을 λ§Œλ“œλŠ” ν•΅μ‹¬κΈ°μˆ 
  4. μž…λ ₯ λ§€κ°œλ³€μˆ˜μ— 따라 맀번 λ‹€λ₯Έ 클래슀의 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆλ‹€.
  5. **정적 νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•˜λŠ” μ‹œμ μ—λŠ” λ°˜ν™˜ν•  객체의 ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€. ****

μ„œλΉ„μŠ€ 제곡자 ν”„λ ˆμž„μ›Œν¬ (JDBC)

μ„œλΉ„μŠ€ 제곡자 ν”„λ ˆμž„μ›Œν¬μ—μ„œ μ„œλΉ„μŠ€μ˜ κ΅¬ν˜„μ²΄μ˜ μ œκ³΅μ„ ν†΅μ œν•˜μ—¬ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό κ΅¬ν˜„μ²΄λ‘œλΆ€ν„° 뢄리해쀀닀.

μ„œλΉ„μŠ€ μΈν„°νŽ˜μ΄μŠ€ : κ΅¬ν˜„μ²΄μ˜ μ •μ˜

제곡자 등둝 API : μ œκ³΅μžκ°€ κ΅¬ν˜„μ²΄λ₯Ό 등둝할 λ•Œ μ‚¬μš©

μ„œλΉ„μŠ€ μ ‘κ·Ό API : μ„œλΉ„μŠ€μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό 얻을 λ•Œ μ‚¬μš©

→ ν΄λΌμ΄μ΄μ–ΈνŠΈλŠ” μ„œλΉ„μŠ€ μ ‘κ·Ό 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와 κ°™μœΌλ‚˜ 생성할 ν΄λž˜μŠ€κ°€ μ•„λ‹Œ λ‹€λ₯Έ ν΄λž˜μŠ€μ— νŽ™ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•  λ•Œ μ“΄λ‹€.
    FileStore fs = Files.getFileStore(path)
  • newType : newInstance 와 κ°™μœΌλ‚˜, 생성할 ν΄λž˜μŠ€κ°€ μ•„λ‹Œ λ‹€λ₯Έ ν΄λž˜μŠ€μ— νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•  λ•Œ μ“΄λ‹€.
    BufferedReader br = Files.newBufferedReader(path)
  • type : getTypeκ³Ό newType의 κ°„κ²°ν•œ 버전
    List<Complaint> litany = Collections.list(legacyLitany)

μ•„μ΄ν…œ 2: μƒμ„±μžμ— λ§€κ°œλ³€μˆ˜κ°€ λ§Žλ‹€λ©΄ λΉŒλ”λ₯Ό 고렀해라

정적 νŒ©ν† λ¦¬μ™€ μƒμ„±μžλŠ” λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ„ λ•Œ 적어야 될게 많고 각각의 λ§€κ°œλ³€μˆ˜ μœ„μΉ˜κ°€ μ–΄λ–€ 값을 μ˜λ―Έν•˜λŠ”μ§€ μ•ŒκΈ° μ–΄λ ΅λ‹€.

λ§€κ°œλ³€μˆ˜κ°€ λ§Žμ•„μ§€λ©΄..

  1. 각 μœ„μΉ˜μ˜ λ§€κ°œλ³€μˆ˜κ°€ μ–΄λ–€ μ˜λ―ΈμΈμ§€ μ•ŒκΈ° μ–΄λ ΅λ‹€.
  2. ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜μ— 따라 μƒμ„±μžλ₯Ό λ‹€ λ”°λ‘œ λ§Œλ“€μ–΄μ€˜μ•Όλ§Œ ν•œλ‹€.

→ ν΄λΌμ΄μ–ΈνŠΈμ˜ μ‹€μˆ˜λ₯Ό μœ λ°œν•˜κ²Œ λœλ‹€.

setter둜 ν•„λ“œλ₯Ό λͺ…ν™•νžˆ ν•˜λ©΄... (μžλ°”λΉˆμ¦ˆνŒ¨ν„΄)

  1. 객체 ν•˜λ‚˜λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄μ„œ λ©”μ„œλ“œλ₯Ό μ—¬λŸ¬κ°œ ν˜ΈμΆœν•΄μ•Όν•˜κ³  λͺ¨λ‘ ν˜ΈμΆœν•˜κΈ° μ „κΉŒμ§€ **‘일관성'**이 λ¬΄λ„ˆμ§„ μƒνƒœκ°€ λœλ‹€.
    1. λΆˆλ³€ 클래슀둜 λ§Œλ“€ 수 μ—†μŒ

λŒ€μ•ˆ ⇒ 점측적 μƒμ„±μž νŒ¨ν„΄ + μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄μ˜ 가독성

[λΉŒν„°νŒ¨ν„΄]

  1. ν΄λΌμ΄μ–ΈνŠΈλŠ” ν•„μš”ν•œ 객체λ₯Ό 직접 λ§Œλ“€μ§€ μ•Šκ³  ν•„μˆ˜ λ§€κ°œλ³€μˆ˜λ§Œμ„ ν˜ΈμΆœν•΄ λΉŒλ” 객체λ₯Ό μ–»λŠ”λ‹€.
  2. λΉŒλ” 객체가 μ œκ³΅ν•˜λŠ” μ„Έν„° λ©”μ„œλ“œλ‘œ μ›ν•˜λŠ” λ§€κ°œλ³€μˆ˜λ₯Ό μ„€μ •ν•œλ‹€.
// μ½”λ“œ 2-3 λΉŒλ” νŒ¨ν„΄ - 점측적 μƒμ„±μž νŒ¨ν„΄κ³Ό μžλ°”λΉˆμ¦ˆ νŒ¨ν„΄μ˜ μž₯점만 μ·¨ν–ˆλ‹€. (17~18μͺ½)
public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    public static class Builder {
        // ν•„μˆ˜ λ§€κ°œλ³€μˆ˜
        private final int servingSize;
        private final int servings;

        // 선택 λ§€κ°œλ³€μˆ˜ - κΈ°λ³Έκ°’μœΌλ‘œ μ΄ˆκΈ°ν™”ν•œλ‹€.
        private int calories      = 0;
        private int fat           = 0;
        private int sodium        = 0;
        private int carbohydrate  = 0;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings    = servings;
        }

        public Builder calories(int val)
        { calories = val;      return this; }
        public Builder fat(int val)
        { fat = val;           return this; }
        public Builder sodium(int val)
        { sodium = val;        return this; }
        public Builder carbohydrate(int val)
        { carbohydrate = val;  return this; }

        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder) {
        servingSize  = builder.servingSize;
        servings     = builder.servings;
        calories     = builder.calories;
        fat          = builder.fat;
        sodium       = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }

    public static void main(String[] args) {
        NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
                .calories(100).sodium(35).carbohydrate(27).build();
    }
}

이 ν΄λž˜μŠ€λŠ” λΆˆλ³€μ΄λ©°, λΉŒλ”μ˜ μ„Έν„° λ©”μ„œλ“œλ“€μ€ λͺ¨λ‘ λΉŒλ” μžμ‹ μ„ λ°˜ν™˜ν•œλ‹€. (물흐λ₯΄λ“―호좜 - ν”Œλ£¨μ–ΈνŠΈλ©”μ„œλ“œ, λ©”μ„œλ“œ 연쇄). λ§ˆμ§€λ§‰μ— build()μ—μ„œ 이 객체의 μƒμ„±μžμ— builderμΈμŠ€ν„΄μŠ€λ₯Ό λ„˜κ²¨μ€˜μ„œ μƒμ„±ν•˜κ²Œ λœλ‹€.

λΉŒλ” νŒ¨ν„΄μ€ 생성 λΉ„μš©μ΄ λ“€μ§€λ§Œ λ§€κ°œλ³€μˆ˜κ°€ 점차 λŠ˜μ–΄λ‚˜λ©΄ 관리가 더 μ–΄λ ΅λ‹€.

→ λ§€κ°œλ³€μˆ˜κ°€ λ§Žλ‹€λ©΄ λΉŒλ” νŒ¨ν„΄μ„ νƒν•˜μž. (κ°„κ²°ν•˜κ³  μ•ˆμ „ν•˜λ‹€)

μ•„μ΄ν…œ 3 : private μƒμ„±μžλ‚˜ μ—΄κ±° νƒ€μž…μœΌλ‘œ μ‹±κΈ€ν„΄μž„μ„ λ³΄μ¦ν•˜λΌ

-νŠΉμ§•-

  1. 싱글톀 : μΈμŠ€ν„΄μŠ€λ₯Ό 였직 ν•˜λ‚˜λ§Œ 생성할 수 μžˆλŠ” 클래슀λ₯Ό λ§ν•œλ‹€.
  2. 클래슀λ₯Ό μ‹±κΈ€ν†€μœΌλ‘œ λ§Œλ“€λ©΄ 이λ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό ν…ŒμŠ€νŠΈν•˜κΈ°κ°€ μ–΄λ €μ›Œμ§„λ‹€.
  3. → μ‹±κΈ€ν„΄ μΈμŠ€ν„΄μŠ€λ₯Ό κ°€μ§œ mock κ΅¬ν˜„μœΌλ‘œ λŒ€μ²΄ν•  수 μ—†μŒ

정적 νŒ©ν„°λ¦¬ λ°©μ‹μ˜ μ‹±κΈ€ν„΄

// μ½”λ“œ 3-2 정적 νŒ©ν„°λ¦¬ λ°©μ‹μ˜ μ‹±κΈ€ν„΄ (24μͺ½)
public class Elvis {
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() { }
    public static Elvis getInstance() { return INSTANCE; }

    public void leaveTheBuilding() {
        System.out.println("Whoa baby, I'm outta here!");
    }

    // 이 λ©”μ„œλ“œλŠ” 보톡 클래슀 λ°”κΉ₯(λ‹€λ₯Έ 클래슀)에 μž‘μ„±ν•΄μ•Ό ν•œλ‹€!
    public static void main(String[] args) {
        Elvis elvis = Elvis.getInstance();
        elvis.leaveTheBuilding();
    }
}
© 2022 GitHub, Inc.
  1. μ›ν•œλ‹€λ©΄ μœ μΌν•œ μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹Œ ν˜ΈμΆœλ§ˆλ‹€ λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€λ₯Ό λ„˜κ²¨μ£ΌλŠ” νŒ©ν„°λ¦¬ λ©”μ„œλ“œλ‘œ λ§Œλ“€ 수 μžˆλ‹€.

λ¬Έμ œμ μ€ μ‹±κΈ€ν„΄ 클래슀λ₯Ό μ§λ ¬ν™”ν•˜λ©΄ 역직렬화 μ‹œ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€κ°€ μƒκΈ΄λ‹€λŠ” 점이닀.

이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ readResoverλ©”μ„œλ“œλ₯Ό μ •μ˜ν•΄ 싱글턴을 보μž₯ν•œλ‹€.

// readResolve λ©”μ„œλ“œλ₯Ό μ •μ˜ν•œλ‹€. 역직렬화 μ‹œ 호좜
	private Object readResolve() {
        // 싱글턴을 보μž₯ν•˜κΈ° μœ„ν•¨!
		return INSTANCE;
	}

μ—΄κ±° νƒ€μž… λ°©μ‹μ˜ 싱글턴이 κ°„κ²°ν•˜κ³  μ’‹λ‹€κ³  ν•œλ‹€..

μ•„μ΄ν…œ 4 : μΈμŠ€ν„΄μŠ€ν™”λ₯Ό λ§‰μœΌλ €κ±°λ“  private μƒμ„±μžλ₯Ό μ‚¬μš©ν•˜λΌ

정적 λ©€λ²„λ§Œ 담은 μœ ν‹Έλ¦¬ν‹° 클래슀의 경우 μΈμŠ€ν„΄μŠ€λ‘œ λ§Œλ“€μ–΄ μ‚¬μš©ν•˜λ €λŠ” 것이 μ•„λ‹ˆλ‹€. (μƒμ„±μžλ₯Ό λ§Œλ“€ ν•„μš”λ„ μ‚¬μš©ν•  μ΄μœ λ„ μ—†λ‹€)

ν•˜μ§€λ§Œ, μƒμ„±μžλ₯Ό μ •μ˜ν•˜μ§€ μ•ŠμœΌλ©΄ κΈ°λ³Έμƒμ„±μžκ°€ μžλ™μœΌλ‘œ μƒμ„±λœλ‹€.

κ·ΈλŸ¬λ―€λ‘œ μƒμ„±μžλ₯Ό private으둜 μ •μ˜ν•΄μ„œ 클래슀의 μΈμŠ€ν„΄μŠ€ν™”λ₯Ό λͺ…μ‹œμ μœΌλ‘œ 막을 수 μžˆλ‹€.

μ•„μ΄ν…œ 5 : μžμ›μ„ 직접 λͺ…μ‹œν•˜μ§€ 말고 의쑴 객체 μ£Όμž…μ„ μ‚¬μš©ν•˜λΌ

λ§Žμ€ ν΄λž˜μŠ€κ°€ ν•˜λ‚˜ μ΄μƒμ˜ μžμ›μ— μ˜μ‘΄ν•œλ‹€. μ‚¬μš©ν•˜λŠ” μžμ›μ— 따라 λ™μž‘μ΄ λ‹¬λΌμ§€λŠ” ν΄λž˜μŠ€μ—λŠ” 정적 μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€λ‚˜ μ‹±κΈ€ν„΄ 방식이 μ ν•©ν•˜μ§€ μ•Šλ‹€.

ν΄λž˜μŠ€κ°€ μ—¬λŸ¬ μžμ› μΈμŠ€ν„΄μŠ€λ₯Ό μ§€μ›ν•˜λ„λ‘ μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ ν•„μš”ν•œ μžμ›μ„ λ„˜κ²¨μ£ΌλŠ” 방식을 μ‚¬μš©ν•˜μž (의쑴 객체 μ£Όμž…)

  • νŒ©ν† λ¦¬λ₯Ό μ£Όμž…ν•΄μ„œ λͺ…μ‹œν•œ νƒ€μž…μ˜ ν•˜μœ„νƒ€μž…μ˜ μ–΄λ–€ 것이든지 생성할 μˆ˜λ„ μžˆλ‹€.
  • 의쑴 객체 μ£Όμž…μ€ 클래슀의 μœ μ—°μ„±, μž¬μ‚¬μš©μ„±, ν…ŒμŠ€νŠΈ μš©μ΄μ„±μ„ κ°œμ„ ν•œλ‹€.

μ•„μ΄ν…œ 6 : λΆˆν•„μš”ν•œ 객체 생성을 ν”Όν•˜λΌ

λ˜‘κ°™μ€ κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 객체λ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ 맀번 μƒμ„±ν•˜μ§€λ§κ³  객체 ν•˜λ‚˜λ₯Ό μž¬μ‚¬μš©ν•΄λΌ.

맀번 μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“œλŠ” 것은 λΉ„μš©μ΄λ‹€.

μž¬μ‚¬μš©μ΄ ν•„μš”ν•˜λ©΄ μƒμ„±μž λŒ€μ‹  정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ μƒμ„±λœ 객체λ₯Ό μž¬μ‚¬μš©ν•˜μž.

μ˜€ν† λ°•μ‹±μ€ λΆˆν•„μš”ν•œ 객체 생성을 μœ λ°œν•  수 μžˆλ‹€. μ‘°μ‹¬ν•˜μž.

private static long sum(){
	Long sum = 0L;
	for(long i = 0; i<= Integer.MAX_VALUE; i++)
			sum +=i;
	return sum;
}
// Long μΈμŠ€ν„΄μŠ€ 2^31개 μƒμ„±ν•˜κ²Œ 됨

μš”μ¦˜μ—λŠ” JVM 가비지 컬렉터가 μ΅œμ ν™”κ°€ μž˜λ˜μ–΄μžˆμ–΄ 객체 풀을 μƒμ„±ν•˜λŠ” 것보닀 λΉ λ₯΄λ‹€. 잘λͺ»λœ 반볡적 μ‚¬μš©μ€ λ§Žμ€ ν”Όν•΄λ₯Ό λΆˆλŸ¬μ˜€λ―€λ‘œ μ‘°μ‹¬ν•΄μ„œ μ‚¬μš©ν•΄μ•Όν•œλ‹€.

μ•„μ΄ν…œ 7 : λ‹€ μ“΄ 객체 μ°Έμ‘°λ₯Ό ν•΄μ œν•˜λΌ

가바지 μ»¬λ ‰ν„°λŠ” λ©”λͺ¨λ¦¬ 관리λ₯Ό ν•΄μ£Όμ§€λ§Œ κ°œλ°œμžκ°€ λ©”λͺ¨λ¦¬ 관리λ₯Ό μ•„μ˜ˆ μ•ˆν•΄λ„ λ˜λŠ”κ²ƒμ€ μ•„λ‹ˆλ‹€.

package effectivejava.chapter2.item7;
import java.util.*;

// μ½”λ“œ 7-1 λ©”λͺ¨λ¦¬ λˆ„μˆ˜κ°€ μΌμ–΄λ‚˜λŠ” μœ„μΉ˜λŠ” 어디인가? (36μͺ½)
public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        return elements[--size];
    }

    /**
     * μ›μ†Œλ₯Ό μœ„ν•œ 곡간을 적어도 ν•˜λ‚˜ 이상 ν™•λ³΄ν•œλ‹€.
     * λ°°μ—΄ 크기λ₯Ό λŠ˜λ €μ•Ό ν•  λ•Œλ§ˆλ‹€ λŒ€λž΅ 두 λ°°μ”© λŠ˜λ¦°λ‹€.
     */
    private void ensureCapacity() {
        if (elements.length == size)
            elements = Arrays.copyOf(elements, 2 * size + 1);
    }

//    // μ½”λ“œ 7-2 μ œλŒ€λ‘œ κ΅¬ν˜„ν•œ pop λ©”μ„œλ“œ (37μͺ½)
//    public Object pop() {
//        if (size == 0)
//            throw new EmptyStackException();
//        Object result = elements[--size];
//        elements[size] = null; // λ‹€ μ“΄ μ°Έμ‘° ν•΄μ œ
//        return result;
//    }

    public static void main(String[] args) {
        Stack stack = new Stack();
        for (String arg : args)
            stack.push(arg);

        while (true)
            System.err.println(stack.pop());
    }
}

μœ„ μ½”λ“œλŠ” λ©”λͺ¨λ¦¬ λˆ„μˆ˜κ°€ λ°œμƒν•œλ‹€.

μŠ€νƒμ΄ pop() ν•˜κ³ λ„ μ—¬μ „νžˆ λ‹€ μ“΄ μ°Έμ‘°λ₯Ό 가지고 있기 λ•Œλ¬Έμ— 가바지 컬렉터가 λ©”λͺ¨λ¦¬λ₯Ό νšŒμˆ˜ν•˜μ§€ λͺ»ν•œλ‹€.

μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ‹¨μˆœνžˆ elements[size] = null; 처리만 ν•˜λ©΄ λœλ‹€. (μ°Έμ‘° ν•΄μ œ)

λ©”λͺ¨λ¦¬λ₯Ό 직접 κ΄€λ¦¬ν•˜λŠ” 클래슀라면 λ©”λͺ¨λ¦¬ λˆ„μˆ˜μ— μ£Όμ˜ν•˜μž.

μ•„μ΄ν…œ 8 : finalizer와 cleaner μ‚¬μš©μ„ ν”Όν•˜λΌ

두 가지 객체 μ†Œλ©Έμž.

finalizer

cleaner

  • λ‘˜ λ‹€ κ²°κ΅­ μ˜ˆμΈ‘ν•  수 μ—†κ³  일반적으둜 λΆˆν•„μš”ν•¨.
  • μ¦‰μ‹œ μžμ›μ„ νšŒμˆ˜ν•œλ‹€λŠ” 보μž₯ μ—†μŒ. (νšŒμˆ˜ν•œλ‹€κ³  μ˜ˆμƒν•˜κ³  μ‹€ν–‰ μ‹œ 예기치 λͺ»ν•œ 였λ₯˜λ₯Ό λ§Œλ‚  수 있음)
  • 특히 λ°μ΄ν„°λ² μ΄μŠ€ 락 μžμ› ν•΄μ œ 같은 것을 이 λ‘˜μ— 맑겨 λ†“μœΌλ©΄ μ‹œμŠ€ν…œ μžμ²΄κ°€ μ„œμ„œνžˆ 멈좜 수 μžˆλ‹€.
  • λ³΄μ•ˆμ—μ·¨μ•½ν•¨
  • μ„±λŠ₯ ν•˜λ½

μ•„μ΄ν…œ 9 : try-finally λ³΄λ‹€λŠ” try-with-resourcesλ₯Ό μ‚¬μš©ν•΄λΌ

μžμ›λ‹«κΈ°μ— μ•ˆμ „λ§μœΌλ‘œ finallizerλ₯Ό μ‚¬μš©ν•˜κΈ°λ„ ν•˜μ§€λ§Œ 맀우 믿을 만 ν•˜μ§€ λͺ»ν•˜λ‹€ (이전 μ•„μ΄ν…œ)

try-finallyλ₯Ό μ‚¬μš©ν•˜λ©΄ μžμ›μ„ νšŒμˆ˜ν•  순 μžˆλ‹€. ν•˜μ§€λ§Œ μžμ›μ΄ μ—¬λŸ¬κ°œλΌλ©΄..?

		// μ½”λ“œ 9-2 μžμ›μ΄ λ‘˜ 이상이면 try-finally 방식은 λ„ˆλ¬΄ μ§€μ €λΆ„ν•˜λ‹€! (47μͺ½)
    static void copy(String src, String dst) throws IOException {
        InputStream in = new FileInputStream(src);
        try {
            OutputStream out = new FileOutputStream(dst);
            try {
                byte[] buf = new byte[BUFFER_SIZE];
                int n;
                while ((n = in.read(buf)) >= 0)
                    out.write(buf, 0, n);
            } finally {
                out.close();
            }
        } finally {
            in.close();
        }
    }

가독성도 λ–¨μ–΄μ§€μ§€λ§Œ

두 번째 tryμ—μ„œ μ˜ˆμ™Έ λ°œμƒ μ‹œ 첫번째 μ˜ˆμ™Έλ₯Ό 먹어버린닀. μ΄λŠ” 좔적 내역에 λŒ€ν•œ 정보가 남지 μ•Šμ•„ 디버깅을 μ–΄λ ΅κ²Œ ν•œλ‹€.

try-with-resourcesλ₯Ό μ‚¬μš©ν•˜λ©΄μ„œ μ΄λŸ¬ν•œ λ¬Έμ œκ°€ ν•΄κ²°λ˜μ—ˆλ‹€.

static void copy(String src, String dst) throws IOException{
		try(InputStream in = new FileInputStream(src);
			OutputStream out = new FileOutputStream(dst)) {
			byte[] buf = new byte[BUFFER_SIZE];
			int n;
			while ((n = in.read(buf)) >= 0)
				out.write(buf, 0,n);
		}
	}

try문을 μ€‘μ²©ν•˜μ§€ μ•Šκ³  μ‚¬μš©ν•  수 있고 μ‰½κ²Œ μžμ›μ„ νšŒμˆ˜ν•  수 μžˆλ‹€.