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

πŸ“šμ½μ€ μ±… 정리/μžλ°” μ½”λ”©μ˜ 기술

[μžλ°” μ½”λ”©μ˜ 기술] 7μž₯ : 객체 λ””μžμΈ

μžλ°”μ˜ ν΄λž˜μŠ€μ™€ 객체λ₯Ό μ˜¬λ°”λ₯΄κ²Œ κΈ°λŠ₯만 λ™μž‘ν•˜κ²Œ ν•˜λŠ” 것은 λΆ€μ‘±ν•˜λ‹€!

보기 μ’‹μ•„μ•Ό ν•˜κ³  μ‚¬μš©ν•˜κΈ°λ„ νŽΈν•΄μ•Όλ§Œ ν•œλ‹€!!

7μž₯μ—μ„œλŠ” 더 객체 지ν–₯적이고 κ°•λ ₯ν•œ μ½”λ“œλ₯Ό λ§Œλ“œλŠ”λ° μœ μš©ν•˜κ²Œ 쓰일 μžλ°”μ˜ 보편적인 λ””μžμΈ 원리λ₯Ό κ°•μ‘°ν•˜κ² λ‹€.

 

7.1 뢈 λ§€κ°œλ³€μˆ˜λ‘œ λ©”μ„œλ“œ λΆ„ν• 

문제 μ½”λ“œ

    void log(String message, boolean classified) throws IOException {
        if (classified) {
            writeMessage(message, CAPTAIN_LOG);
        } else {
            writeMessage(message, CREW_LOG);
        }
    }

μœ„ μ½”λ“œλŠ” boolean의 μƒνƒœμ— 따라 μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€.

μ΄λŠ” λ™μž‘μ— λ¬Έμ œκ°€ μ—†μ§€λ§Œ 읽기 λΆˆνŽΈν•˜κ³  λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” μ‚¬λžŒμ΄ True와 Falseκ°€ 각각 무슨 μ˜λ―ΈμΈμ§€ μ•Œκ³  μžˆμ–΄μ•Όλ§Œ ν•œλ‹€.

 

이 μ½”λ“œλ₯Ό μ’€ 더 ν–₯상 μ‹œν‚€λ €λ©΄ boolean λ§€κ°œλ³€μˆ˜κ°€ μ‹€μ œλ‘œ μ–΄λ–€ 역할을 ν•˜λŠ”μ§€ μ•Œμ•„λ³΄κΈ° μ‰½κ²Œ λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. (ν˜Όλ™μ„ μ€„μž„)

κ°œμ„  μ½”λ“œ

    void writeToCaptainLog(String message) throws IOException {
        writeMessage(message, CAPTAIN_LOG);
    }

    void writeToCrewLog(String message) throws IOException {
        writeMessage(message, CREW_LOG);
    }

μœ„ μ½”λ“œμ²˜λŸΌ boolean이 쓰인 λ©”μ„œλ“œλ₯Ό μ—¬λŸ¬ 개둜 λΆ„λ¦¬ν•¨μœΌλ‘œμ¨ μ½”λ“œκ°€ ν–₯상될 수 μžˆλ‹€.

 

*κ°œμ„  방법*

1. λ§€κ°œλ³€μˆ˜λ‘œ κ΅¬λΆ„ν•˜λ˜ μ œμ–΄ 흐름 κ²½λ‘œλ§ˆλ‹€ μƒˆ λ©”μ„œλ“œλ₯Ό μΆ”κ°€

2. λ©”μ„œλ“œμ— 의미 μžˆλŠ” 이름을 지어주어 μ½”λ“œ 가독성 λ†’μž„

λ©”μ„œλ“œκ°€ 어디에 μ†ν•˜λ©° 무엇을 ν•˜λŠ”μ§€ λ©”μ„œλ“œλͺ…λ§Œ 봐도 ν™•μ‹€νžˆ μ•Œ 수 μžˆμ–΄μ§.

7.2 μ˜΅μ…˜ λ§€κ°œλ³€μˆ˜λ‘œ λ©”μ„œλ“œ λΆ„ν• 

