๐ŸŽฏ1์ฃผ์ฐจ Unit 2.5 โ€” instanceof์™€ ํ˜•๋ณ€ํ™˜

Psjยท5์ผ ์ „

F-lab

๋ชฉ๋ก ๋ณด๊ธฐ
27/50

๐ŸŽฏ Unit 2.5 โ€” instanceof์™€ ํ˜•๋ณ€ํ™˜

F-lab Java 1์ฃผ์ฐจ / Phase 2 / Unit 2.5 ๋ณธ๊ฒฉ ํ•™์Šต ์ž๋ฃŒ
9-์„น์…˜ ๋งˆ์Šคํ„ฐ ํ”„๋กฌํ”„ํŠธ ํ˜•์‹์œผ๋กœ ๊นŠ์ด ํŒŒํ—ค์นœ๋‹ค.

์„ ์ˆ˜ ์ง€์‹: Unit 2.4 (๋‹คํ˜•์„ฑ)
๋‹ค์Œ Unit: 2.6 โ€” Nested/Inner/Anonymous ํด๋ž˜์Šค

์ด Unit์˜ ์˜๋ฏธ: ๋‹คํ˜•์„ฑ์˜ ์•ˆ์ „์žฅ์น˜. ClassCastException์„ ๋ฐฉ์ง€ํ•˜๊ณ , ์ž์‹์˜ ๊ณ ์œ  ๋ฉ”์„œ๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ํ˜ธ์ถœํ•˜๋Š” ๋„๊ตฌ.


๐ŸŒ 1. ์„ธ์ƒ ์† ๋น„์œ 

instanceof = "์‹ ๋ถ„์ฆ ๊ฒ€์‚ฌ"

๋‹น์‹ ์ด ์–ด๋ฅธ์šฉ ํ–‰์‚ฌ์— ๋“ค์–ด๊ฐ€๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ž…๊ตฌ์˜ ๋ณด์•ˆ ์ง์›์ด ๋ฌป์Šต๋‹ˆ๋‹ค:

"์ด๋ถ„์ด ์ •๋ง ์„ฑ์ธ์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค."

์ง์›์ด ์‹ ๋ถ„์ฆ์„ ๋ณด๊ณ  ํ™•์ธ:

  • โœ… "์„ฑ์ธ ๋งž์œผ์‹œ๋„ค์š”. ์ž…์žฅํ•˜์„ธ์š”."
  • โŒ "๋ฏธ์„ฑ๋…„์ž๋„ค์š”. ์ž…์žฅ ๋ถˆ๊ฐ€."

ํ•ต์‹ฌ:

  • ์‚ฌ๋žŒ์˜ ๊ฒ‰๋ชจ์Šต ๋งŒ์œผ๋กœ๋Š” ๋ชจ๋ฆ„
  • ์‹ ๋ถ„์ฆ ์œผ๋กœ ์ง„์งœ ์‹ ์› ํ™•์ธ
  • ํ™•์ธ ํ›„์—์•ผ ์ ์ ˆํ•œ ์ฒ˜๋ฆฌ

โ†’ instanceof ๊ฐ€ ์ž๋ฐ”์—์„œ ํ•˜๋Š” ์—ญํ• .


ํ˜•๋ณ€ํ™˜ = "์œ ๋‹ˆํผ ๊ฐˆ์•„์ž…๊ธฐ"

์•ผ๊ตฌ ์„ ์ˆ˜๊ฐ€ ๊ฒฝ๊ธฐ ํ›„ ์œ ๋‹ˆํผ์„ ๊ฐˆ์•„์ž…๋Š”๋‹ค๊ณ  ํ•ฉ์‹œ๋‹ค.

์ƒํ™ฉ:

  • ์„ ์ˆ˜๋Š” ์‚ฌ๋žŒ (Person)
  • ๊ฒฝ๊ธฐ ์ค‘์—๋Š” ์•ผ๊ตฌ ์„ ์ˆ˜ (BaseballPlayer) ์œ ๋‹ˆํผ
  • ์ผ์ƒ์—์„œ๋Š” ์‹œ๋ฏผ (Citizen) ์˜ท

๊ฐ™์€ ์‚ฌ๋žŒ ์ธ๋ฐ:

  • ์•ผ๊ตฌ ์„ ์ˆ˜๋กœ์„œ์˜ ๋Šฅ๋ ฅ (์Šค์œ™, ๋˜์ง€๊ธฐ) ์„ ์“ฐ๋ ค๋ฉด โ†’ ์•ผ๊ตฌ ์œ ๋‹ˆํผ
  • ์‹œ๋ฏผ์œผ๋กœ์„œ์˜ ๊ถŒ๋ฆฌ (ํˆฌํ‘œํ•˜๊ธฐ) ๋ฅผ ์“ฐ๋ ค๋ฉด โ†’ ์‹œ๋ฏผ ์˜ท

ํ•ต์‹ฌ:

  • ๋ณธ์งˆ(์‚ฌ๋žŒ)์€ ๊ฐ™์ง€๋งŒ ์–ด๋–ค ๋Šฅ๋ ฅ์„ ์“ฐ๋А๋ƒ์— ๋”ฐ๋ผ ํ˜•ํƒœ๋ฅผ ๋ฐ”๊ฟˆ
  • ์ž˜๋ชป ์ž…์œผ๋ฉด (๋ฏธ์„ฑ๋…„์ž๊ฐ€ ์–ด๋ฅธ ์˜ท) ์•ˆ ์–ด์šธ๋ฆผ โ†’ ๊ฑฐ๋ถ€

โ†’ ์ด๊ฒŒ ํ˜•๋ณ€ํ™˜ (Type Casting).


๋‘˜์„ ํ•ฉ์นœ ๋น„์œ  โ€” "๋ณ‘์› ์‘๊ธ‰์‹ค"

์‘๊ธ‰์‹ค์— ํ™˜์ž๊ฐ€ ๋„์ฐฉํ•ฉ๋‹ˆ๋‹ค. ์˜์‚ฌ๊ฐ€:

1. instanceof โ€” ์‹ ์› ํ™•์ธ
   "์ด ํ™˜์ž๋Š” ์„ฑ์ธ์ธ๊ฐ€? ์–ด๋ฆฐ์ด์ธ๊ฐ€?"
        โ†“
2. ํ˜•๋ณ€ํ™˜ โ€” ์ ์ ˆํ•œ ๋„๊ตฌ ์ค€๋น„
   "์–ด๋ฆฐ์ด๋ผ๋ฉด โ†’ ์†Œ์•„๊ณผ ๋„๊ตฌ"
   "์„ฑ์ธ์ด๋ผ๋ฉด โ†’ ์„ฑ์ธ ๋„๊ตฌ"
        โ†“
3. ์ž์‹ ํด๋ž˜์Šค๋งŒ์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
   "์–ด๋ฆฐ์ด์—๊ฒŒ๋Š” ์–ด๋ฆฐ์ด์šฉ ์•ฝ ์ฒ˜๋ฐฉ"

์ž˜๋ชป๋œ ์ฒ˜๋ฆฌ:

  • ์–ด๋ฆฐ์ด๋ฅผ ์„ฑ์ธ์šฉ ์•ฝ์œผ๋กœ ์ฒ˜๋ฐฉ โ†’ ์œ„ํ—˜ (ClassCastException)

โ†’ instanceof๋กœ ๋จผ์ € ํ™•์ธ โ†’ ์•ˆ์ „ํ•œ ํ˜•๋ณ€ํ™˜ โ†’ ์ž์‹์˜ ๊ณ ์œ  ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ


๐Ÿ”ฅ 2. ํƒ„์ƒ ๋ฐฐ๊ฒฝ

๋‹คํ˜•์„ฑ์˜ ํ•œ๊ณ„ โ€” "๊ณตํ†ต ๋ฉ”์„œ๋“œ๋งŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค"

Unit 2.4 ๋‹คํ˜•์„ฑ์„ ๋ณต์Šต:

public abstract class Animal {
    public abstract void makeSound();  // ๋ชจ๋“  ๋™๋ฌผ ๊ณตํ†ต
}

public class Dog extends Animal {
    @Override
    public void makeSound() { System.out.println("๋ฉ๋ฉ"); }
    
    public void bark() { System.out.println("BARK!"); }       // Dog๋งŒ์˜ ๋ฉ”์„œ๋“œ
    public void wagTail() { System.out.println("๊ผฌ๋ฆฌ ํ”๋“ค๊ธฐ"); } // Dog๋งŒ์˜ ๋ฉ”์„œ๋“œ
}

๋‹คํ˜•์„ฑ์˜ ๊ฐ•์ :

