🌱 μΈν”„λŸ°/β˜•οΈ κΉ€μ˜ν•œμ˜ μ‹€μ „ μžλ°” - 쀑급 1편

μžλ°” 쀑첩 ν΄λž˜μŠ€μ™€ λ‚΄λΆ€ 클래슀

mallin 2025. 7. 9. 17:48

β˜•οΈ  κΉ€μ˜ν•œμ˜ μ‹€μ „ μžλ°” - 쀑급 1편 μ„ λ“£κ³  μž‘μ„±ν•˜λŠ” λ³΅μŠ΅ λΈ”λ‘œκ·Έ μž…λ‹ˆλ‹€.

 

0. λ°°κ²½

클래슀λ₯Ό κ·Έλƒ₯ 단일 클래슀둜 μƒμ„±ν•΄μ„œ μ‚¬μš©ν•  수 μžˆμ§€λ§Œ, μ€‘μ²©ν•΄μ„œ μ“°κ±°λ‚˜ 내뢀에 μ“°κ±°λ‚˜ λ‹€μ–‘ν•œ λ°©μ‹μœΌλ‘œλ„ ν™œμš©ν•  수 μžˆλ‹€ 

λ‹€μ–‘ν•˜κ²Œ ν™œμš©λ˜λŠ” 클래슀 쀑 쀑첩 ν΄λž˜μŠ€μ™€ λ‚΄λΆ€ ν΄λž˜μŠ€μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μž


1. 쀑첩 클래슀

πŸ’‘ 클래슀 μ•ˆμ— 클래슀λ₯Ό μ€‘μ²©ν•΄μ„œ μ‚¬μš©ν•˜λŠ” 것
class Outer {
	class Nested {...}
}
  • 쀑첩 ν΄λž˜μŠ€λŠ” μ€‘μ²©μ΄λΌλŠ” λ§μ—μ„œ μ•Œ 수 μžˆλ“―μ΄ 클래슀 μ•ˆμ— 클래슀λ₯Ό λ„£μ–΄μ„œ μ‚¬μš©ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€
  • μ΄λŠ” 클래슀λ₯Ό μ •μ˜ν•˜λŠ” μœ„μΉ˜μ— λ”°λΌμ„œ λΆ„λ₯˜κ°€ 달라진닀
  • 총 4κ°€μ§€κ°€ 있고, μΈμŠ€ν„΄μŠ€ μ†Œμ†μ— 따라 크게 2κ°€μ§€λ‘œ λΆ„λ₯˜ν•  수 μžˆλ‹€
μΈμŠ€ν„΄μŠ€ μ†Œμ† 쀑첩 클래슀 이름 μ„€λͺ…
μ „ν˜€ λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€ 정적 쀑첩 클래슀 (static nested) static 을 μ‚¬μš©ν•΄ μ„ μ–Έ
λ°”κΉ₯ μΈμŠ€ν„΄μŠ€ μ†Œμ† λ‚΄λΆ€ 클래슀 (inner) μΈμŠ€ν„΄μŠ€ 내뢀에 μ„ μ–Έ
μ§€μ—­ 클래슀 (local) μ½”λ“œ 블둝에 μ„ μ–Έ
읡λͺ… 클래슀 (anoymous) 이름 μ—†λŠ” 클래슀

 

❓ 쀑첩 (Nested) vs λ‚΄λΆ€ (Inner)
쀑첩 : λ‹€λ₯Έ 것이 내뢀에 μœ„μΉ˜ν•˜κ±°λ‚˜ ν¬ν•¨λ˜λŠ” ꡬ쑰적인 관계
→ λ‹¨μˆœνžˆ μœ„μΉ˜λ§Œ μ•ˆμ— 있고, λ‚΄ 것이 μ•„λ‹Œ 것