μ˜΅μ…˜ λ§€κ°œλ³€μˆ˜λ„ 뢈 λ§€κ°œλ³€μˆ˜ 처럼 λ©”μ„œλ“œ 뢄할을 톡해 μ½”λ“œλ₯Ό κ°œμ„ ν•  수 μžˆλ‹€.

문제 μ½”λ“œ

class Logbook {

    static final Path CREW_LOG = Paths.get("/var/log/crew.log");

    List<String> readEntries(LocalDate date) throws IOException {
        final List<String> entries = Files.readAllLines(CREW_LOG,
                StandardCharsets.UTF_8);
        if (date == null) {
            return entries;
        }

        List<String> result = new LinkedList<>();
        for (String entry : entries) {
            if (entry.startsWith(date.toString())) {
                result.add(entry);
            }
        }
        return result;
    }
}

 

인자둜 null 인 것과 null이 μ•„λ‹Œ 것이 λ„˜μ–΄μ˜¬ 수 μžˆλŠ”λ° μ΄λ•Œ μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ΄ μ‹€ν–‰λœλ‹€.

호좜자 μž…μž₯μ—μ„œ null둜 인자둜 λ„˜κΈΈ λ•Œ μ–΄λ–€ κ²°κ³Όκ°€ λ‚˜μ˜¬μ§€ μ˜ˆμƒν•˜κΈ° μ–΄λ ΅λ‹€..

κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 이 뢀뢄을 λ¦¬νŒ©ν† λ§ ν•  수 μžˆλ‹€.

κ°œμ„  μ½”λ“œ

class Logbook {

    static final Path CREW_LOG = Paths.get("/var/log/crew.log");

    List<String> readEntries(LocalDate date) throws IOException {
        Objects.requireNonNull(date);
        
        List<String> result = new LinkedList<>();
        for (String entry : readAllEntries()) {
            if (entry.startsWith(date.toString())) {
                result.add(entry);
            }
        }
        return result;
    }

    List<String> readAllEntries() throws IOException {
        return Files.readAllLines(CREW_LOG, StandardCharsets.UTF_8);
    }
}

'뢈 λ§€κ°œλ³€μˆ˜'λ₯Ό κ°œμ„ ν•œ κ²ƒμ²˜λŸΌ 'μ˜΅μ…˜ λ§€κ°œλ³€μˆ˜' λ˜ν•œ λ©”μ„œλ“œλ₯Ό μ—¬λŸ¬ 개둜 λΆ„ν• ν•΄μ£Όλ©΄ λœλ‹€.

 

*κ°œμ„  방법*

1. 각각의 μ œμ–΄ 흐름을 ν•˜λ‚˜μ˜ λ©”μ„œλ“œλ‘œ ν‘œν˜„.

2. λ©”μ„œλ“œλͺ…을 톡해 무엇을 ν•  것인지 λͺ…ν™•νžˆ 전달.

 

readAllEntriles()λŠ” 'λͺ¨λ“  μ—”νŠΈλ¦¬λ₯Ό μ½μ–΄μ˜¨λ‹€'λΌλŠ” 의미λ₯Ό ν•œλˆˆμ— μ•Œ 수 있고 더 이상 null을 μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

7.3 ꡬ체 νƒ€μž…λ³΄λ‹€ 좔상 νƒ€μž…

λ³€μˆ˜μ— 좔상적인 νƒ€μž…μ„ μ‚¬μš©ν• μˆ˜λ‘ μ½”λ“œλŠ” 더 μœ μ—°ν•΄μ§„λ‹€!

문제 μ½”λ“œ

class Inventory {
    LinkedList<Supply> supplies = new LinkedList();

    void stockUp(ArrayList<Supply> delivery) {
        supplies.addAll(delivery);
    }

    LinkedList<Supply> getContaminatedSupplies() {
        LinkedList<Supply> contaminatedSupplies = new LinkedList<>();
        for (Supply supply : supplies) {
            if (supply.isContaminated()) {
                contaminatedSupplies.add(supply);
            }
        }
        return contaminatedSupplies;
    }
}

