F-lab Java 1์ฃผ์ฐจ / Phase 2 / Unit 2.5 ๋ณธ๊ฒฉ ํ์ต ์๋ฃ
9-์น์ ๋ง์คํฐ ํ๋กฌํํธ ํ์์ผ๋ก ๊น์ด ํํค์น๋ค.์ ์ ์ง์: Unit 2.4 (๋คํ์ฑ)
๋ค์ Unit: 2.6 โ Nested/Inner/Anonymous ํด๋์ค์ด Unit์ ์๋ฏธ: ๋คํ์ฑ์ ์์ ์ฅ์น. ClassCastException์ ๋ฐฉ์งํ๊ณ , ์์์ ๊ณ ์ ๋ฉ์๋๋ฅผ ์์ ํ๊ฒ ํธ์ถํ๋ ๋๊ตฌ.
๋น์ ์ด ์ด๋ฅธ์ฉ ํ์ฌ์ ๋ค์ด๊ฐ๋ ค๊ณ ํฉ๋๋ค. ์ ๊ตฌ์ ๋ณด์ ์ง์์ด ๋ฌป์ต๋๋ค:
"์ด๋ถ์ด ์ ๋ง ์ฑ์ธ์ด ๋ง๋์ง ํ์ธํ๊ฒ ์ต๋๋ค."
์ง์์ด ์ ๋ถ์ฆ์ ๋ณด๊ณ ํ์ธ:
ํต์ฌ:
โ instanceof ๊ฐ ์๋ฐ์์ ํ๋ ์ญํ .
์ผ๊ตฌ ์ ์๊ฐ ๊ฒฝ๊ธฐ ํ ์ ๋ํผ์ ๊ฐ์์ ๋๋ค๊ณ ํฉ์๋ค.
์ํฉ:
๊ฐ์ ์ฌ๋ ์ธ๋ฐ:
ํต์ฌ:
โ ์ด๊ฒ ํ๋ณํ (Type Casting).
์๊ธ์ค์ ํ์๊ฐ ๋์ฐฉํฉ๋๋ค. ์์ฌ๊ฐ:
1. instanceof โ ์ ์ ํ์ธ
"์ด ํ์๋ ์ฑ์ธ์ธ๊ฐ? ์ด๋ฆฐ์ด์ธ๊ฐ?"
โ
2. ํ๋ณํ โ ์ ์ ํ ๋๊ตฌ ์ค๋น
"์ด๋ฆฐ์ด๋ผ๋ฉด โ ์์๊ณผ ๋๊ตฌ"
"์ฑ์ธ์ด๋ผ๋ฉด โ ์ฑ์ธ ๋๊ตฌ"
โ
3. ์์ ํด๋์ค๋ง์ ๋ฉ์๋ ํธ์ถ
"์ด๋ฆฐ์ด์๊ฒ๋ ์ด๋ฆฐ์ด์ฉ ์ฝ ์ฒ๋ฐฉ"
์๋ชป๋ ์ฒ๋ฆฌ:
โ instanceof๋ก ๋จผ์ ํ์ธ โ ์์ ํ ํ๋ณํ โ ์์์ ๊ณ ์ ๋ฉ์๋ ์ฌ์ฉ
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 ์๋");
}
ํจ๊ณผ:
"๋คํ์ฑ์ ๊ฐ๋ ฅํ์ง๋ง ์์์ ๊ณ ์ ๋ฅ๋ ฅ์ ์ฐ๋ ค๋ฉด ํ๋ณํ์ด ํ์ํ๋ค.
๊ทธ ํ๋ณํ์ ์ํํ๋ฏ๋กinstanceof๋ผ๋ ์์ ์ฅ์น๋ฅผ ๊ฑฐ์ณ์ผ ํ๋ค."
๋คํ์ฑ, instanceof, ํ๋ณํ์ ์ธ ๊ฐ์ง๊ฐ ํจ๊ป ๊ฐ๋ ํ ์ธํธ.
instanceof ์์ด ํ๋ณํ์ ๋จ๋ฐํ๋ฉด ์ด๋ค ๋ฌธ์ ๊ฐ ์๊ธฐ๋์ง ๋ณด๊ฒ ์ต๋๋ค.
๋ค์ํ ์ด์ ์ข ๋ฅ (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; }
}
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. ๊ณ ๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ค ๋ค์ด โ ์๋น์ค ์ฅ์
๋์์ผ๋ก ๋ชจ๋ ๋ฉ์๋๋ฅผ ๋ถ๋ชจ์ ์ ์ํ๋ ์ฌ๋์ด ์์ต๋๋ค:
// โ ์๋ชป๋ ์ค๊ณ
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)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);
// ๋ชจ๋ ์ด์ ์์ ํ๊ฒ ์ฒ๋ฆฌ โ
ํจ๊ณผ:
// โ ๏ธ ๋๋ฌด ๋ง์ 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 ๊ฐ ์ฝ๋์ ๋ง์ด ๋ฑ์ฅํ๋ฉด ์ค๊ณ ์ฌ๊ฒํ .
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; // ์ปดํ์ผ ์๋ฌ โ ๋ฌด๊ดํ ํ์
ํต์ฌ ๊ท์น โญ :
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) {
// ๋ ๊ธธ๊ณ ๋ช
์์
}
๋ ์ข ๋ฅ:
Dog d = new Dog();
Animal a = d; // โ
์์์ ์บ์คํ
(์๋)
๊ท์น:
๋คํ์ฑ์ ํ ๋:
List<Animal> animals = new ArrayList<>();
animals.add(new Dog()); // Dog โ Animal ์๋ ์
์บ์คํ
animals.add(new Cat());
Animal a = new Dog();
Dog d = (Dog) a; // โ
๋ช
์์ ์บ์คํ
ํ์
๊ท์น:
(ํ์
) ํ์ ํ์Animal a = getAnimal();
if (a instanceof Dog) {
Dog d = (Dog) a; // ์์
d.bark();
}
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();
}
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 -> "์ ์ ์๋ ์ด์";
};
}
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์ด ๊ฒ์ฆ + ์บ์คํ
Animal a = new Dog();
Dog d = (Dog) a;
// a์ d๋ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํด
System.out.println(a == d); // true โ
์๋ฏธ:
๋น์ :
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; // โ ์ปดํ์ผ ์๋ฌ
์?:
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 | |
|---|---|---|
| ๋น๊ต ๋ฐฉ์ | ์ ํํ ๊ฐ์ ํด๋์ค | ์์ ํฌํจ |
| ๋คํ์ฑ | X | O |
| ์ฌ์ฉ ๋น๋ | ๋ฎ์ | ๋งค์ฐ ๋์ |
| ์ฌ์ฉ ์ผ์ด์ค | 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์ฃผ์ฐจ์์ ์์ธํ.
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());
}
}
}
}
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());
}
}
}
}
โ ๋ณ์ ์ ์ธ์ด ํ ๋ฒ์ ๋๋จ.
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.
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);
}
}
// โ ์ ์ข์ ์ฝ๋ โ ๋คํ์ฑ์ ์ธ๋ฉด
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 ๊ฐ ์์ฃผ ๋ณด์ด๋ฉด ๋คํ์ฑ์ผ๋ก ๋ฆฌํฉํ ๋ง.
์ธ์ instanceof๊ฐ ์ ํฉํ๊ฐ?
public void handleEvent(Object event) {
if (event instanceof OrderCreatedEvent ev) {
processOrder(ev);
} else if (event instanceof PaymentCompletedEvent ev) {
processPayment(ev);
}
}
โ ์ด๋ฒคํธ ์์คํ ์ฒ๋ผ ํ์ ์ ๋ฏธ๋ฆฌ ์ ์ ์๋ ๊ฒฝ์ฐ.
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.
public void serialize(Object obj) {
if (obj instanceof Serializable) {
// ์ง๋ ฌํ ๊ฐ๋ฅ
} else {
throw new IllegalArgumentException("์ง๋ ฌํ ๋ถ๊ฐ");
}
}
โ ๋ง์ปค ์ธํฐํ์ด์ค ํ์ธ.
@Test
void ์ด์_์์ฑ_์_๊ธด๊ธ_์ด์์ด๋ผ๋ฉด_๊ธด๊ธ๋น๊ฐ_์ถ๊ฐ๋๋ค() {
Fare fare = fareService.create(new UrgentFareRequest(...));
assertThat(fare).isInstanceOf(UrgentFare.class); // ํ์
๊ฒ์ฆ
UrgentFare urgent = (UrgentFare) fare;
assertThat(urgent.getUrgentFee()).isPositive();
}
โ AssertJ๋ isInstanceOf() ๋ฅผ ์ ๊ณต.
// โ 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();
}
}
// โ ๋คํ์ฑ์ ์ ์
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๊ฐ ์ด์์ด๋ฉด ๋คํ์ฑ์ผ๋ก ๋ฆฌํฉํ ๋ง ๊ฒํ .
String s = "hello";
if (s instanceof Integer) { // โ ์ปดํ์ผ ์๋ฌ
// ...
}
โ String๊ณผ Integer๋ ์์ ๊ด๊ณ ์์. ์ปดํ์ผ๋ฌ๊ฐ ์ก์.
์์ธ โ Object ๋ณ์:
Object obj = "hello";
if (obj instanceof Integer) { // โ
์ปดํ์ผ OK (๋ฐํ์์ false)
// ...
}
โ Object ํ์ ์ ์ด๋ค ๊ฐ์ฒด๋ ๊ฐ๋ฆฌํฌ ์ ์์ด์ ์ปดํ์ผ์ ํต๊ณผ.
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 ์ฒ๋ฆฌํด์ค.
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("๊ณ ์์ด ์ฒ๋ฆฌ");
}
๊ท์น: ์์ โ ๋ถ๋ชจ ์์.
// โ ์ํํ 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์ฃผ์ฐจ์์ ๊น์ด ๋ค๋ฃฐ ์ฃผ์ .
// ์ ์คํ์ผ โ ๋ณ์ ๋ ๋ฒ ์ ์ธ
if (obj instanceof String) {
String s = (String) obj;
// ...
}
// ํ๋ ์คํ์ผ (Java 16+)
if (obj instanceof String s) {
// ํ ๋ฒ์ ๋
}
โ Java 16+ ํ๊ฒฝ์ด๋ฉด ํจํด ๋งค์นญ ์ ๊ทน ํ์ฉ.
// โ ์ํฐํจํด
try {
Dog d = (Dog) a;
d.bark();
} catch (ClassCastException e) {
// ๋ฌด์
}
๋ฌธ์ :
ํด๊ฒฐ:
if (a instanceof Dog d) {
d.bark();
}
[Unit 2.4: ๋คํ์ฑ]
โ
[Unit 2.5: instanceof์ ํ๋ณํ] โ ์ง๊ธ ์ฌ๊ธฐ
โ
[Unit 2.6: Nested/Inner/Anonymous]
1์ฃผ์ฐจ ๋ด:
๋ฏธ๋ ์ฃผ์ฐจ:
<T extends Number> ๋ฑ[๋คํ์ฑ (Unit 2.4)]
"๋ถ๋ชจ ํ์
์ผ๋ก ์์ ๊ฐ์ฒด ์ฒ๋ฆฌ"
โ
ํ์ง๋ง ์์ ๊ณ ์ ๋ฉ์๋๋?
โ
[ํ๋ณํ (Unit 2.5)]
"๋ถ๋ชจ ํ์
์ ์์ ํ์
์ผ๋ก"
โ
์๋ชป ์บ์คํ
ํ๋ฉด ์ํ
โ
[instanceof (Unit 2.5)]
"์์ ํ๊ฒ ํ์
ํ์ธ"
์ธ ๊ฐ์ง๊ฐ ํ ์ธํธ โ ํ๋๋ง ์์๋ ๋ถ์กฑ.
| ์ง๋ฌธ | ์ด Unit์์์ ๋ต |
|---|---|
| "instanceof๊ฐ ๋ญ๊ฐ์?" | ๊ฐ์ฒด๊ฐ ํน์ ํ์ ์ธ์ง ๊ฒ์ฌํ๋ ์ฐ์ฐ์ |
| "๋ค์ด์บ์คํ ์ด ์ํํ ์ด์ ?" | ClassCastException ๊ฐ๋ฅ โ instanceof ์ฌ์ ๊ฒ์ฌ ํ์ |
| "instanceof์ getClass()์ ์ฐจ์ด?" | instanceof๋ ์์ ํฌํจ, getClass()๋ ์ ํํ ํ์ |
| "ํจํด ๋งค์นญ์ด ๋ญ๊ฐ์?" | Java 16+ ์ instanceof + ๋ณ์ ์ ์ธ ๊ฒฐํฉ ๋ฌธ๋ฒ |
| "instanceof ๋จ๋ฐ์ ๋ฌธ์ ?" | ๋คํ์ฑ์ ํ์ฉ ๋ชปํจ โ ์ค๊ณ ์ฌ๊ฒํ ์ ํธ |
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๊ฐ ์ด์์ด๋ฉด ๋คํ์ฑ์ผ๋ก ๋ฆฌํฉํ ๋ง ๊ฒํ . ๋จ, ์ธ๋ถ ์ด๋ฒคํธ ์ฒ๋ฆฌ, ์ต์ ์ธํฐํ์ด์ค ํ์ธ, ๋ง์ปค ์ธํฐํ์ด์ค ๊ฒ์ฌ ๊ฐ์ ์ ๋นํ ์ฌ์ฉ ์ผ์ด์ค๋ ์๋ค. ๋ํ ๋ค์ด์บ์คํ ์ ๊ฐ์ฅ ๊ตฌ์ฒด์ ์ธ ์์ ํ์ ๋ถํฐ ๊ฒ์ฌํด์ผ ์ ํํ๋ค.
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์ผ ์ ์๋ ๊ฒฝ์ฐ๋?
๊ฐ๋ฅํ ๋ชจ๋ ๊ฒฝ์ฐ:
Object obj = 42; // Integer
obj instanceof String; // false
Object obj = null;
obj instanceof String; // false (null์ ์ด๋ค ํ์
๋ ์๋)
Object obj = new Object(); // ์ ํํ Object
obj instanceof String; // false (Object๋ String์ ๋ถ๋ชจ์ด์ง ์์์ด ์๋)
์ false์ธ๊ฐ โ instanceof ์ ๋์ ๊ท์น:
"๊ฐ์ฒด๊ฐ ๊ทธ ํ์ ๋๋ ๊ทธ ํ์ ์ ์์์ธ ๊ฒฝ์ฐ ์๋ง true"
ํต์ฌ ์ ๋ฆฌ:
| Object obj ์ ์ค์ ํ์ | obj instanceof String |
|---|---|
null | false |
Object (์ ํํ) | false |
Integer | false |
String | true |
String์ ์์ (์์ โ final ํด๋์ค) | true |
๋น์ :
โ instanceof๋ ์๊ธฐ ๋๋ ์์ ๋ง true.
์ฐธ๊ณ โ String์ ํน์์ฑ:
final ํด๋์ค โ ์์ ํด๋์ค ์์instanceof String ์ด true๋ฉด ์ ํํ String