λ‚΄λΆ€ : λ‚˜μ˜ 내뢀에 μžˆλŠ” λ‚˜λ₯Ό κ΅¬μ„±ν•˜λŠ” μš”μ†Œ
→ μœ„μΉ˜λ„ μ•ˆμ— 있고, λ‚΄ 것인 것

 

쀑첩과 λ‚΄λΆ€λŠ” μœ„μΉ˜κ°€ μ•ˆμ— μžˆλŠ” 것은 κ°™μ§€λ§Œ, 내것인지 내것이 μ•„λ‹Œμ§€λ‘œ λ‚˜λ‰œλ‹€.

πŸ™†‍♀️ λ‚΄ 것인 경우 쀑첩

πŸ™…‍♀️ λ‚΄ 것이 μ•„λ‹Œ 경우 → λ‚΄λΆ€

 

μ€‘μ²©ν΄λž˜μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ”

  1. 논리적 κ·Έλ£Ήν™” 
    • νŠΉμ • ν΄λž˜μŠ€κ°€ λ‹€λ₯Έ ν•˜λ‚˜μ˜ 클래슀 μ•ˆμ—μ„œλ§Œ μ‚¬μš©λ˜λŠ” 경우 쀑첩 클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ κ·Έλ£Ήν™”λ₯Ό ν•  수 μžˆλ‹€
    • λ‹€λ₯Έ κ³³μ—μ„œ μ‚¬μš©ν•  ν•„μš”κ°€ μ—†λŠ” ν΄λž˜μŠ€κ°€ λ…ΈμΆœλ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 개발자의 ν˜Όλž€μ„ 쀄여쀀닀
  2. μΊ‘μŠν™”
    • 쀑첩 ν΄λž˜μŠ€λŠ” λ°”κΉ₯ 클래슀의 private 멀버에 μ ‘κ·Όν•  수 μžˆλ‹€
    • 두 클래슀λ₯Ό κΈ΄λ°€ν•˜κ²Œ μ—°κ²°ν•˜κ³ , λΆˆν•„μš”ν•œ public λ©”μ„œλ“œλ₯Ό μ œκ±°ν•  수 μžˆλ‹€

 

이젠 각각의 쀑첩 ν΄λž˜μŠ€μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μž


2. 정적 쀑첩 클래슀 (static nested class)

πŸ’‘  μ„œλ‘œ 관계가 μ—†λŠ” 클래슀 두 개λ₯Ό 쀑첩해둔 클래슀
  • 정적 쀑첩 ν΄λž˜μŠ€λŠ” 클래슀 μ•žμ— static 을 λΆ™μ—¬μ„œ λ§Œλ“ λ‹€
  • static 을 λΆ™μ—¬μ„œ λ§Œλ“€κΈ° λ•Œλ¬Έμ— μ™ΈλΆ€μ˜ ν΄λž˜μŠ€μ™€ 관계 없이 클래슀 λ‘œλ”© μ‹œ Method Area 에 λ‘œλ”©λœλ‹€
public class NestedOuter {
    private static int outCalssValue = 3;
    private int outInstanceValue = 2;
    static class Nested {
        private int nestedInstanceValue = 1;
        public void print() {
            System.out.println(nestedInstanceValue);
            System.out.println(outInstanceValue);
            System.out.println(outCalssValue);
        }
    }
}
  • μžμ‹ μ˜ λ©€λ²„λ³€μˆ˜μΈ nestedInstanceValue μ—λŠ” μ ‘κ·Ό πŸ™†‍♀️
  • λ°”κΉ₯ 클래슀의 μΈμŠ€ν„΄μŠ€λ³€μˆ˜μΈ outInstanceValue μ—λŠ” μ ‘κ·Ό πŸ™…‍♀️
  • λ°”κΉ₯ 클래슀의 ν΄λž˜μŠ€λ³€μˆ˜μΈ outClassValue μ—λŠ” μ ‘κ·Ό πŸ™†‍♀️

 