class Usage {
    static void main(String[] args) {
        CargoShip cargoShip = null;
        Inventory inventory = null;
        Stack<Supply> delivery = cargoShip.unload();
        ArrayList<Supply> loadableDelivery = new ArrayList<>(delivery);
        inventory.stockUp(loadableDelivery);
    }
}

μœ„ μ½”λ“œλŠ” LinkenList<>, ArraryList<> λ“±μ˜ ꡬ체 νƒ€μž…μœΌλ‘œ νŒŒλΌλ―Έν„° νƒ€μž…μ΄λ‚˜, λ³€μˆ˜ νƒ€μž…μ„ μ§€μ •ν•˜κ³  μžˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ μ—¬λŸ¬ 자료 ꡬ쑰 κ°„ νƒ€μž… κ°„ λ³€ν™˜μ΄ μž¦μ•„μ§€κ³  Inventory클래슀λ₯Ό λ³€κ²½ν•  경우 λ‹€λ₯Έ 뢀뢄에도 영ν–₯을 미치게 λœλ‹€....(객체 지ν–₯에 μ•ˆμ’‹μŒ)

 

좔상 νƒ€μž…μ„ μ“°λ©΄ 이 문제λ₯Ό κ°œμ„ ν•  수 μžˆλ‹€.

κ°œμ„  μ½”λ“œ

class Inventory {
    List<Supply> supplies = new LinkedList();

    void stockUp(Collection<Supply> delivery) {
        supplies.addAll(delivery);
    }

    List<Supply> getContaminatedSupplies() {
        List<Supply> contaminatedSupplies = new LinkedList<>();
        for (Supply supply : supplies) {
            if (supply.isContaminated()) {
                contaminatedSupplies.add(supply);
            }
        }
        return contaminatedSupplies;
    }
}

μ½”λ“œκ°€ κ°œμ„  된 3가지 츑면을 μ‚΄νŽ΄λ³΄μž.

  1. supplies ν•„λ“œμ— List μΈν„°νŽ˜μ΄μŠ€ μ‚¬μš© -> 인벀토리에 μ œν’ˆμ΄ μ–΄λ–»κ²Œ μ €μž₯λ˜λŠ”μ§€ μ•Œ 수 없어짐 (λ‹€μ–‘ν•œ 객체 넣을 수 μžˆμ–΄μ§)
  2. stockUp() λ©”μ„œλ“œκ°€ νŒŒλΌλ―Έν„°λ‘œ μ–΄λ–€ Collection이든 ν—ˆμš© -> 즉, μ–΄λ–€ ν•˜μœ„ νƒ€μž…μ΄λ“  λ©”μ„œλ“œλ‘œ 전달 κ°€λŠ₯해짐.
  3. getConataminatedSupplies() ꡬ체적인 νƒ€μž…μ΄ μ•„λ‹Œ 좔상적인 List<> νƒ€μž…μ„ λ°˜ν™˜ν•¨.
    -> μ œν’ˆμ˜ λ°˜ν™˜μ€ Listν˜•νƒœμ΄μ§€λ§Œ λ‚΄λΆ€μ μœΌλ‘œ μ–΄λ–»κ²Œ μ €μž₯ν–ˆλŠ” μ§€λŠ” 외뢀에 μ•Œλ¦¬μ§€ μ•ŠμŒ
class Usage {
    static void main(String[] args) {
        CargoShip cargoShip = null;
        Inventory inventory = null;
        Stack<Supply> delivery = cargoShip.unload();
        inventory.stockUp(delivery);
    }
}

stockUp μ‚¬μš© μ‹œ νƒ€μž… λ³€ν™˜ 없이 Stack νƒ€μž…μ„ λ°”λ‘œ Collection으둜 λ°›μ•„μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.

7.4 κ°€λ³€ μƒνƒœλ³΄λ‹€ λΆˆλ³€ μƒνƒœ μ‚¬μš©ν•˜κΈ°

기본적으둜 객체의 μƒνƒœλŠ” λΆˆλ³€μ΄λ‹€. κ°€λŠ₯ν•˜λ©΄ 객체λ₯Ό λΆˆλ³€μœΌλ‘œ λ§Œλ“€μ–΄μ•Ό 잘λͺ» μ‚¬μš©ν•  κ²½μš°κ°€ 적닀.