Animal a = new Dog();
a.makeSound();  // โœ… "๋ฉ๋ฉ"

๋‹คํ˜•์„ฑ์˜ ํ•œ๊ณ„ โš ๏ธ :

Animal a = new Dog();
a.bark();     // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ โ€” Animal์— bark() ์—†์Œ
a.wagTail();  // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ โ€” Animal์— wagTail() ์—†์Œ

โ†’ ๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ๋Š” ์ž์‹๋งŒ์˜ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ๋ถˆ๊ฐ€. ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ณ€์ˆ˜ ํƒ€์ž…(Animal) ๋งŒ ๋ด„.


ํ•ด๊ฒฐ์ฑ… โ€” ์ž์‹ ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜

์ž์‹์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์“ฐ๋ ค๋ฉด ์ž์‹ ํƒ€์ž…์œผ๋กœ ํ˜•๋ณ€ํ™˜ ํ•„์š”:

Animal a = new Dog();
Dog d = (Dog) a;  // ๋ช…์‹œ์  ์บ์ŠคํŒ…
d.bark();          // โœ… ๊ฐ€๋Šฅ
d.wagTail();       // โœ… ๊ฐ€๋Šฅ

์ƒˆ๋กœ์šด ๋ฌธ์ œ โ€” ์ž˜๋ชป๋œ ์บ์ŠคํŒ…์˜ ์œ„ํ—˜ โš ๏ธ

Animal a = new Cat();      // ์‹ค์ œ๋Š” Cat
Dog d = (Dog) a;            // โš ๏ธ Cat์„ Dog๋กœ ์บ์ŠคํŒ… ์‹œ๋„
d.bark();                   // ๐Ÿ’ฅ ClassCastException (๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ)

๋ฌธ์ œ:

  • ์ปดํŒŒ์ผ๋Ÿฌ๋Š” "์บ์ŠคํŒ…ํ•˜๊ฒ ๋‹ค" ๋งŒ ํ™•์ธ
  • ์‹ค์ œ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋Š” ๋Ÿฐํƒ€์ž„์— ๊ฒฐ์ •
  • ์ž˜๋ชป ์บ์ŠคํŒ… ์‹œ ์ฆ‰์‹œ ํฌ๋ž˜์‹œ

instanceof ์˜ ๋“ฑ์žฅ

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ์•ˆ์ „์žฅ์น˜:

Animal a = new Cat();

if (a instanceof Dog) {  // โ† ์ง„์งœ Dog์ธ์ง€ ํ™•์ธ
    Dog d = (Dog) a;     // ์•ˆ์ „ํ•œ ์บ์ŠคํŒ…
    d.bark();
} else {
    System.out.println("Dog ์•„๋‹˜");
}

ํšจ๊ณผ:

  • ์บ์ŠคํŒ… ์ „ ํƒ€์ž… ๊ฒ€์ฆ
  • ClassCastException ๋ฐฉ์–ด
  • ์•ˆ์ „ํ•œ ๋‹คํ˜•์„ฑ ํ™œ์šฉ

ํ•ต์‹ฌ ํ†ต์ฐฐ

"๋‹คํ˜•์„ฑ์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ์ž์‹์˜ ๊ณ ์œ  ๋Šฅ๋ ฅ์„ ์“ฐ๋ ค๋ฉด ํ˜•๋ณ€ํ™˜์ด ํ•„์š”ํ•˜๋‹ค.
๊ทธ ํ˜•๋ณ€ํ™˜์€ ์œ„ํ—˜ํ•˜๋ฏ€๋กœ instanceof ๋ผ๋Š” ์•ˆ์ „์žฅ์น˜๋ฅผ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค."

๋‹คํ˜•์„ฑ, instanceof, ํ˜•๋ณ€ํ™˜์€ ์„ธ ๊ฐ€์ง€๊ฐ€ ํ•จ๊ป˜ ๊ฐ€๋Š” ํ•œ ์„ธํŠธ.


๐Ÿ’ฃ 3. ์—†์œผ๋ฉด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ

instanceof ์—†์ด ํ˜•๋ณ€ํ™˜์„ ๋‚จ๋ฐœํ•˜๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š”์ง€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์‹œ๋‚˜๋ฆฌ์˜ค: ILIC ์šด์ž„ ์‹œ์Šคํ…œ

๋‹ค์–‘ํ•œ ์šด์ž„ ์ข…๋ฅ˜ (StandardFare, UrgentFare, InternationalFare) ๊ฐ€ ์žˆ๊ณ , ๊ฐ์ž ๊ณ ์œ  ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

public abstract class Fare { ... }

public class StandardFare extends Fare { ... }

public class UrgentFare extends Fare {
    public int getUrgentFee() { return urgentFee; }
}

public class InternationalFare extends Fare {
    public String getCurrency() { return currency; }
    public double getExchangeRate() { return exchangeRate; }
}

instanceof ์—†์ด โ€” ์œ„ํ—˜ํ•œ ์บ์ŠคํŒ…

public class FareReportService {
    public void printReport(List<Fare> fares) {
        for (Fare fare : fares) {
            // ๋ชจ๋“  ์šด์ž„์„ UrgentFare๋กœ ์บ์ŠคํŒ… ์‹œ๋„ โŒ
            UrgentFare urgent = (UrgentFare) fare;
            System.out.println("๊ธด๊ธ‰๋น„: " + urgent.getUrgentFee());
        }
    }
}

List<Fare> fares = List.of(
    new StandardFare(1L, 50000),
    new UrgentFare(2L, 50000, 10000),
    new InternationalFare(3L, 100, "USD", 1300.0)
);

reportService.printReport(fares);
// ์ฒซ ๋ฒˆ์งธ ํ•ญ๋ชฉ ์ฒ˜๋ฆฌ ์‹œ๋„:
// ๐Ÿ’ฅ ClassCastException โ€” StandardFare๋ฅผ UrgentFare๋กœ ์บ์ŠคํŒ… ๋ถˆ๊ฐ€
// โ†’ ํ”„๋กœ๊ทธ๋žจ ์ฃฝ์Œ

๋ฌธ์ œ:
1. ์ฒซ ๋‹ค๋ฅธ ํƒ€์ž… ๋งŒ๋‚˜๋ฉด ์ฆ‰์‹œ ํฌ๋ž˜์‹œ
2. ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ฐ์ฒด ์ฒ˜๋ฆฌ ์œ„ํ—˜
3. ๊ณ ๊ฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ๋‹ค์šด โ†’ ์„œ๋น„์Šค ์žฅ์• 


instanceof ์—†์ด โ€” ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ€๋ชจ์— ์šฐ๊ฒจ๋„ฃ๊ธฐ

๋Œ€์•ˆ์œผ๋กœ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ€๋ชจ์— ์ •์˜ํ•˜๋Š” ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

// โŒ ์ž˜๋ชป๋œ ์„ค๊ณ„
public abstract class Fare {
    // ๋ชจ๋“  ์ž์‹์˜ ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค ๊ฐ€์ง
    public int getUrgentFee() { return 0; }  // ์ผ๋ฐ˜ ์šด์ž„์€ 0
    public String getCurrency() { return "KRW"; }  // ์ผ๋ฐ˜์€ KRW
    public double getExchangeRate() { return 1.0; }  // ์ผ๋ฐ˜์€ 1.0
    // ... ๋ชจ๋“  ์ž์‹์˜ ๋ฉ”์„œ๋“œ โŒ
}

๋ฌธ์ œ:

  • ๋ถ€๋ชจ๊ฐ€ ์ž์‹๋“ค์˜ ๋ชจ๋“  ์ •๋ณด๋ฅผ ์•Œ์•„์•ผ ํ•จ (์ž˜๋ชป๋œ ์˜์กด)
  • ์ผ๋ฐ˜ ์šด์ž„์— ์˜๋ฏธ ์—†๋Š” ๋ฉ”์„œ๋“œ๋“ค (getUrgentFee() ๊ฐ€ ํ•ญ์ƒ 0)
  • ์ƒˆ ์ž์‹ ์ถ”๊ฐ€ ์‹œ ๋ถ€๋ชจ ์ˆ˜์ • ํ•„์š” (OCP ์œ„๋ฐ˜)
  • ๋นˆํ˜ˆ ๋ชจ๋ธ + God Class ์•ˆํ‹ฐํŒจํ„ด

instanceof ํ™œ์šฉ โ€” ์•ˆ์ „ํ•œ ์ฒ˜๋ฆฌ