사싀상 NestedOuter 와 Nested ν΄λž˜μŠ€λŠ” 클래슀λ₯Ό λ”°λ‘œ 2개λ₯Ό λ§Œλ“  것과 κ°™λ‹€

class NestedOuter {
}

class Nested {
}

→ μœ μΌν•œ μ°¨μ΄λŠ” 같은 클래슀이기 λ•Œλ¬Έμ— private μ ‘κ·Ό μ œμ–΄μžμ— μ ‘κ·Όν•  수 μžˆλ‹€.


3. λ‚΄λΆ€ 클래슀

πŸ’‘  λ°”κΉ₯ 클래슀 μΈμŠ€ν„΄μŠ€μ— μ†Œμ†λœλ‹€
  • static 을 뢙이지 μ•Šκ³  class 둜 λ§Œλ“ λ‹€
  • μ‰½κ²Œ λ§ν•΄μ„œ μΈμŠ€ν„΄μŠ€ 멀버가 λœλ‹€
public class InnerOuter {
    private static int outClassValue = 3;
    private int outInstanceValue = 2;
    class Inner {
        private int innerInstanceValue = 1;
        public void print() {
            System.out.println(innerInstanceValue);
            System.out.println(outInstanceValue);
            System.out.println(outClassValue);
        }
    }
}
  • μžμ‹ μ˜ λ©€λ²„λ³€μˆ˜μΈ nestedInstanceValue μ—λŠ” μ ‘κ·Ό πŸ™†‍♀️
  • λ°”κΉ₯ 클래슀의 μΈμŠ€ν„΄μŠ€λ³€μˆ˜μΈ outInstanceValue μ—λŠ” μ ‘κ·Ό πŸ™†‍♀️
  • λ°”κΉ₯ 클래슀의 ν΄λž˜μŠ€λ³€μˆ˜μΈ outClassValue μ—λŠ” μ ‘κ·Ό πŸ™†‍♀️
InnerOuter outer = new InnerOuter();
InnerOuter.Inner inner = outer.new Inner();
  • λ‚΄λΆ€ 클래슀의 경우 new λ°”κΉ₯클래슀의 μΈμŠ€ν„΄μŠ€ μ°Έμ‘°.new λ‚΄λΆ€ν΄λž˜μŠ€() 둜 생성할 수 μžˆλ‹€
  • μ‹€μ œλ‘œλŠ” λ‚΄λΆ€ μΈμŠ€ν„΄μŠ€κ°€ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€ μ•ˆμ— μƒμ„±λ˜μ§€ μ•Šκ³ , λ‚΄λΆ€ μΈμŠ€ν„΄μŠ€κ°€ λ°”κΉ₯ μΈμŠ€ν„΄μŠ€μ˜ μ°Έμ‘°λ₯Ό λ³΄κ΄€ν•˜λŠ” λ°©μ‹μœΌλ‘œ μƒμ„±λœλ‹€
  • ν•˜μ§€λ§Œ, κ°œλ…μƒ μΈμŠ€ν„΄μŠ€ μ•ˆμ— μƒμ„±λœλ‹€κ³  μ΄ν•΄ν•˜λ©΄ λœλ‹€

4. μ§€μ—­ 클래슀

πŸ’‘  μ§€μ—­ λ³€μˆ˜μ™€ 같은 μœ„μΉ˜μ— μƒμ„±λ˜λŠ” 클래슀
  • λ‚΄λΆ€ 클래슀의 νŠΉμ§•μ„ κ·ΈλŒ€λ‘œ κ°€μ§„λ‹€
  • λ°”κΉ₯ 클래슀의 μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ— μ ‘κ·Όν•  수 μžˆλ‹€
  • μ§€μ—­λ³€μˆ˜μ™€ 같이 μ½”λ“œ λΈ”λŸ­ μ•ˆμ—μ„œ μ •μ˜λœλ‹€
  • μ§€μ—­ λ³€μˆ˜μ²˜λŸΌ μ ‘κ·Ό μ œμ–΄μžλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€