문제 μ½”λ“œ

class Distance {
    DistanceUnit unit;
    double value;

    Distance(DistanceUnit unit, double value) {
        this.unit = unit;
        this.value = value;
    }

    static Distance km(double value) {
        return new Distance(DistanceUnit.KILOMETERS, value);
    }

    void add(Distance distance) {
        distance.convertTo(unit);
        value += distance.value;
    }

    void convertTo(DistanceUnit otherUnit) {
        double conversionRate = unit.getConversionRate(otherUnit);
        unit = otherUnit;
        value = conversionRate * value;
    }
}


class Main {
    static void usage() {
        Distance toMars = new Distance(DistanceUnit.KILOMETERS, 56_000_000);
        Distance marsToVenus = new Distance(DistanceUnit.LIGHTYEARS, 0.000012656528);
        Distance toVenusViaMars = toMars;
        toVenusViaMars.add(marsToVenus);
    }
}

toMars와 toVenusViaMarsλŠ” 같은 객체λ₯Ό κ°€λ₯΄ν‚¨λ‹€. λ”°λΌμ„œ, toVenusViaMars.add(marsToVenus)λ₯Ό μ‹€ν–‰ν•˜λ©΄ toMars객체도 변경이 μΌμ–΄λ‚˜κ²Œ λœλ‹€. (value 값은 변동)

κ°œμ„  μ½”λ“œ

final class Distance {
    final DistanceUnit unit;
    final double value;


    Distance(DistanceUnit unit, double value) {
        this.unit = unit;
        this.value = value;
    }

    Distance add(Distance distance) {
        return new Distance(unit, value + distance.convertTo(unit).value);
    }

    Distance convertTo(DistanceUnit otherUnit) {
        double conversionRate = unit.getConversionRate(otherUnit);
        return new Distance(otherUnit, conversionRate * value);
    }
}

class Main {
    static void usage() {
        Distance toMars = new Distance(DistanceUnit.KILOMETERS, 56_000_000);
        Distance marsToVenus = new Distance(DistanceUnit.LIGHTYEARS, 0.000012656528);
        Distance toVenusViaMars = toMars.add(marsToVenus)
                                        .convertTo(DistanceUnit.MILES);
    }
}

κ°μ²΄λŠ” μœ νš¨ν•˜μ§€ μ•Šμ€ 변경이 μΌμ–΄λ‚˜μ§€ μ•Šλ„λ‘ 가변성을 μ œν•œν•΄ 슀슀둜λ₯Ό λ³΄ν˜Έν•  수 μžˆλ‹€.

 

μƒμ„±μžμ˜ value와 unitν•„λ“œμ— final ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ΄ν›„λ‘œλŠ” λ³€κ²½ν•  수 μ—†λ‹€.

λ”°λΌμ„œ, 거리λ₯Ό κ³„μ‚°ν•˜λ €λ©΄ 맀번 μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€κ°€ ν•„μš”ν•˜λ‹€.

 

add() 와 convertTo() ν•¨μˆ˜λŠ” μˆ˜ν–‰ ν›„ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄ λ°˜ν™˜ν•œλ‹€.

μ΄λ ‡κ²Œ ν•˜λ©΄ Distance의 λΆˆλ³€ μƒνƒœλ₯Ό μœ μ§€ν•  수 μžˆλ‹€.

 

클래슀 μ •μ˜ μ•žμ— final ν‚€μ›Œλ“œλ₯Ό λΆ™μ΄λŠ” κ²½μš°λŠ” 클래슀λ₯Ό 더 이상 ν™•μž₯ν•  수 μ—†κ²Œ ν•˜λ €λŠ” μ˜λ„μ΄λ‹€.

7.5 μƒνƒœμ™€ λ™μž‘ κ²°ν•©ν•˜κΈ°

문제 μ½”λ“œ

class Hull {
    int holes;
}


class HullRepairUnit {

    void repairHole(Hull hull) {
        if (isIntact(hull)) {
            return;
        }
        hull.holes--;
    }

    boolean isIntact(Hull hull) {
        return hull.holes == 0;
    }
}