public class FareReportService {
    public void printReport(List<Fare> fares) {
        for (Fare fare : fares) {
            // ๊ณตํ†ต ์ •๋ณด
            System.out.println("์šด์ž„ ID: " + fare.getId());
            System.out.println("์ด์•ก: " + fare.calculateTotal());
            
            // ํƒ€์ž…๋ณ„ ์ถ”๊ฐ€ ์ •๋ณด
            if (fare instanceof UrgentFare) {
                UrgentFare urgent = (UrgentFare) fare;
                System.out.println("๊ธด๊ธ‰๋น„: " + urgent.getUrgentFee());
            } else if (fare instanceof InternationalFare) {
                InternationalFare intl = (InternationalFare) fare;
                System.out.println("ํ†ตํ™”: " + intl.getCurrency());
                System.out.println("ํ™˜์œจ: " + intl.getExchangeRate());
            }
        }
    }
}

reportService.printReport(fares);
// ๋ชจ๋“  ์šด์ž„ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ โœ…

ํšจ๊ณผ:

  • ๊ฐ ํƒ€์ž…์„ ์•ˆ์ „ํ•˜๊ฒŒ ์‹๋ณ„
  • ์ž์‹์˜ ๊ณ ์œ  ๋ฉ”์„œ๋“œ ํ™œ์šฉ
  • ClassCastException ๋ฐฉ์–ด

๊ทธ๋Ÿฌ๋‚˜ โ€” instanceof๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์œผ๋ฉด ๋‹คํ˜•์„ฑ ์™ธ๋ฉด ์‹ ํ˜ธ โš ๏ธ

// โš ๏ธ ๋„ˆ๋ฌด ๋งŽ์€ instanceof โ€” ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉ ๋ชปํ•จ
public void process(Fare fare) {
    if (fare instanceof StandardFare) { ... }
    else if (fare instanceof UrgentFare) { ... }
    else if (fare instanceof InternationalFare) { ... }
    else if (fare instanceof DomesticFare) { ... }
    // ... ๋งค๋ฒˆ ์ถ”๊ฐ€
}

โ†’ ๋‹คํ˜•์„ฑ (Unit 2.4) ์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ instanceof๋กœ ํ’€๊ณ  ์žˆ๋‹ค๋Š” ์‹ ํ˜ธ.

์ง„์งœ ํ•ด๊ฒฐ:

public abstract class Fare {
    public abstract void printDetail();  // ๊ฐ ์ž์‹์ด ์•Œ์•„์„œ
}

public void process(Fare fare) {
    fare.printDetail();  // โœ… ๋‹คํ˜•์„ฑ!
}

โ†’ instanceof ๊ฐ€ ์ฝ”๋“œ์— ๋งŽ์ด ๋“ฑ์žฅํ•˜๋ฉด ์„ค๊ณ„ ์žฌ๊ฒ€ํ† .


โœ… 4. ํ•ด๊ฒฐ์ฑ… โ€” instanceof์™€ ํ˜•๋ณ€ํ™˜ ๋ฌธ๋ฒ•

instanceof ๊ธฐ๋ณธ ๋ฌธ๋ฒ•

๊ฐ์ฒด instanceof ํƒ€์ž…

๋ฐ˜ํ™˜๊ฐ’: boolean

  • true: ๊ฐ์ฒด๊ฐ€ ๊ทธ ํƒ€์ž… (๋˜๋Š” ์ž์†) ์ž„
  • false: ๊ทธ๋ ‡์ง€ ์•Š์Œ

๊ธฐ๋ณธ ์‚ฌ์šฉ

Animal a = new Dog();

a instanceof Dog;     // true โ€” Dog ์ธ์Šคํ„ด์Šค
a instanceof Animal;  // true โ€” Animal์˜ ์ž์†์ด๊ธฐ๋„ ํ•จ
a instanceof Object;  // true โ€” ๋ชจ๋“  ๊ฐ์ฒด๋Š” Object์˜ ์ž์†
a instanceof Cat;     // false โ€” Cat์ด ์•„๋‹˜
a instanceof String;  // ์ปดํŒŒ์ผ ์—๋Ÿฌ โ€” ๋ฌด๊ด€ํ•œ ํƒ€์ž…

ํ•ต์‹ฌ ๊ทœ์น™ โญ :

  • ์ž๊ธฐ ํƒ€์ž…๊ณผ ๋ชจ๋“  ๋ถ€๋ชจ ํƒ€์ž… ์— ๋Œ€ํ•ด true
  • ๋ฌด๊ด€ํ•œ ํƒ€์ž… ์€ ์ปดํŒŒ์ผ ์—๋Ÿฌ

null ์ฒ˜๋ฆฌ

Animal a = null;
a instanceof Dog;     // false (null์€ ์–ด๋–ค ํƒ€์ž…๋„ ์•„๋‹˜)
a instanceof Animal;  // false

โ†’ instanceof ๋Š” null ์•ˆ์ „. NullPointerException ์•ˆ ๋‚จ.

ํ™œ์šฉ:

// null ์ฒดํฌ + ํƒ€์ž… ์ฒดํฌ๋ฅผ ํ•œ ๋ฒˆ์—
if (obj instanceof String) {
    // obj๋Š” null์ด ์•„๋‹ˆ๊ณ , String์ž„
    String s = (String) obj;
}

// vs ์•ˆ ์ข‹์€ ์ฝ”๋“œ
if (obj != null && obj.getClass() == String.class) {
    // ๋” ๊ธธ๊ณ  ๋ช…์‹œ์ 
}

ํ˜•๋ณ€ํ™˜ (Type Casting) โญ

๋‘ ์ข…๋ฅ˜:

1. ์—…์บ์ŠคํŒ… (Upcasting) โ€” ์ž์‹ โ†’ ๋ถ€๋ชจ

Dog d = new Dog();
Animal a = d;  // โœ… ์•”์‹œ์  ์บ์ŠคํŒ… (์ž๋™)

๊ทœ์น™:

  • ์•”์‹œ์  (์ž๋™) โ€” ๋ช…์‹œ์  ์บ์ŠคํŒ… ํ‘œ์‹œ ๋ถˆํ•„์š”
  • ํ•ญ์ƒ ์•ˆ์ „ โ€” ์ž์‹์€ ๋ถ€๋ชจ์˜ ๋ชจ๋“  ๊ฒƒ ๊ฐ€์ง

๋‹คํ˜•์„ฑ์˜ ํ† ๋Œ€:

List<Animal> animals = new ArrayList<>();
animals.add(new Dog());  // Dog โ†’ Animal ์ž๋™ ์—…์บ์ŠคํŒ…
animals.add(new Cat());

2. ๋‹ค์šด์บ์ŠคํŒ… (Downcasting) โ€” ๋ถ€๋ชจ โ†’ ์ž์‹

Animal a = new Dog();
Dog d = (Dog) a;  // โœ… ๋ช…์‹œ์  ์บ์ŠคํŒ… ํ•„์š”

๊ทœ์น™:

  • ๋ช…์‹œ์  โ€” (ํƒ€์ž…) ํ‘œ์‹œ ํ•„์š”
  • ์œ„ํ—˜ โ€” ์ž˜๋ชปํ•˜๋ฉด ClassCastException
  • ์‚ฌ์ „ instanceof ๊ฒ€์‚ฌ ๊ถŒ์žฅ

์•ˆ์ „ํ•œ ๋‹ค์šด์บ์ŠคํŒ… ํŒจํ„ด โญ

Animal a = getAnimal();

if (a instanceof Dog) {
    Dog d = (Dog) a;  // ์•ˆ์ „
    d.bark();
}

Java 16+ ํŒจํ„ด ๋งค์นญ โญโญ (ํ˜„๋Œ€์  ๋ฌธ๋ฒ•)

Java 16๋ถ€ํ„ฐ instanceof + ์บ์ŠคํŒ…์„ ํ•œ ์ค„๋กœ:

// ์˜› ๋ฐฉ์‹
if (a instanceof Dog) {
    Dog d = (Dog) a;
    d.bark();
}

// Java 16+ ํŒจํ„ด ๋งค์นญ
if (a instanceof Dog d) {  // โ† ํ•œ ๋ฒˆ์—!
    d.bark();
}

๋” ๊ฐ„๊ฒฐํ•œ ์‚ฌ์šฉ:

// ๋ถ€์ • ์กฐ๊ฑด๊ณผ ๊ฒฐํ•ฉ
if (!(a instanceof Dog d)) {
    return;  // Dog ์•„๋‹ˆ๋ฉด ์ข…๋ฃŒ
}
d.bark();  // ์—ฌ๊ธฐ์„œ๋Š” d ์‚ฌ์šฉ ๊ฐ€๋Šฅ

// ์กฐ๊ฑด ๊ฒฐํ•ฉ
if (a instanceof Dog d && d.getAge() > 3) {
    d.bark();
}