class Outer {
	public void process() {
		int localVar = 0;
		class Local { .. }
	}
}

 

 

4-1. 생λͺ… μ£ΌκΈ° 문제 

μ§€μ—­ 클래슀의 경우 생λͺ… μ£ΌκΈ° 문제λ₯Ό κ°€μ§„λ‹€ 

λ³€μˆ˜μ˜ 생λͺ… μ£ΌκΈ°λŠ” μ•„λž˜ ν‘œμ™€ κ°™λ‹€

λ³€μˆ˜λͺ… 생쑴 μ£ΌκΈ° λ³€μˆ˜ 쑴재 μ˜μ—­
클래슀 λ³€μˆ˜ 클래슀 정보λ₯Ό μ½μ–΄λ“€μ΄λŠ” μˆœκ°„λΆ€ν„° ν”„λ‘œκ·Έλž¨ μ’…λ£ŒκΉŒμ§€ λ©”μ„œλ“œ μ˜μ—­
μΈμŠ€ν„΄μŠ€ λ³€μˆ˜ μΈμŠ€ν„΄μŠ€κ°€ GC 되기 μ „κΉŒμ§€ νž™ μ˜μ—­
μ§€μ—­ λ³€μˆ˜ λ©”μ„œλ“œ 호좜이 μ’…λ£Œλ  λ•ŒκΉŒμ§€ μŠ€νƒ μ˜μ—­

 

λ§Œμ•½ μ§€μ—­ 클래슀 λ‚΄λΆ€μ—μ„œ μ™ΈλΆ€ 클래슀의 μ§€μ—­ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ 생λͺ… μ£ΌκΈ°κ°€ λ§žμ§€ μ•Šκ²Œ λ˜λŠ”λ°

이런 κ²½μš°λŠ” μ–΄λ–»κ²Œ λ™μž‘ν• κΉŒ?

class Outer {
    public Printer process() {
        int processVar = 1;
        class Local implements Printer {
            int localVar = 2;

            @Override
            public void print() {
                System.out.println("processVar = " + processVar);
                System.out.println("localVar = " + localVar);
            }
        }
        return new Local();
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        Printer printer = outer.process();
        printer.print();
    }
}

 

Outer 클래슀 λ‚΄λΆ€μ˜ process() λ©”μ†Œλ“œμ— Local μ§€μ—­ ν΄λž˜μŠ€κ°€ μžˆλ‹€.