μƒνƒœμ™€ λ™μž‘μ˜ 결합은 객체 지ν–₯ ν”„λ‘κ·Έλž˜λ°μ˜ κΈ°λ³Έ ν‹€ 쀑 ν•˜λ‚˜μ΄λ‹€.

μœ„ μ½”λ“œλŠ” μƒνƒœμ™€ λ™μž‘μ΄ λ³„κ°œμ˜ 클래슀둜 λ‚˜λ‰˜μ–΄ μžˆλ‹€.

 

μœ„μ™€ 같이 μ‚¬μš©ν•˜λ©΄ λ¬Έμ œλŠ” '정보 은닉'이 λΆˆκ°€λŠ₯해지고 μ½”λ“œλ₯Ό μ΄ν•΄ν•˜κΈ° 더 μ–΄λ €μ›Œμ§„λ‹€λŠ” 점이닀.

Hull ν΄λž˜μŠ€λŠ” HullRepairUnit 바같에 μžˆλŠ” ν΄λž˜μŠ€μ΄λ―€λ‘œ μžμ‹ μ˜ μƒνƒœμ— λŒ€ν•΄ 읽기와 μ“°κΈ° 접근을 μ œκ³΅ν•΄μ•Όλ§Œ ν•œλ‹€.

 

μƒνƒœμ™€ λ™μž‘μ„ μ˜¬λ°”λ₯΄κ²Œ κ²°ν•©ν•΄μ„œ μ½”λ“œλ₯Ό κ°œμ„ ν•΄λ³΄μž.

κ°œμ„  μ½”λ“œ

class Hull {
    int holes;

    void repairHole() {
        if (isIntact()) {
            return;
        }
        holes--;
    }

    boolean isIntact() {
        return holes == 0;
    }
}

HullRepairUnit을 μ™„μ „νžˆ 지웠닀. 이제 Hull은 슀슀둜 κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.

Hull λ©”μ„œλ“œλŠ” μžμ‹ μ˜ λ‚΄λΆ€ μƒνƒœλ₯Ό 직접 μ²˜λ¦¬ν•  수 있고 λ©”μ„œλ“œ λ§€κ°œλ³€μˆ˜λ‘œ μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

λ˜ν•œ, κ²Œν„°, μ„Έν„°λ₯Ό 톡해 μ™ΈλΆ€λ‘œ μƒνƒœλ₯Ό λ…ΈμΆœν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

 

μš”μ•½ν•˜λ©΄ λ©”μ„œλ“œ λ‚΄μ—μ„œ μž…λ ₯ λ§€κ°œλ³€μˆ˜λ§Œ 닀루고 μžμ‹ μ΄ μ†ν•œ 클래슀 μΈμŠ€ν„΄μŠ€ λ³€μˆ˜λŠ” 닀루지 μ•ŠλŠ” κ²½μš°λŠ” μœ μ‹¬νžˆ λ΄μ•Όν•œλ‹€.

이것은 μƒνƒœμ™€ λ™μž‘μ΄ λΆ„λ¦¬λ˜μ—ˆλ‹€λŠ” 의미이고 μ΄λŸ¬ν•œ λ©”μ„œλ“œλ‘œλŠ” '정보 은닉'이 λΆˆκ°€λŠ₯ν•˜λ‹€.

7.6 μ°Έμ‘° λˆ„μˆ˜ ν”Όν•˜κΈ°

문제 μ½”λ“œ

class Inventory {

    private final List<Supply> supplies;

    Inventory(List<Supply> supplies) {
        this.supplies = supplies;
    }

    List<Supply> getSupplies() {
        return supplies;
    }
}

class Usage {

    static void main(String[] args) {
        List<Supply> externalSupplies = new ArrayList<>();
        Inventory inventory = new Inventory(externalSupplies);

        inventory.getSupplies().size(); // == 0
        externalSupplies.add(new Supply("Apple"));
        inventory.getSupplies().size(); // == 1

        inventory.getSupplies().add(new Supply("Banana"));
        inventory.getSupplies().size(); // == 2
    }
}