Java 21+ Switch ํŒจํ„ด ๋งค์นญ (์ตœ์‹ )

public String describe(Animal a) {
    return switch (a) {
        case Dog d -> "๊ฐœ: " + d.getBreed();
        case Cat c -> "๊ณ ์–‘์ด: " + c.getName();
        case null -> "๋™๋ฌผ ์—†์Œ";
        default -> "์•Œ ์ˆ˜ ์—†๋Š” ๋™๋ฌผ";
    };
}

โ†’ if-else ์ง€์˜ฅ์„ ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐ.

ILIC ํ™œ์šฉ ๊ฐ€๋Šฅ:

public String describeFare(Fare fare) {
    return switch (fare) {
        case UrgentFare u -> "๊ธด๊ธ‰ (๊ธด๊ธ‰๋น„: " + u.getUrgentFee() + ")";
        case InternationalFare i -> "๊ตญ์ œ (" + i.getCurrency() + ")";
        case StandardFare s -> "์ผ๋ฐ˜";
        default -> "์•Œ ์ˆ˜ ์—†๋Š” ์šด์ž„";
    };
}

๐Ÿ—๏ธ 5. ๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ

instanceof ์˜ ๋‚ด๋ถ€ ๋™์ž‘

JVM์ด ์–ด๋–ป๊ฒŒ instanceof๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š”์ง€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Animal a = new Dog();
boolean result = a instanceof Dog;

JVM ๋‚ด๋ถ€ ํ๋ฆ„:

1. a๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด์˜ ํด๋ž˜์Šค ์ •๋ณด ํ™•์ธ
        โ†“
2. ๊ทธ ํด๋ž˜์Šค๊ฐ€ Dog์ธ์ง€ ํ™•์ธ
        โ†“
3. ์•„๋‹ˆ๋ฉด ๋ถ€๋ชจ ํด๋ž˜์Šค๋กœ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋ฉฐ ํ™•์ธ
   Dog โ†’ Animal โ†’ Object
        โ†“
4. ๋น„๊ต ๋Œ€์ƒ(Dog)์„ ๋ฐœ๊ฒฌํ•˜๋ฉด true
   ๋๊นŒ์ง€ ๋ชป ์ฐพ์œผ๋ฉด false

๋ฐ”์ดํŠธ์ฝ”๋“œ:

INSTANCEOF Dog  โ† JVM ๋ช…๋ น์–ด

โ†’ JVM์ด ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹จ์ˆœํ•˜๊ณ  ๋น ๋ฅธ ์—ฐ์‚ฐ.


ํ˜•๋ณ€ํ™˜์˜ ๋‚ด๋ถ€ ๋™์ž‘

Animal a = new Dog();
Dog d = (Dog) a;

JVM ๋‚ด๋ถ€ ํ๋ฆ„:

1. a๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด์˜ ์‹ค์ œ ํด๋ž˜์Šค ํ™•์ธ
        โ†“
2. ์บ์ŠคํŒ… ๋Œ€์ƒ(Dog)๊ณผ ํ˜ธํ™˜๋˜๋Š”์ง€ ๊ฒ€์ฆ
   - a๊ฐ€ Dog ๋˜๋Š” Dog์˜ ์ž์‹? โ†’ OK
   - ์•„๋‹ˆ๋ฉด โ†’ ClassCastException
        โ†“
3. d ๋ณ€์ˆ˜์— ๊ฐ™์€ ๊ฐ์ฒด ์ฐธ์กฐ ํ• ๋‹น
   - ๊ฐ์ฒด ์ž์ฒด๋Š” ๋ณ€ํ•˜์ง€ ์•Š์Œ โญ
   - ๋‹จ์ง€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…๋งŒ ๋‹ค๋ฆ„

๋ฐ”์ดํŠธ์ฝ”๋“œ:

CHECKCAST Dog  โ† JVM์ด ๊ฒ€์ฆ + ์บ์ŠคํŒ…

ํ•ต์‹ฌ ํ†ต์ฐฐ โ€” "์บ์ŠคํŒ…์€ ๊ฐ์ฒด๋ฅผ ๋ณ€ํ™˜ X" โญ

Animal a = new Dog();
Dog d = (Dog) a;

// a์™€ d๋Š” ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ด
System.out.println(a == d);  // true โœ…

์˜๋ฏธ:

  • ์บ์ŠคํŒ…์€ ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š์Œ
  • ๋‹จ์ง€ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ๋ณ€๊ฒฝ ํ•  ๋ฟ
  • Heap์˜ ๊ฐ์ฒด๋Š” ๊ทธ๋Œ€๋กœ

๋น„์œ :

  • ๊ฐ™์€ ์‚ฌ๋žŒ์ด ์ง์ฑ…์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ช…ํ•จ์„ ๊ฐ€์ง
  • ๋ช…ํ•จ์€ ๋‹ค๋ฅด์ง€๋งŒ ์‚ฌ๋žŒ์€ ๊ฐ™์Œ

๋ฉ”๋ชจ๋ฆฌ ๊ด€์ 

Animal a = new Dog();  // Heap์— Dog ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ, a๋Š” Animal ํƒ€์ž… ์ฐธ์กฐ
Dog d = (Dog) a;        // d๋„ ๊ฐ™์€ Dog ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ด

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ:

[Stack]
  a (Animal ํƒ€์ž… ์ฐธ์กฐ) โ”€โ”
  d (Dog ํƒ€์ž… ์ฐธ์กฐ)    โ”€โ”ค
                       โ†“
[Heap]
  Dog ์ธ์Šคํ„ด์Šค (1๊ฐœ๋งŒ ์กด์žฌ)
   - name
   - breed

โ†’ ์ฐธ์กฐ ๋ณ€์ˆ˜๋งŒ ์—ฌ๋Ÿฌ ๊ฐœ, ๊ฐ์ฒด๋Š” ํ•˜๋‚˜.


์ปดํŒŒ์ผ ์‹œ ์บ์ŠคํŒ… ๊ฒ€์ฆ

String s = "hello";
Integer i = (Integer) s;  // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ

์™œ?:

  • String๊ณผ Integer๋Š” ์ƒ์† ๊ด€๊ณ„ ์—†์Œ
  • ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ "์ ˆ๋Œ€ ์บ์ŠคํŒ… ๋ถˆ๊ฐ€" ํŒ๋‹จ
Animal a = new Dog();
Dog d = (Dog) a;  // โœ… ์ปดํŒŒ์ผ OK (๊ฐ€๋Šฅ์„ฑ ์žˆ์Œ)
                  // ๋‹จ, ๋Ÿฐํƒ€์ž„์— ๊ฒ€์ฆ

getClass() vs instanceof โญ

๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ• ๋น„๊ต:

Animal a = new Dog();

// ๋ฐฉ๋ฒ• 1: getClass()
a.getClass() == Dog.class;  // true (์ •ํ™•ํžˆ Dog)
a.getClass() == Animal.class;  // false (Dog๋Š” Animal์ด ์•„๋‹˜)

// ๋ฐฉ๋ฒ• 2: instanceof
a instanceof Dog;     // true
a instanceof Animal;  // true (์ž์† ๊ด€๊ณ„)

ํ•ต์‹ฌ ์ฐจ์ด โญ :

getClass()instanceof
๋น„๊ต ๋ฐฉ์‹์ •ํ™•ํžˆ ๊ฐ™์€ ํด๋ž˜์Šค์ž์† ํฌํ•จ
๋‹คํ˜•์„ฑXO
์‚ฌ์šฉ ๋นˆ๋„๋‚ฎ์Œ๋งค์šฐ ๋†’์Œ
์‚ฌ์šฉ ์ผ€์ด์Šคequals() ๊ตฌํ˜„ ๋“ฑ์ผ๋ฐ˜์ ์ธ ํƒ€์ž… ๊ฒ€์ฆ

equals() ์—์„œ์˜ ๋…ผ์Ÿ:

// ๋ฐฉ์‹ 1 โ€” instanceof (Joshua Bloch ๊ถŒ์žฅ)
@Override
public boolean equals(Object o) {
    if (!(o instanceof Customer)) return false;
    // ์ž์‹๋„ equals ๊ฐ€๋Šฅ (๋Œ€์นญ์„ฑ ๊นจ์งˆ ์ˆ˜ ์žˆ์Œ)
}

// ๋ฐฉ์‹ 2 โ€” getClass() (๋Œ€์นญ์„ฑ ๋ณด์žฅ)
@Override
public boolean equals(Object o) {
    if (o == null || getClass() != o.getClass()) return false;
    // ์ •ํ™•ํžˆ ๊ฐ™์€ ํด๋ž˜์Šค๋งŒ ๊ฐ™๋‹ค๊ณ  ํŒ๋‹จ
}