Local μ§€μ—­ 클래슀의 print() λ©”μ†Œλ“œμ—μ„ 

  • process() λ©”μ†Œλ“œμ˜ μ§€μ—­ λ³€μˆ˜μΈ processVar (생λͺ…μ£ΌκΈ° : process() λ©”μ†Œλ“œκ°€ ν˜ΈμΆœλ λ•ŒκΉŒμ§€)
  • Local 클래슀의 μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μΈ localVar (생λͺ…μ£ΌκΈ° : Local ν΄λž˜μŠ€κ°€ GCμ—μ„œ μ‚­μ œλ  λ•ŒκΉŒμ§€

을 좜λ ₯ν•œλ‹€.

 

그리고 main μ—μ„œλŠ” process() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜κ³  print() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ”λ° 

μ–΄λž ... ? πŸ€”

process() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜κ³  λ‚˜λ©΄ processVar λ³€μˆ˜λŠ” 생λͺ…이 λ‹€ν•΄μ„œ μ‚¬λΌμ§€λŠ” 걸둜 μ•Œκ³  μžˆλŠ”λ°

print() λ©”μ†Œλ“œ λ‚΄λΆ€μ—μ„œ processVar λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜κ³  μžˆλ‹€ !!!! ? 

 

→ 이건 μ§€μ—­ λ³€μˆ˜ 캑처λ₯Ό ν†΅ν•΄μ„œ ν•΄κ²°λœλ‹€.

 

 

4-2. μ§€μ—­ λ³€μˆ˜ 캑처

πŸ’‘  μ§€μ—­ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” μ‹œμ μ— ν•„μš”ν•œ μ§€μ—­ λ³€μˆ˜λ₯Ό λ³΅μ‚¬ν•΄μ„œ μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€μ— λ„£μ–΄μ€€λ‹€

 

κ°„λ‹¨ν•˜κ²Œ λ§ν•˜λ©΄ μ§€μ—­ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ λ°–μ—μ„œ μ°Έμ‘°ν•˜κ³  μžˆλŠ” μ§€μ—­ λ³€μˆ˜κ°€ μžˆλ‹€λ©΄ λ³΅μ‚¬ν•΄μ„œ λ§Œλ“€μ–΄μ€€λ‹€

  1. μ§€μ—­ 클래슀 μΈμŠ€ν„΄μŠ€ 생성 μ‹œλ„ 
  2. μ‚¬μš©ν•˜λŠ” μ§€μ—­λ³€μˆ˜ 볡사
  3. μ§€μ—­ λ³€μˆ˜ 볡사 μ™„λ£Œ
  4. μΈμŠ€ν„΄μŠ€ 생성 μ™„λ£Œ

의 과정을 톡해 μ§€μ—­ 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λ˜κΈ° λ•Œλ¬Έμ— μœ„μ™€ 같은 생λͺ…μ£ΌκΈ° λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€

μ΄λ ‡κ²Œ 볡사λ₯Ό ν•˜κΈ° λ•Œλ¬Έμ— μ§€μ—­ ν΄λž˜μŠ€κ°€ μ ‘κ·Όν•˜λŠ” μ§€μ—­ λ³€μˆ˜λŠ” 쀑간에 값이 λ³€ν•˜λ©΄ μ•ˆλœλ‹€. (사싀상 final)

 


5. 읡λͺ… 클래슀

πŸ’‘  클래슀 이름이 μ—†λŠ” μ§€μ—­ 클래슀
  • 읡λͺ… ν΄λž˜μŠ€λŠ” μ§€μ—­ 클래슀의 νŠΉλ³„ν•œ μ’…λ₯˜ 쀑에 ν•˜λ‚˜λ‹€
  • μ§€μ—­ ν΄λž˜μŠ€μ΄μ§€λ§Œ, 클래슀의 이름을 κ°€μ§€μ§€ μ•ŠλŠ”λ‹€
Printer printer = new Printer() {
    int value = 0;

    @Override
    public void print() {
        System.out.println("value = " + value);
    }
};
  • μœ„μ˜ μ½”λ“œμ²˜λŸΌ 클래슀의 이름을 μƒλž΅ν•˜κ³  클래슀의 μ„ μ–Έκ³Ό 생성을 λ™μ‹œμ— μ²˜λ¦¬ν•  수 μžˆλ‹€
  • Printer 은 μΈν„°νŽ˜μ΄μŠ€μΈλ° μΈν„°νŽ˜μ΄μŠ€λ₯Ό μƒμ„±ν•˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ, μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 읡λͺ… 클래슀λ₯Ό μƒμ„±ν•˜λŠ” 것이닀
  • 읡λͺ… ν΄λž˜μŠ€λŠ” λΆ€λͺ¨ 클래슀λ₯Ό μƒμ†λ°›κ±°λ‚˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ•Ό ν•˜λ―€λ‘œ μƒμœ„ ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€κ°€ ν•„μš”ν•˜λ‹€

읡λͺ… 클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ 인자둜 클래슀λ₯Ό λ°”λ‘œ λ„˜κΈΈ 수 μžˆλ‹€

hello(new Process() {
    @Override
    public void run() {
        int randomValue = new Random().nextInt(6) + 1;
        System.out.println("μ£Όμ‚¬μœ„ = " + randomValue);
    }
});

 

→ 이게 μ’€ 더 λ°œμ „ν•΄μ„œ λžŒλ‹€κ°€ 됐닀!! (lambda)