μœ„ μ½”λ“œλŠ” μ–΄λŠ 뢀뢄이 λ¬Έμ œκ°€ 될까?

 

λ¨Όμ € inventoryλŠ” λ‚΄λΆ€μ˜ μ œν’ˆ 리슀트λ₯Ό μ „ν˜€ λ³΄ν˜Έν•˜μ§€ μ•ŠλŠ”λ‹€!

 

μœ„ μ½”λ“œμ—μ„œ 재고 μΆ”κ°€λŠ” 클래슀 λ‚΄λΆ€κ°€ μ•„λ‹ˆλ”λΌλ„ μ—¬λŸ¬ κ³³μ—μ„œ κ°€λŠ₯ν•˜λ‹€....

1. μ™ΈλΆ€μ—μ„œ μƒμ„±ν•œ 리슀트λ₯Ό μ΄μš©ν•΄ 재고 μΆ”κ°€ -> externalSupplies.add(new Supply("Apple")); 

2. 클래슀의 λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ 리슀트 μ°Έμ‘°ν•΄ μ™ΈλΆ€μ—μ„œ 재고 μΆ”κ°€ -> inventory.getSupplies().add(new Supply("Banana"));

 

κ·Έλ ‡λ‹€λ©΄ 클래슀 λ‚΄λΆ€λ₯Ό μ΄ˆκΈ°ν™”ν•œ ν›„ μ‘°μž‘λ˜μ§€ μ•Šλ„λ‘ λ³΄ν˜Έν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Όν• κΉŒ??

class Inventory {

    private final List<Supply> supplies;

    Inventory(List<Supply> supplies) {
        this.supplies = new ArrayList<>(supplies);
    }

    List<Supply> getSupplies() {
        return Collections.unmodifiableList(supplies);
    }
}

class Usage {

    static void main(String[] args) {
        List<Supply> externalSupplies = new ArrayList<>();
        Inventory inventory = new Inventory(externalSupplies);

        inventory.getSupplies().size(); // == 0
        externalSupplies.add(new Supply("Apple"));
        inventory.getSupplies().size(); // == 0

        // UnsupportedOperationException
        inventory.getSupplies().add(new Supply("Banana"));
    }
}

λ¨Όμ € μœ„ μ½”λ“œλŠ” μ „λ‹¬ν•œ 리슀트의 μ°Έμ‘°κ°€ μ•„λ‹ˆλΌ 리슀트 λ‚΄ Supply객체둜 λ‚΄λΆ€ ArrayListλ₯Ό μ±„μš΄λ‹€.

-> this.supplies = new ArrayList<>(supplies); (λ°©μ–΄ 볡사)

 

그리고 getSupplies() 호좜 μ‹œ -> return Collections.unmodifiableList(supplies); 둜 λž˜ν•‘ν•œ ν›„ λ°˜ν™˜ν•΄μ„œ 읽기 μ ‘κ·Όλ§Œ κ°€λŠ₯ν•˜κ²Œ λ§Œλ“ λ‹€.

 

μ΄λ ‡κ²Œ ν•˜λ©΄ μ™ΈλΆ€μ—μ„œλŠ” λ‚΄λΆ€μ˜ 리슀트λ₯Ό μ‘°μž‘ν•  수 μ—†μœΌλ‹ˆ μ™ΈλΆ€μ—μ„œ λ‚΄λΆ€λ‘œ 영ν–₯을 주지 λͺ»ν•œλ‹€.

7.7 널 λ°˜ν™˜ν•˜μ§€ μ•ŠκΈ°

λ©”μ„œλ“œ 호좜 μ‹œ λ°˜ν™˜ν•  값이 μ—†μœΌλ©΄ κ·Έλƒ₯ 'null'을 λ°˜ν™˜ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μžˆλ‹€. 이것은 ν”„λ‘œκ·Έλž¨μ˜ μ•ˆμ •μ„±μ„ ν•΄μΉ˜λŠ” 행동이닀.

문제 μ½”λ“œ

class SpaceNations {

    static List<SpaceNation> nations = Arrays.asList(
            new SpaceNation("US", "United States"),
            new SpaceNation("RU", "Russia")
    );