โ†’ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฆ„. 6์ฃผ์ฐจ์—์„œ ์ž์„ธํžˆ.


๐Ÿ’ป 6. ์‹ค์ „ ์ฝ”๋“œ ์˜ˆ์‹œ

์˜ˆ์‹œ 1: ILIC ์šด์ž„ ์ฒ˜๋ฆฌ โ€” ์•ˆ์ „ํ•œ ๋‹ค์šด์บ์ŠคํŒ…

public class FareReportService {
    
    public void printDetailedReport(List<Fare> fares) {
        for (Fare fare : fares) {
            // ๊ณตํ†ต ์ •๋ณด (๋‹คํ˜•์„ฑ)
            System.out.println("=== ์šด์ž„ #" + fare.getId() + " ===");
            System.out.println("์ด์•ก: " + fare.calculateTotal() + "์›");
            
            // ํƒ€์ž…๋ณ„ ์ถ”๊ฐ€ ์ •๋ณด (instanceof + ์บ์ŠคํŒ…)
            if (fare instanceof UrgentFare) {
                UrgentFare urgent = (UrgentFare) fare;
                System.out.println("๊ธด๊ธ‰๋น„: " + urgent.getUrgentFee() + "์›");
                System.out.println("๊ธด๊ธ‰ ์ฒ˜๋ฆฌ ์‚ฌ์œ : " + urgent.getUrgentReason());
            } else if (fare instanceof InternationalFare) {
                InternationalFare intl = (InternationalFare) fare;
                System.out.println("ํ†ตํ™”: " + intl.getCurrency());
                System.out.println("ํ™˜์œจ: " + intl.getExchangeRate());
                System.out.println("์ถœ๋ฐœ์ง€: " + intl.getOrigin());
                System.out.println("๋„์ฐฉ์ง€: " + intl.getDestination());
            }
        }
    }
}

์˜ˆ์‹œ 2: Java 16+ ํŒจํ„ด ๋งค์นญ ์‚ฌ์šฉ

public class FareReportService {
    
    public void printDetailedReport(List<Fare> fares) {
        for (Fare fare : fares) {
            System.out.println("=== ์šด์ž„ #" + fare.getId() + " ===");
            System.out.println("์ด์•ก: " + fare.calculateTotal() + "์›");
            
            // Java 16+ ํŒจํ„ด ๋งค์นญ โ€” ํ•œ ์ค„๋กœ ๊ฒ€์‚ฌ + ์บ์ŠคํŒ…
            if (fare instanceof UrgentFare urgent) {
                System.out.println("๊ธด๊ธ‰๋น„: " + urgent.getUrgentFee() + "์›");
            } else if (fare instanceof InternationalFare intl) {
                System.out.println("ํ†ตํ™”: " + intl.getCurrency<());
                System.out.println("ํ™˜์œจ: " + intl.getExchangeRate());
            }
        }
    }
}

โ†’ ๋ณ€์ˆ˜ ์„ ์–ธ์ด ํ•œ ๋ฒˆ์— ๋๋‚จ.


์˜ˆ์‹œ 3: Java 21+ Switch ํŒจํ„ด ๋งค์นญ

public class FareDescriptionService {
    
    public String describe(Fare fare) {
        return switch (fare) {
            case UrgentFare u -> 
                String.format("๊ธด๊ธ‰ ์šด์ž„ (๊ธด๊ธ‰๋น„: %d์›, ์‚ฌ์œ : %s)",
                    u.getUrgentFee(), u.getUrgentReason());
            case InternationalFare i -> 
                String.format("๊ตญ์ œ ์šด์ž„ (%s, ํ™˜์œจ %.2f)",
                    i.getCurrency(), i.getExchangeRate());
            case StandardFare s -> 
                "์ผ๋ฐ˜ ์šด์ž„";
            case null -> 
                "์šด์ž„ ์—†์Œ";
            default -> 
                "์•Œ ์ˆ˜ ์—†๋Š” ์šด์ž„ ํƒ€์ž…";
        };
    }
}

โ†’ if-else ์ง€์˜ฅ โ†’ ๊น”๋”ํ•œ switch.


์˜ˆ์‹œ 4: ์ปฌ๋ ‰์…˜์˜ ์•ˆ์ „ํ•œ ์ฒ˜๋ฆฌ

public class CustomerService {
    
    public void processCustomers(List<Customer> customers) {
        int vipCount = 0;
        int totalDiscount = 0;
        
        for (Customer customer : customers) {
            // ๊ณตํ†ต ์ฒ˜๋ฆฌ
            customer.register();
            
            // VIP๋งŒ์˜ ์ถ”๊ฐ€ ์ฒ˜๋ฆฌ
            if (customer instanceof VipCustomer vip) {
                vipCount++;
                totalDiscount += vip.getExtraVipDiscount();
                vip.sendVipNotification();
            }
            
            // ํŒŒํŠธ๋„ˆ๋งŒ์˜ ์ถ”๊ฐ€ ์ฒ˜๋ฆฌ
            if (customer instanceof PartnerCustomer partner) {
                partner.notifyPartnerTeam();
            }
        }
        
        System.out.println("VIP ์ˆ˜: " + vipCount);
        System.out.println("VIP ์ถ”๊ฐ€ ํ• ์ธ ์ด์•ก: " + totalDiscount);
    }
}

์˜ˆ์‹œ 5: ์•ˆํ‹ฐํŒจํ„ด โ€” instanceof ๋‚จ๋ฐœ

// โŒ ์•ˆ ์ข‹์€ ์ฝ”๋“œ โ€” ๋‹คํ˜•์„ฑ์„ ์™ธ๋ฉด
public class FareCalculator {
    public int calculate(Fare fare) {
        if (fare instanceof StandardFare s) {
            return s.getAmount();
        } else if (fare instanceof UrgentFare u) {
            return u.getAmount() + u.getUrgentFee();
        } else if (fare instanceof InternationalFare i) {
            return (int)(i.getAmount() * i.getExchangeRate());
        }
        return 0;
    }
}

๋ฌธ์ œ:

  • ์ƒˆ ์šด์ž„ ํƒ€์ž… ์ถ”๊ฐ€ ์‹œ ๋งค๋ฒˆ ์ˆ˜์ •
  • ๋‹คํ˜•์„ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

ํ•ด๊ฒฐ โ€” ๋‹คํ˜•์„ฑ ํ™œ์šฉ:

public abstract class Fare {
    public abstract int calculateTotal();  // ๊ฐ ์ž์‹์ด ๊ตฌํ˜„
}

public class FareCalculator {
    public int calculate(Fare fare) {
        return fare.calculateTotal();  // โœ… ๋‹คํ˜•์„ฑ!
    }
}

โ†’ instanceof ๊ฐ€ ์ž์ฃผ ๋ณด์ด๋ฉด ๋‹คํ˜•์„ฑ์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง.


์˜ˆ์‹œ 6: instanceof๊ฐ€ ์ •๋‹นํ•œ ๊ฒฝ์šฐ

์–ธ์ œ instanceof๊ฐ€ ์ ํ•ฉํ•œ๊ฐ€?

Case 1: ์™ธ๋ถ€ API ์‘๋‹ต ์ฒ˜๋ฆฌ

public void handleEvent(Object event) {
    if (event instanceof OrderCreatedEvent ev) {
        processOrder(ev);
    } else if (event instanceof PaymentCompletedEvent ev) {
        processPayment(ev);
    }
}

โ†’ ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ ํƒ€์ž…์„ ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ.

Case 2: ํ”Œ๋Ÿฌ๊ทธ์ธ / ์˜ต์…˜ ๊ธฐ๋Šฅ

public void register(Object service) {
    services.add(service);
    
    // ์ถ”๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ์—ฌ๋ถ€ ํ™•์ธ
    if (service instanceof Closeable closeable) {
        cleanupHandlers.add(closeable);
    }
    
    if (service instanceof Healthchecker checker) {
        healthCheckers.add(checker);
    }
}

โ†’ ์„ ํƒ์  ๊ธฐ๋Šฅ ์„ ์œ„ํ•œ instanceof.

Case 3: ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ / ํ”„๋ ˆ์ž„์›Œํฌ ํ†ตํ•ฉ

public void serialize(Object obj) {
    if (obj instanceof Serializable) {
        // ์ง๋ ฌํ™” ๊ฐ€๋Šฅ
    } else {
        throw new IllegalArgumentException("์ง๋ ฌํ™” ๋ถˆ๊ฐ€");
    }
}

โ†’ ๋งˆ์ปค ์ธํ„ฐํŽ˜์ด์Šค ํ™•์ธ.


์˜ˆ์‹œ 7: ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ์˜ instanceof

@Test
void ์šด์ž„_์ƒ์„ฑ_์‹œ_๊ธด๊ธ‰_์šด์ž„์ด๋ผ๋ฉด_๊ธด๊ธ‰๋น„๊ฐ€_์ถ”๊ฐ€๋œ๋‹ค() {
    Fare fare = fareService.create(new UrgentFareRequest(...));
    
    assertThat(fare).isInstanceOf(UrgentFare.class);  // ํƒ€์ž… ๊ฒ€์ฆ
    
    UrgentFare urgent = (UrgentFare) fare;
    assertThat(urgent.getUrgentFee()).isPositive();
}

โ†’ AssertJ๋Š” isInstanceOf() ๋ฅผ ์ œ๊ณต.


โš ๏ธ 7. ์ฃผ์˜์‚ฌํ•ญ & ํ”ํ•œ ์‹ค์ˆ˜

์‹ค์ˆ˜ 1: ClassCastException ๋ฐฉ์น˜

// โŒ instanceof ๊ฒ€์‚ฌ ์—†์ด ์บ์ŠคํŒ…
public void process(Animal a) {
    Dog d = (Dog) a;  // a๊ฐ€ Cat์ด๋ฉด ์ฆ‰์‹œ ํญ๋ฐœ
    d.bark();
}

ํ•ด๊ฒฐ:

public void process(Animal a) {
    if (a instanceof Dog d) {
        d.bark();
    }
}

์‹ค์ˆ˜ 2: instanceof ๋‚จ๋ฐœ โ€” ๋‹คํ˜•์„ฑ ์™ธ๋ฉด โญ

// โŒ ๋‹คํ˜•์„ฑ์„ ์•ˆ ์”€
public int calculate(Shape shape) {
    if (shape instanceof Circle c) {
        return (int)(Math.PI * c.getRadius() * c.getRadius());
    } else if (shape instanceof Rectangle r) {
        return r.getWidth() * r.getHeight();
    } else if (shape instanceof Triangle t) {
        return t.getBase() * t.getHeight() / 2;
    }
    return 0;
}

ํ•ด๊ฒฐ โ€” ๋‹คํ˜•์„ฑ:

public abstract class Shape {
    public abstract int calculateArea();  // ๊ฐ ์ž์‹์ด ๊ตฌํ˜„
}

public int calculate(Shape shape) {
    return shape.calculateArea();  // โœ…
}

โ†’ instanceof ๋ถ„๊ธฐ๊ฐ€ 3๊ฐœ ์ด์ƒ์ด๋ฉด ๋‹คํ˜•์„ฑ์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง ๊ฒ€ํ† .


์‹ค์ˆ˜ 3: ๋ฌด๊ด€ํ•œ ํƒ€์ž… ๋น„๊ต

String s = "hello";
if (s instanceof Integer) {  // โŒ ์ปดํŒŒ์ผ ์—๋Ÿฌ
    // ...
}

โ†’ String๊ณผ Integer๋Š” ์ƒ์† ๊ด€๊ณ„ ์—†์Œ. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์žก์Œ.

์˜ˆ์™ธ โ€” Object ๋ณ€์ˆ˜:

Object obj = "hello";
if (obj instanceof Integer) {  // โœ… ์ปดํŒŒ์ผ OK (๋Ÿฐํƒ€์ž„์— false)
    // ...
}

โ†’ Object ํƒ€์ž…์€ ์–ด๋–ค ๊ฐ์ฒด๋“  ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ์–ด์„œ ์ปดํŒŒ์ผ์€ ํ†ต๊ณผ.


์‹ค์ˆ˜ 4: null ์ฒดํฌ ์—†์ด ์บ์ŠคํŒ…

Animal a = null;
Dog d = (Dog) a;  // โœ… ์ปดํŒŒ์ผ OK, ๋Ÿฐํƒ€์ž„ OK (d๋Š” null)
d.bark();          // ๐Ÿ’ฅ NullPointerException

ํ•ด๊ฒฐ:

if (a instanceof Dog d) {  // null์ด๋ฉด false
    d.bark();
}

โ†’ instanceof ๊ฐ€ ์ž๋™์œผ๋กœ null ์ฒ˜๋ฆฌํ•ด์คŒ.


์‹ค์ˆ˜ 5: ์ˆœ์„œ ์ž˜๋ชป โ€” ๊ฐ€์žฅ ๊ตฌ์ฒด์  ํƒ€์ž…๋ถ€ํ„ฐ โญ (์ž๊ธฐ ์ ๊ฒ€ Q1 ๊ด€๋ จ)

public class Cat extends Animal { ... }
public class Persian extends Cat { ... }

Animal a = new Persian();

// โŒ ์ž˜๋ชป๋œ ์ˆœ์„œ
if (a instanceof Cat c) {
    System.out.println("๊ณ ์–‘์ด ์ฒ˜๋ฆฌ");
} else if (a instanceof Persian p) {  // ์ ˆ๋Œ€ ๋„๋‹ฌ X (์ด๋ฏธ Cat์—์„œ ์žกํž˜)
    System.out.println("ํŽ˜๋ฅด์‹œ์•ˆ ์ฒ˜๋ฆฌ");
}

// โœ… ์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ โ€” ๊ฐ€์žฅ ๊ตฌ์ฒด์ ์ธ ๊ฒƒ๋ถ€ํ„ฐ
if (a instanceof Persian p) {
    System.out.println("ํŽ˜๋ฅด์‹œ์•ˆ ์ฒ˜๋ฆฌ");
} else if (a instanceof Cat c) {
    System.out.println("๊ณ ์–‘์ด ์ฒ˜๋ฆฌ");
}

๊ทœ์น™: ์ž์‹ โ†’ ๋ถ€๋ชจ ์ˆœ์„œ.


์‹ค์ˆ˜ 6: instanceof์™€ equals() ์ž˜๋ชป๋œ ๊ฒฐํ•ฉ

// โŒ ์œ„ํ—˜ํ•œ equals
@Override
public boolean equals(Object o) {
    if (o instanceof Customer) {
        // ์ž์‹๋„ ํ†ต๊ณผ โ†’ ๋Œ€์นญ์„ฑ ๊นจ์งˆ ์ˆ˜ ์žˆ์Œ
    }
}

VipCustomer v = new VipCustomer(1L);
Customer c = new Customer(1L);

v.equals(c);  // true (Vip์ด Customer๋กœ ๋น„๊ต)
c.equals(v);  // ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ โš ๏ธ โ€” ๋Œ€์นญ์„ฑ ๊นจ์ง

โ†’ 6์ฃผ์ฐจ์—์„œ ๊นŠ์ด ๋‹ค๋ฃฐ ์ฃผ์ œ.


์‹ค์ˆ˜ 7: ์˜›๋‚  ์Šคํƒ€์ผ ์‚ฌ์šฉ (Java 16+ ๋ฌด์‹œ)

// ์˜› ์Šคํƒ€์ผ โ€” ๋ณ€์ˆ˜ ๋‘ ๋ฒˆ ์„ ์–ธ
if (obj instanceof String) {
    String s = (String) obj;
    // ...
}

// ํ˜„๋Œ€ ์Šคํƒ€์ผ (Java 16+)
if (obj instanceof String s) {
    // ํ•œ ๋ฒˆ์— ๋
}

โ†’ Java 16+ ํ™˜๊ฒฝ์ด๋ฉด ํŒจํ„ด ๋งค์นญ ์ ๊ทน ํ™œ์šฉ.


์‹ค์ˆ˜ 8: ClassCastException์„ catch๋กœ ์ฒ˜๋ฆฌ

// โŒ ์•ˆํ‹ฐํŒจํ„ด
try {
    Dog d = (Dog) a;
    d.bark();
} catch (ClassCastException e) {
    // ๋ฌด์‹œ
}

๋ฌธ์ œ:

  • ์˜ˆ์™ธ๋Š” ๋А๋ฆผ (Stack trace ์ƒ์„ฑ ๋น„์šฉ)
  • ์˜๋„๊ฐ€ ๋ถˆ๋ช…ํ™•
  • instanceof๋กœ ์‚ฌ์ „ ์˜ˆ๋ฐฉ์ด ํ‘œ์ค€

ํ•ด๊ฒฐ:

if (a instanceof Dog d) {
    d.bark();
}

๐Ÿ”— 8. ์—ฐ๊ด€ ๊ฐœ๋… ๋งต

์ง์ ‘ ์ด์–ด์ง€๋Š” ํ•™์Šต

[Unit 2.4: ๋‹คํ˜•์„ฑ]
        โ†“