    static SpaceNation getByCode(String code) {
        for (SpaceNation nation : nations) {
            if (nation.getCode().equals(code)) {
                return nation;
            }
        }
        return null;
    }
}

μœ„ μ½”λ“œλŠ” getByCode() λ©”μ„œλ“œ μ‚¬μš© μ‹œ codeκ°€ 같은 것이 μ—†λ‹€λ©΄ 'null'을 λ°˜ν™˜ν•œλ‹€.

 

μ΄λŠ” 같은 κ΅­κ°€ μ½”λ“œκ°€ μ—†λ‹€λ©΄ λ„ˆλ¬΄ μ‰½κ²Œ 'NullPointerException'을 λ°œμƒμ‹œν‚¨λ‹€.

λ¬Όλ‘  ν˜ΈμΆœν•˜λŠ” μͺ½μ—μ„œ null을 검증할 수 μžˆμ§€λ§Œ λˆ„κ΅°κ°€λŠ” μžŠμ–΄λ²„λ¦¬κ³  μ˜ˆμ™Έλ₯Ό λ°œμƒν•˜κ²Œ λ‘˜ 수 μžˆλ‹€..

 

λ”°λΌμ„œ, null말고 λ‹€λ₯Έ 무언가λ₯Ό λ°˜ν™˜ν•˜λŠ” μͺ½μœΌλ‘œ κ°œμ„ ν•΄λ³΄μž.

κ°œμ„  μ½”λ“œ

class SpaceNations {

    /** Null object. */
    static final SpaceNation UNKNOWN_NATION = new SpaceNation("", "");

    static List<SpaceNation> nations = Arrays.asList(
            new SpaceNation("US", "United States"),
            new SpaceNation("RU", "Russia")
    );

    static SpaceNation getByCode(String code) {
        for (SpaceNation nation : nations) {
            if (nation.getCode().equals(code)) {
                return nation;
            }
        }
        return UNKNOWN_NATION;
    }
}

μœ„ μ½”λ“œλŠ” "널 객체 νŒ¨ν„΄"을 μ‚¬μš©ν–ˆλ‹€. null을 λ°˜ν™˜ν•˜λŠ” λŒ€μ‹  널 객체(null object), μ¦‰ 객체에 μ‹€μ§ˆμ μΈ 값이 μ—†μŒμ„ λͺ…μ‹œμ μœΌλ‘œ ν‘œν˜„ν•œ 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” 방식이닀. 

 

μ˜ˆμ œμ—μ„œλŠ” UNKOWN_NATION -> SpaceNation("", "")

 

μ΄λ ‡κ²Œ ν•˜λ©΄ 호좜자μͺ½μ—μ„œ 'NullPointerException'이 λ°œμƒν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 널 객체λ₯Ό λ¬΄μ‹œν• μ§€ μ˜ˆμ™Έλ₯Ό 던질 지 선택할 수 μžˆλ‹€.

7.8 7μž₯μ—μ„œ 배운 λ‚΄μš©

μš°λ¦¬λŠ” μ½”λ“œ μž‘μ„±μžκ°€ μ–΄λ–€ 근거둜 λ””μžμΈ 결정을 λ‚΄λ ΈλŠ”μ§€ μ•Œμ•„λ‚΄λŠ”λ° λ§Žμ€ λ…Έλ ₯을 κΈ°μšΈμ—¬μ•Ό ν•œλ‹€.

 

μ½”λ“œ λ””μžμΈμ€ 항상 μ„ νƒμ˜ 연속이며 κ·Έ 득싀에 λŒ€ν•œ μ±…μž„μ€ 개발자의 λͺ«μ΄λ‹€.

 

<가독성>, <ν…ŒμŠ€νŠΈ κ°€λŠ₯μ„±>, <μœ μ§€ λ³΄μˆ˜μ„±>, <μ„±λŠ₯> λ“±μ˜ νŠΈλ ˆμ΄λ“œ μ˜€ν”„λ₯Ό κ³ λ €ν•΄ κ°œλ°œμžλŠ” μ˜¬λ°”λ₯Έ 결정을 λ‚΄λ €μ•Ό ν•œλ‹€.