[Unit 2.5: instanceof์™€ ํ˜•๋ณ€ํ™˜]  โ† ์ง€๊ธˆ ์—ฌ๊ธฐ
        โ†“
[Unit 2.6: Nested/Inner/Anonymous]

์ด Unit์˜ ๊ฐœ๋…์ด ํ™œ์šฉ๋˜๋Š” ๊ณณ

1์ฃผ์ฐจ ๋‚ด:

  • Phase 3 (SOLID): LSP โ€” ์•ˆ์ „ํ•œ ๋ถ€๋ชจ-์ž์‹ ์น˜ํ™˜
  • Phase 6 (์ปฌ๋ ‰์…˜): equals/hashCode ๊ตฌํ˜„ ์‹œ instanceof

๋ฏธ๋ž˜ ์ฃผ์ฐจ:

  • 3์ฃผ์ฐจ (์ œ๋„ค๋ฆญ): Bounded Type Parameter โ€” <T extends Number> ๋“ฑ
  • 5์ฃผ์ฐจ (Spring): ๋นˆ ํƒ€์ž… ์ฒดํฌ, ApplicationContextAware
  • 8-9์ฃผ์ฐจ (AOP): Proxy ๊ฐ์ฒด ์ฒ˜๋ฆฌ
  • 15์ฃผ์ฐจ (Spring MVC): HandlerMethod ์ฒ˜๋ฆฌ
  • 17์ฃผ์ฐจ (์ด๋ฒคํŠธ ์‹œ์Šคํ…œ): ApplicationEvent ์ฒ˜๋ฆฌ

๋‹คํ˜•์„ฑ, instanceof, ํ˜•๋ณ€ํ™˜์˜ ์‚ผ๊ฐ๊ด€๊ณ„ โญ

[๋‹คํ˜•์„ฑ (Unit 2.4)]
"๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ์ž์‹ ๊ฐ์ฒด ์ฒ˜๋ฆฌ"
        โ†“
   ํ•˜์ง€๋งŒ ์ž์‹ ๊ณ ์œ  ๋ฉ”์„œ๋“œ๋Š”?
        โ†“
[ํ˜•๋ณ€ํ™˜ (Unit 2.5)]
"๋ถ€๋ชจ ํƒ€์ž…์„ ์ž์‹ ํƒ€์ž…์œผ๋กœ"
        โ†“
   ์ž˜๋ชป ์บ์ŠคํŒ…ํ•˜๋ฉด ์œ„ํ—˜
        โ†“
[instanceof (Unit 2.5)]
"์•ˆ์ „ํ•˜๊ฒŒ ํƒ€์ž… ํ™•์ธ"

์„ธ ๊ฐ€์ง€๊ฐ€ ํ•œ ์„ธํŠธ โ€” ํ•˜๋‚˜๋งŒ ์•Œ์•„๋„ ๋ถ€์กฑ.


๋ฉด์ ‘ ๋‹จ๊ณจ ์งˆ๋ฌธ ๋งคํ•‘

์งˆ๋ฌธ์ด Unit์—์„œ์˜ ๋‹ต
"instanceof๊ฐ€ ๋ญ”๊ฐ€์š”?"๊ฐ์ฒด๊ฐ€ ํŠน์ • ํƒ€์ž…์ธ์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ์—ฐ์‚ฐ์ž
"๋‹ค์šด์บ์ŠคํŒ…์ด ์œ„ํ—˜ํ•œ ์ด์œ ?"ClassCastException ๊ฐ€๋Šฅ โ€” instanceof ์‚ฌ์ „ ๊ฒ€์‚ฌ ํ•„์š”
"instanceof์™€ getClass()์˜ ์ฐจ์ด?"instanceof๋Š” ์ž์† ํฌํ•จ, getClass()๋Š” ์ •ํ™•ํ•œ ํƒ€์ž…
"ํŒจํ„ด ๋งค์นญ์ด ๋ญ”๊ฐ€์š”?"Java 16+ ์˜ instanceof + ๋ณ€์ˆ˜ ์„ ์–ธ ๊ฒฐํ•ฉ ๋ฌธ๋ฒ•
"instanceof ๋‚จ๋ฐœ์˜ ๋ฌธ์ œ?"๋‹คํ˜•์„ฑ์„ ํ™œ์šฉ ๋ชปํ•จ โ€” ์„ค๊ณ„ ์žฌ๊ฒ€ํ†  ์‹ ํ˜ธ

๐Ÿ“ 9. ํ•ต์‹ฌ ์š”์•ฝ โ€” 3์ค„ ์ •๋ฆฌ

1๏ธโƒฃ instanceof๋Š” ๋‹คํ˜•์„ฑ์˜ ์•ˆ์ „์žฅ์น˜๋‹ค.

๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ์ž์‹ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃจ๋‹ค๊ฐ€ ์ž์‹์˜ ๊ณ ์œ  ๋ฉ”์„œ๋“œ ๋ฅผ ์“ฐ๋ ค๋ฉด ๋‹ค์šด์บ์ŠคํŒ…์ด ํ•„์š”ํ•œ๋ฐ, ์ž˜๋ชป ์บ์ŠคํŒ…ํ•˜๋ฉด ClassCastException์ด ๋ฐœ์ƒํ•œ๋‹ค. instanceof ๋กœ ์‚ฌ์ „ ํƒ€์ž… ๊ฒ€์ฆ ํ›„ ์•ˆ์ „ํ•˜๊ฒŒ ์บ์ŠคํŒ…ํ•˜๋Š” ๊ฒŒ ํ‘œ์ค€ ํŒจํ„ด์ด๋‹ค.

2๏ธโƒฃ Java 16+ ํŒจํ„ด ๋งค์นญ์œผ๋กœ ํ•œ ์ค„์— ๋๋‚ธ๋‹ค.

์˜› ๋ฐฉ์‹ (if (a instanceof Dog) { Dog d = (Dog) a; ... }) ๋Œ€์‹  if (a instanceof Dog d) { d.bark(); } ๋กœ ๊ฒ€์‚ฌ + ์บ์ŠคํŒ… + ๋ณ€์ˆ˜ ์„ ์–ธ์„ ํ•œ ๋ฒˆ์—. Java 21+์—์„œ๋Š” switch ํŒจํ„ด ๋งค์นญ์œผ๋กœ if-else ์ง€์˜ฅ์„ ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐ.

3๏ธโƒฃ instanceof๊ฐ€ ๋งŽ์œผ๋ฉด ๋‹คํ˜•์„ฑ์„ ์™ธ๋ฉดํ•œ๋‹ค๋Š” ์‹ ํ˜ธ๋‹ค.

๋ถ„๊ธฐ๊ฐ€ 3๊ฐœ ์ด์ƒ์ด๋ฉด ๋‹คํ˜•์„ฑ์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง ๊ฒ€ํ† . ๋‹จ, ์™ธ๋ถ€ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ, ์˜ต์…˜ ์ธํ„ฐํŽ˜์ด์Šค ํ™•์ธ, ๋งˆ์ปค ์ธํ„ฐํŽ˜์ด์Šค ๊ฒ€์‚ฌ ๊ฐ™์€ ์ •๋‹นํ•œ ์‚ฌ์šฉ ์ผ€์ด์Šค๋Š” ์žˆ๋‹ค. ๋˜ํ•œ ๋‹ค์šด์บ์ŠคํŒ… ์‹œ ๊ฐ€์žฅ ๊ตฌ์ฒด์ ์ธ ์ž์‹ ํƒ€์ž…๋ถ€ํ„ฐ ๊ฒ€์‚ฌํ•ด์•ผ ์ •ํ™•ํ•˜๋‹ค.


๐ŸŽ“ ํ•™์Šต ์ž๊ธฐ ์ ๊ฒ€

๊ธฐ๋ณธ ์ดํ•ด

  • instanceof์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…๊ณผ ๋™์ž‘ ๋ฐฉ์‹์„ ์•ˆ๋‹ค
  • ์—…์บ์ŠคํŒ…๊ณผ ๋‹ค์šด์บ์ŠคํŒ…์˜ ์ฐจ์ด๋ฅผ ์•ˆ๋‹ค
  • ClassCastException์ด ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์„ ์•ˆ๋‹ค
  • Java 16+ ํŒจํ„ด ๋งค์นญ ๋ฌธ๋ฒ•์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค

์‹ค์ „ ์ ์šฉ

  • ILIC ์ฝ”๋“œ์—์„œ instanceof๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
  • instanceof ๋‚จ๋ฐœ ์ฝ”๋“œ๋ฅผ ๋‹คํ˜•์„ฑ์œผ๋กœ ๋ฆฌํŒฉํ† ๋งํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๊ฐ€์žฅ ๊ตฌ์ฒด์ ์ธ ์ž์‹ ํƒ€์ž…๋ถ€ํ„ฐ ๊ฒ€์‚ฌํ•˜๋Š” ์ˆœ์„œ๋ฅผ ์ง€ํ‚จ๋‹ค
  • ์˜› instanceof + ์บ์ŠคํŒ…์„ ํŒจํ„ด ๋งค์นญ์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค

๋ฉด์ ‘ ๋Œ€๋น„ (1-2๋ถ„ ๋‹ต๋ณ€)

  • "instanceof์™€ ํ˜•๋ณ€ํ™˜์˜ ๊ด€๊ณ„๋Š”?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "ClassCastException์„ ์–ด๋–ป๊ฒŒ ๋ฐฉ์ง€ํ•˜๋‚˜์š”?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "instanceof์™€ getClass()์˜ ์ฐจ์ด?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ
  • "instanceof๋ฅผ ์•ˆ ์จ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š”?" ๋‹ต๋ณ€ ๊ฐ€๋Šฅ

์ž๊ธฐ ์ ๊ฒ€ ์งˆ๋ฌธ ๋‹ต๋ณ€

Q1: ๋ถ€๋ชจ ํƒ€์ž…์„ ์ž์‹ ํƒ€์ž…์œผ๋กœ ์บ์ŠคํŒ…ํ•˜๊ธฐ ์ „์— ์™œ instanceof ๊ฒ€์‚ฌ๊ฐ€ ํ•„์š”ํ•œ๊ฐ€?

ํ•œ ๋ฌธ์žฅ: ClassCastException์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด.

์ƒ์„ธ ์„ค๋ช…:

๋‹ค์šด์บ์ŠคํŒ… (๋ถ€๋ชจ โ†’ ์ž์‹) ์€ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ฒ€์ฆํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค:

Animal a = getAnimal();  // ์‹ค์ œ ๊ฐ์ฒด๋Š” ๋Ÿฐํƒ€์ž„์— ๊ฒฐ์ •
Dog d = (Dog) a;          // ์ปดํŒŒ์ผ๋Ÿฌ: "์บ์ŠคํŒ…ํ•˜๊ฒ ๋‹ค"๋งŒ ํ™•์ธ

์ปดํŒŒ์ผ๋Ÿฌ๋Š” "Animal ๋ณ€์ˆ˜๋ฅผ Dog๋กœ ์บ์ŠคํŒ…ํ•˜๊ฒ ๋‹ค" ๋งŒ ๋ณด๊ณ , ์‹ค์ œ๋กœ ๊ฐ€๋Šฅํ•œ์ง€๋Š” ๋ชจ๋ฆ„. ์‹ค์ œ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋Š” ๋Ÿฐํƒ€์ž„์— JVM์ด ๊ฒ€์ฆ.

์ž˜๋ชป ์บ์ŠคํŒ… ์‹œ:

Animal a = new Cat();  // ์‹ค์ œ๋Š” Cat
Dog d = (Dog) a;        // ๐Ÿ’ฅ ClassCastException
                        // โ€” JVM์ด ๋Ÿฐํƒ€์ž„์— "Cat์€ Dog ์•„๋‹˜" ๋ฐœ๊ฒฌ

instanceof ๊ฒ€์‚ฌ๋กœ ์‚ฌ์ „ ๋ฐฉ์–ด:

Animal a = new Cat();

if (a instanceof Dog) {  // false โ†’ ์บ์ŠคํŒ… ์‹œ๋„ ์•ˆ ํ•จ
    Dog d = (Dog) a;
    d.bark();
} else {
    // ์•ˆ์ „ํ•œ ๋Œ€์ฒด ์ฒ˜๋ฆฌ
}

Java 16+ ํŒจํ„ด ๋งค์นญ์œผ๋กœ ๋” ๊น”๋”ํ•˜๊ฒŒ:

if (a instanceof Dog d) {  // ๊ฒ€์‚ฌ + ์บ์ŠคํŒ…์„ ํ•œ ๋ฒˆ์—
    d.bark();
}

ํ•ต์‹ฌ ํ†ต์ฐฐ โญ :

"์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋‹ค์šด์บ์ŠคํŒ…์˜ ๊ฐ€๋Šฅ์„ฑ๋งŒ ํ™•์ธํ•˜๊ณ , ์‹ค์ œ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋Š” ๋Ÿฐํƒ€์ž„์— ๊ฒฐ์ •๋œ๋‹ค.
๊ทธ๋ž˜์„œ instanceof๋กœ ์‚ฌ์ „ ๊ฒ€์ฆ์ด ์•ˆ์ „ํ•œ ํŒจํ„ด์ด๋‹ค."

์˜ˆ์™ธ โ€” 100% ํ™•์‹คํ•œ ๊ฒฝ์šฐ:

public void process(Object obj) {
    String s = obj.toString();  // toString() ๊ฒฐ๊ณผ๋Š” ํ•ญ์ƒ String
    // ์บ์ŠคํŒ… ๋ถˆํ•„์š”
}

โ†’ ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋ช…ํ™•ํ•˜๋ฉด ์บ์ŠคํŒ…๋„ ๋ถˆํ•„์š”.


Q2: Object instanceof String ์ด false์ผ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋Š”?

๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ฒฝ์šฐ:

1. Object ๋ณ€์ˆ˜๊ฐ€ String์ด ์•„๋‹Œ ๋‹ค๋ฅธ ํƒ€์ž…

Object obj = 42;  // Integer
obj instanceof String;  // false

2. Object ๋ณ€์ˆ˜๊ฐ€ null

Object obj = null;
obj instanceof String;  // false (null์€ ์–ด๋–ค ํƒ€์ž…๋„ ์•„๋‹˜)

3. Object ๋ณ€์ˆ˜๊ฐ€ String์˜ ๋ถ€๋ชจ ํƒ€์ž…

Object obj = new Object();  // ์ •ํ™•ํžˆ Object
obj instanceof String;  // false (Object๋Š” String์˜ ๋ถ€๋ชจ์ด์ง€ ์ž์†์ด ์•„๋‹˜)

์™œ false์ธ๊ฐ€ โ€” instanceof ์˜ ๋™์ž‘ ๊ทœ์น™:

"๊ฐ์ฒด๊ฐ€ ๊ทธ ํƒ€์ž… ๋˜๋Š” ๊ทธ ํƒ€์ž…์˜ ์ž์†์ธ ๊ฒฝ์šฐ ์—๋งŒ true"

ํ•ต์‹ฌ ์ •๋ฆฌ:

Object obj ์˜ ์‹ค์ œ ํƒ€์ž…obj instanceof String
nullfalse
Object (์ •ํ™•ํžˆ)false
Integerfalse
Stringtrue
String์˜ ์ž์‹ (์—†์Œ โ€” final ํด๋ž˜์Šค)true

๋น„์œ :

  • "์ด ์‚ฌ๋žŒ์ด ๋ฐ•์”จ ํ›„์†์ธ๊ฐ€?" ๋ฌผ์œผ๋ฉด
  • ๋ณธ์ธ์ด ๋ฐ•์”จ โ†’ true
  • ๋ถ€๋ชจ/์กฐ๋ถ€๋ชจ๊ฐ€ ๋ฐ•์”จ์ด์ง€๋งŒ ๋ณธ์ธ์€ ๋‹ค๋ฅธ ์„ฑ์”จ โ†’ false

โ†’ instanceof๋Š” ์ž๊ธฐ ๋˜๋Š” ์ž์† ๋งŒ true.

์ฐธ๊ณ  โ€” String์˜ ํŠน์ˆ˜์„ฑ:

  • String์€ final ํด๋ž˜์Šค โ†’ ์ž์‹ ํด๋ž˜์Šค ์—†์Œ
  • ๊ทธ๋ž˜์„œ instanceof String ์ด true๋ฉด ์ •ํ™•ํžˆ String

๋‹ค์Œ Unit์œผ๋กœ

  • Nested/Inner/Anonymous ํด๋ž˜์Šค ๋ฅผ ํ•™์Šตํ•  ์ค€๋น„ ์™„๋ฃŒ
  • "ํด๋ž˜์Šค ์•ˆ์— ๋˜ ํด๋ž˜์Šค๋ฅผ?" ๊ฐ€ ๊ถ๊ธˆํ•˜๋‹ค
  • ๋žŒ๋‹ค์˜ ์ „์‹ ์„ ๋งŒ๋‚  ์ค€๋น„ ์™„๋ฃŒ
profile
Software Developer

0๊ฐœ์˜ ๋Œ“๊ธ€