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

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

[μ΄νŽ™ν‹°λΈŒ μžλ°”] 6μž₯ : μ—΄κ±° νƒ€μž…κ³Ό μ• λ„ˆν…Œμ΄μ…˜

μžλ°”μ˜ νŠΉμˆ˜ν•œ λͺ©μ μ˜ μ°Έμ‘° νƒ€μž… 2가지

  • 클래슀의 일쒅인 ‘μ—΄κ±° νƒ€μž…’
  • μΈν„°νŽ˜μ΄μŠ€μ˜ 일쒅인 ‘μ• λ„ˆν…Œμ΄μ…˜’

이 두가지λ₯Ό μ˜¬λ°”λ₯΄κ²Œ μ‚¬μš©ν•΄λ³΄μž.

μ•„μ΄ν…œ 34 : int μƒμˆ˜ λŒ€μ‹  μ—΄κ±° νƒ€μž…μ„ μ‚¬μš©ν•˜λΌ

μ—΄κ±° νƒ€μž…μ€ 일정 개수의 μƒμˆ˜κ°’ μ •μ˜ ν›„ κ·Έμ™ΈλŠ” μ§€μ›ν•˜μ§€ μ•ŠλŠ” νƒ€μž…μ΄λ‹€.

μ—΄κ±° νƒ€μž… 이전 μƒμˆ˜ μ„ μ–Έ (μ •μˆ˜ μ—΄κ±° νŒ¨ν„΄)

public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_SMITH = 2;
...
public static final int ORANGE_NEVLE = 0;
public static final int ORANGE_TEMPLE = 1;

단점 →

  • νƒ€μž… μ•ˆμ „ 보μž₯ X, (μ˜€λ Œμ§€ λŒ€μ‹  사과λ₯Ό 보내도 κ²½κ³ κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€) ‘==’이 λ™μΌν•˜λ―€λ‘œ
  • μƒμˆ˜λ₯Ό μ‚¬μš©ν•œ λͺ¨λ“  파일 재컴파일 ν•„μš”

μžλ°” μ—΄κ±° νƒ€μž…

public enum Apple { FUJI, PIPPIN, GRANNY_SMITH } 
public enum ORANGE { NAVEL, TEMPLE, BLOOD }
  • μ—΄κ±° νƒ€μž… μžμ²΄κ°€ 클래슀이며 μƒμˆ˜ ν•˜λ‚˜λ‹Ή μžμ‹ μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄ public static final둜 κ³΅κ°œν•œλ‹€.
    • μƒμ„±μžλ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ μΈμŠ€ν„΄μŠ€κ°€ μƒμ„±λΆˆκ°€ν•˜κ³  사싀상 final이닀. (μΈμŠ€ν„΄μŠ€ ν†΅μ œ)
    • 싱글턴은 μ›μ†Œκ°€ ν•˜λ‚˜λΏμΈ μ—΄κ±° νƒ€μž…
  • 컴파일 νƒ€μž… μ•ˆμ •μ„±μ„ 제곡
  • 각자의 λ„€μž„μŠ€νŽ˜μ΄μŠ€ μ œκ³΅ν•¨μœΌλ‘œ 이름이 같아도 곡쑴가λŠ₯ (APPLE.FUJI, ORANGE.FUJI κ°€λŠ₯)
  • λ©”μ„œλ“œλ‚˜ ν•„λ“œ μΆ”κ°€ κ°€λŠ₯ (μƒμˆ˜λ₯Ό μ΄μš©ν•œ 좔가적인 κΈ°λŠ₯ 제곡)

-Planet-

public enum Planet {
    MERCURY(3.302e+23, 2.439e6),
    VENUS  (4.869e+24, 6.052e6),
    EARTH  (5.975e+24, 6.378e6),
    MARS   (6.419e+23, 3.393e6),
    JUPITER(1.899e+27, 7.149e7),
    SATURN (5.685e+26, 6.027e7),
    URANUS (8.683e+25, 2.556e7),
    NEPTUNE(1.024e+26, 2.477e7);

    private final double mass;           // μ§ˆλŸ‰(λ‹¨μœ„: ν‚¬λ‘œκ·Έλž¨)
    private final double radius;         // λ°˜μ§€λ¦„(λ‹¨μœ„: λ―Έν„°)
    private final double surfaceGravity; // ν‘œλ©΄μ€‘λ ₯(λ‹¨μœ„: m / s^2)

    // 쀑λ ₯μƒμˆ˜(λ‹¨μœ„: m^3 / kg s^2)
    private static final double G = 6.67300E-11;

    // μƒμ„±μž
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
        surfaceGravity = G * mass / (radius * radius);
    }

    public double mass()           { return mass; }
    public double radius()         { return radius; }
    public double surfaceGravity() { return surfaceGravity; }

    public double surfaceWeight(double mass) {
        return mass * surfaceGravity;  // F = ma
    }
}

μ—΄κ±°νƒ€μž…ν΄λž˜μŠ€ 내뢀에 νŠΉμ • 데이터값을 ν• λ‹Ήν•˜κ³  μ‹Άλ‹€λ©΄ μ—΄κ±° μ„ μ–Έ ν›„ μƒμ„±μžλ₯Ό 톡해 ν• λ‹Ήν•˜λ©΄ λœλ‹€.

  • μ—΄κ±° νƒ€μž…μ€ λΆˆλ³€μ΄λ―€λ‘œ λͺ¨λ“  ν•„λ“œλŠ” final, public static final둜 곡개

λ§Œμ•½, μƒμˆ˜λ₯Ό ν•˜λ‚˜ μ œκ±°ν•˜κ²Œ 되면 μ œκ±°ν•œ μƒμˆ˜λ₯Ό μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ μ•„λ¬΄λŸ° 영ν–₯이 μ—†λ‹€.

그리고 μ°Έμ‘°ν•˜λŠ” μƒμˆ˜λ₯Ό μ œκ±°ν•œ κ³³μ—μ„œλŠ” 컴파일 μ—λŸ¬κ°€ λ°œμƒν•΄ μ—λŸ¬λ₯Ό 쑰기에 찾을 수 μžˆλ‹€.

μ—΄κ±° νƒ€μž… μƒμˆ˜λ§ˆλ‹€ λ™μž‘μ΄ λ‹¬λΌμ§€λŠ” λ©”μ„œλ“œ ꡬ성

public enum Operation {
    PLUS("+") {
        public double apply(double x, double y) { return x + y; }
    },
    MINUS("-") {
        public double apply(double x, double y) { return x - y; }
    },
    TIMES("*") {
        public double apply(double x, double y) { return x * y; }
    },
    DIVIDE("/") {
        public double apply(double x, double y) { return x / y; }
    };

    private final String symbol;

    Operation(String symbol) { this.symbol = symbol; }

    @Override public String toString() { return symbol; }

    public abstract double apply(double x, double y);

λ‚΄λΆ€ symbolν•„λ“œμ— μ•Œλ§žμ€ 값이 μ €μž₯되며 toString() μž¬μ •μ˜λ₯Ό 톡해 symbol값이 λ°˜ν™˜λ¨

μƒˆλ‘œμš΄ μƒμˆ˜κ°€ μΆ”κ°€ λ˜μ—ˆμ„ λ•Œ apply()μž¬μ •μ˜μ—¬λΆ€λ₯Ό μ»΄νŒŒμΌμ—λŸ¬λ‘œ μ•Œλ €μ€€λ‹€.

값에 따라 λΆ„κΈ°ν•˜μ—¬ μ½”λ“œλ₯Ό κ³΅μœ ν•˜λŠ” μ—΄κ±° νƒ€μž…

enum PayrollDay {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY;

    private static final int MINS_PER_SHIFT = 8 * 60;

    int pay(int minutesWorked, int payRate) {
        int basePay = minutesWorked * payRate;
        int overtimePay;
        switch (this) {
            case SATURDAY:
            case SUNDAY:
                overtimePay = basePay / 2;
                break;
            default:
                overtimePay = minutesWorked <= MINS_PER_SHIFT
                    ? 0
                    : (minutesWorked - MINS_PER_SHIFT) * payRate / 2;
        }
        return basePay + overtimePay;
    }
}
@Test public void payrollDayTest() {
    int pay1 = PayrollDay.FRIDAY.pay(480, 200);
    System.out.println("pay1 = " + pay1);
    int pay2 = PayrollDay.FRIDAY.pay(540, 200);
    System.out.println("pay2 = " + pay2);
    int pay3 = PayrollDay.SUNDAY.pay(480, 200);
    System.out.println("pay3 = " + pay3);
}

주말과 주쀑을 λΆ„λ¦¬ν•˜μ—¬ κ³„μ‚°ν•˜λŠ” 것은 λΆ„λͺ… κ°„κ²°ν•˜μ§€λ§Œ ‘관리 관점' μ—μ„œ μœ„ν—˜ν•œ μ½”λ“œμ΄λ‹€. λ§Œμ•½, μƒˆλ‘œμš΄ μƒμˆ˜μΈ νœ΄κ°€κ°€ μΆ”κ°€λ˜μ—ˆλŠ”λ° pay에 μž¬μ •μ˜λ₯Ό ν•˜μ§€ μ•ŠμœΌλ©΄ νœ΄κ°€μ—λ„ 평일과 같은 μž„κΈˆμ„ λ°›κ²Œλœλ‹€.

  • 관리가 μ–΄λ ΅κ³  μ‹€μˆ˜λ₯Ό μœ λ°œν•  수 μžˆλ‹€.

μ „λž΅ μ—΄κ±° νƒ€μž… νŒ¨ν„΄

// μ½”λ“œ 34-9 μ „λž΅ μ—΄κ±° νƒ€μž… νŒ¨ν„΄ (218-219μͺ½)
enum PayrollDay {
    MONDAY(WEEKDAY), TUESDAY(WEEKDAY), WEDNESDAY(WEEKDAY),
    THURSDAY(WEEKDAY), FRIDAY(WEEKDAY),
    SATURDAY(WEEKEND), SUNDAY(WEEKEND);

    private final PayType payType;

    PayrollDay(PayType payType) { this.payType = payType; }
    // PayrollDay() { this(PayType.WEEKDAY); } // (μ—­μž λ…ΈνŠΈ) μ›μ„œ 4쇄뢀터 μ‚­μ œ
    
    int pay(int minutesWorked, int payRate) {
        return payType.pay(minutesWorked, payRate);
    }

    // μ „λž΅ μ—΄κ±° νƒ€μž…
    enum PayType {
        WEEKDAY {
            int overtimePay(int minsWorked, int payRate) {
                return minsWorked <= MINS_PER_SHIFT ? 0 :
                        (minsWorked - MINS_PER_SHIFT) * payRate / 2;
            }
        },
        WEEKEND {
            int overtimePay(int minsWorked, int payRate) {
                return minsWorked * payRate / 2;
            }
        };

        abstract int overtimePay(int mins, int payRate);
        private static final int MINS_PER_SHIFT = 8 * 60;

        int pay(int minsWorked, int payRate) {
            int basePay = minsWorked * payRate;
            return basePay + overtimePay(minsWorked, payRate);
        }
    }

    public static void main(String[] args) {
        for (PayrollDay day : values())
            System.out.printf("%-10s%d%n", day, day.pay(8 * 60, 1));
    }
}

μƒˆλ‘œμš΄ μƒμˆ˜λ₯Ό μΆ”κ°€ν•  λ•Œ ‘μ „λž΅'을 μ„ νƒν•˜λ„λ‘ ν•˜λŠ” 것이닀. 이제 PayrollDayλŠ” μž”μ—…μˆ˜λ‹Ή μ „λž΅μœΌλ‘œ ‘PayType’을 선택할 수 μžˆλ‹€.

μ „λž΅μ„ 미리 μ •μ˜ν•΄λ‘κ³  생성 μ‹œ μ„ νƒν•œ μ „λž΅μœΌλ‘œ pay()λ©”μ„œλ“œκ°€ μˆ˜ν–‰λœλ‹€.

μ—΄κ±° νƒ€μž… μ‚¬μš© κΈ°μ€€

  • ν•„μš”ν•œ μ›μ†Œλ₯Ό 컴파일 νƒ€μž„μ— λ‹€ μ•Œ 수 μžˆλŠ” μƒμˆ˜ 집합이라면 항상 μ—΄κ±° νƒ€μž…μ„ μ‚¬μš©ν•˜μž.
  • μ—΄κ±° νƒ€μž…μ— μ •μ˜λ„λ‹ˆ μƒμˆ˜κ°€ μ˜μ›νžˆ μ˜μ› λΆˆλ³€μΌ ν•„μš”λŠ” μ—†λ‹€.

핡심 정리

  • μ—΄κ±°νƒ€μž…μ΄ μ •μˆ˜ μƒμˆ˜λ³΄λ‹€ 가독성도 μ’‹κ³  μ•ˆμ „ν•˜λ‹€.
  • μ—΄κ±° νƒ€μž… μƒμˆ˜κ°€ 같은 μ½”λ“œλ₯Ό κ³΅μœ ν•œλ‹€λ©΄, μ „λž΅ μ—΄κ±° νƒ€μž… νŒ¨ν„΄μ„ μ‚¬μš©ν•˜μž.

μ•„μ΄ν…œ 35 : ordinal λ©”μ„œλ“œ λŒ€μ‹  μΈμŠ€ν„΄μŠ€ ν•„λ“œλ₯Ό μ‚¬μš©ν•˜λΌ

λŒ€λΆ€λΆ„ μ—΄κ±° νƒ€μž… μƒμˆ˜λŠ” ν•˜λ‚˜μ˜ μ •μˆ«κ°’μ— λŒ€μ‘λœλ‹€. 그리고 ordinal() λ©”μ„œλ“œλŠ” ν•΄λ‹Ή μƒμˆ˜κ°€ μ—΄κ±° νƒ€μž…μ—μ„œ λͺ‡λ²ˆμ§Έ μœ„μΉ˜ν•˜λŠ”μ§€ λ°˜ν™˜ν•œλ‹€.

이 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ‹€κ°€ 쀑간에 μƒμˆ˜κ°€ μΆ”κ°€λ˜λ©΄ μœ„μΉ˜μ˜ λ³€ν™”λ‘œ 인해 였λ₯˜κ°€ λ°œμƒν•œλ‹€. λ”°λΌμ„œ μ‚¬μš©ν•˜μ§€ 말자. (λ²”μš© μžλ£Œκ΅¬μ‘°μ—μ„œ μ“°μž„)

μ“Έ 일이 μžˆλ‹€λ©΄ μΈμŠ€ν„΄μŠ€ ν•„λ“œλ‘œ μ •μ˜ν•΄μ„œ μ‚¬μš©ν•˜λΌ.

μ•„μ΄ν…œ 36 : λΉ„νŠΈ ν•„λ“œ λŒ€μ‹  EnumSet을 μ‚¬μš©ν•˜λΌ

λΉ„νŠΈ ν•„λ“œλŠ” μ—¬λŸ¬ μƒμˆ˜λ₯Ό ν•˜λ‚˜λ‘œ λͺ¨μœΌκ³  합집합, ꡐ집합 연산에 μœ λ¦¬ν•˜λ‹€.

ν•˜μ§€λ§Œ, λΉ„νŠΈμ΄κΈ°λ•Œλ¬Έμ— μ •μˆ˜ μƒμˆ˜λ³΄λ‹€ ν•΄μ„ν•˜κΈ° μ–΄λ ΅λ‹€.

EnumSet - λΉ„νŠΈ ν•„λ“œλ₯Ό λŒ€μ²΄ν•˜λŠ” ν˜„λŒ€μ  기법

public class Text {
    public enum Style {BOLD, ITALIC, UNDERLINE, STRIKETHROUGH}

    // μ–΄λ–€ Set을 λ„˜κ²¨λ„ λ˜λ‚˜, EnumSet이 κ°€μž₯ μ’‹λ‹€.
    public void applyStyles(Set<Style> styles) {
        System.out.printf("Applying styles %s to text%n",
                Objects.requireNonNull(styles));
    }

    // μ‚¬μš© 예
    public static void main(String[] args) {
        Text text = new Text();
        text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
    }
}

EnumSet을 μ‚¬μš©ν•˜λ©΄ λΉ„νŠΈλ₯Ό 효율적으둜 μ²˜λ¦¬ν•˜λ©° λΉ„νŠΈλ₯Ό λ‹€λ£¨λŠ” μ–΄λ €μ›€μ—μ„œ λ²—μ–΄λ‚  수 μžˆλ‹€.

μ•„μ΄ν…œ 37 : ordinal 인덱싱 λŒ€μ‹  EnumMap을 μ‚¬μš©ν•˜λΌ

λ°°μ—΄μ˜ 인덱슀λ₯Ό μ–»κΈ° μœ„ν•΄ ordinal을 μ“°λŠ” 것은 쒋지 μ•ŠμœΌλ‹ˆ EnumMap을 μ‚¬μš©ν•˜λΌ

μ•„μ΄ν…œ 38 : ν™•μž₯ν•  수 μžˆλŠ” μ—΄κ±° νƒ€μž…μ΄ ν•„μš”ν•˜λ©΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λΌ

μ—΄κ±°νƒ€μž…μ„ ν™•μž₯ν•˜λŠ” 것은 섀계와 κ΅¬ν˜„μ΄ λ³΅μž‘ν•΄μ Έμ„œ 쒋지 μ•Šλ‹€. (ν™•μž₯도 μ§€μ›λ˜μ§„ μ•ŠμŒ)

μ—΄κ±°νƒ€μž…μ΄ μž„μ˜μ˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„κ°€λŠ₯ν•˜λ―€λ‘œ ν™•μž₯이 κ°€λŠ₯ν•˜λ‹€.

μ—΄κ±° νƒ€μž… ν™•μž₯

public interface Operation {
  	double apply(double x, double y);
}

public enum BasicOperation implements Operation {
  	PLUS("+") {
      	public double apply(double x, double y) { return x + y; }
    }
  	MINUS("-") {
      	public double apply(double x, double y) { return x - y; }
    }
}

// ν™•μž₯ κ°€λŠ₯ μ—΄κ±° νƒ€μž…
public enum ExtendedOperation implements Operation {
  	EXP("^") {
      	public double apply(double x, double y) {
	          return Math.pow(x, y);
        }
    }
}

클래슀 λ°›μ•„ μ‹€ν–‰

@Test 
public void operationTest() {
    double x = 4.0;
    double y = 2.0;
    getEnumClass(BasicOperation.class, x, y);
    getEnumClass(ExtendedOperation.class, x, y);
}
private < T extends Enum < T > & Operation > void getEnumClass(Class < T > enumClass, double x, double y) {
    for (Operation operation : enumClass.getEnumConstants()) {
        System.out.printf("%f %s %f = %f%n", x, operation, y, operation.apply(x, y));
    }
}

μ»¬λ ‰μ…˜μœΌλ‘œ λ°›μ•„ μ‹€ν–‰

@Test public void operationTest() {
    double x = 4.0;
    double y = 2.0;
    getEnumCollection(Arrays.asList(BasicOperation.values()), x, y);
    getEnumCollection(Arrays.asList(ExtendedOperation.values()), x, y);
}
private void getEnumCollection(Collection <? extends Operation > opSet, double x, double y) {
    for (Operation operation : opSet) {
        System.out.printf("%f %s %f = %f%n", x, operation, y, operation.apply(x, y));
    }
}

μ•„μ΄ν…œ 39 : λͺ…λͺ… νŒ¨ν„΄λ³΄λ‹¨ μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λΌ

λͺ…λͺ… νŒ¨ν„΄ 단점

  1. 정해진 μ΄λ¦„μ—μ„œ μ˜€νƒ€κ°€ λ‚˜λ©΄ μ•ˆλœλ‹€. (μ‹€μˆ˜ λ°œμƒ)
  2. κ°œλ°œμžκ°€ μ˜λ„ν•œλŒ€λ‘œ μ•ˆλ  수 μžˆλ‹€ (μ‚¬μš©λ²• 잘λͺ» 이해할 μ‹œ)
  3. ν”„λ‘œκ·Έλž¨ μš”μ†Œλ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ 전달할 방법이 μ—†λ‹€.

μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λ©΄ 적용된 정보λ₯Ό μ΄μš©ν•΄ 잘λͺ» μ‚¬μš©ν•œ μœ„μΉ˜μ—μ„œ 컴파일 μ‹œ 였λ₯˜λ₯Ό λ±‰λŠ”λ‹€.

/**
 * λͺ…μ‹œν•œ μ˜ˆμ™Έλ₯Ό λ˜μ Έμ•Όλ§Œ μ„±κ³΅ν•˜λŠ” ν…ŒμŠ€νŠΈ λ©”μ„œλ“œμš© μ• λ„ˆν…Œμ΄μ…˜
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
    Class<? extends Throwable> value();
}

μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 ‘λ©”μ„œλ“œ μœ„μΉ˜'에 μ‚¬μš©ν–ˆλŠ” 지 컴파일 νƒ€μž„μ— 검사할 수 있고 μ–΄λ…Έν…Œμ΄μ…˜μ΄ μ–΄λ””κΉŒμ§€ μ‚΄μ•„μžˆμ„ 지도 λͺ…μ‹œν•  수 μžˆλ‹€.

μ• λ„ˆν…Œμ΄μ…˜μ€ 관심 μžˆλŠ” ν”„λ‘œκ·Έλž¨μ— 좔가정보λ₯Ό μ œκ³΅ν•œλ‹€. 즉, νŠΉλ³„ν•œ 처리λ₯Ό ν•  기회λ₯Ό μ€€λ‹€.

 

-RunTestsμ˜ˆμ‹œ-

public class RunTests {
    public static void main(String[] args) throws Exception {
        int tests = 0;
        int passed = 0;
        Class<?> testClass = Class.forName(args[0]);
        for (Method m : testClass.getDeclaredMethods()) {
            if (m.isAnnotationPresent(Test.class)) {
                tests++;
                try {
                    m.invoke(null);
                    passed++;
                } catch (InvocationTargetException wrappedExc) {
                    Throwable exc = wrappedExc.getCause();
                    System.out.println(m + " μ‹€νŒ¨: " + exc);
                } catch (Exception exc) {
                    System.out.println("잘λͺ» μ‚¬μš©ν•œ @Test: " + m);
                }
            }

            if (m.isAnnotationPresent(ExceptionTest.class)) {
                tests++;
                try {
                    m.invoke(null);
                    System.out.printf("ν…ŒμŠ€νŠΈ %s μ‹€νŒ¨: μ˜ˆμ™Έλ₯Ό λ˜μ§€μ§€ μ•ŠμŒ%n", m);
                } catch (InvocationTargetException wrappedEx) {
                    Throwable exc = wrappedEx.getCause();
                    Class<? extends Throwable> excType =
                            m.getAnnotation(ExceptionTest.class).value();
                    if (excType.isInstance(exc)) {
                        passed++;
                    } else {
                        System.out.printf(
                                "ν…ŒμŠ€νŠΈ %s μ‹€νŒ¨: κΈ°λŒ€ν•œ μ˜ˆμ™Έ %s, λ°œμƒν•œ μ˜ˆμ™Έ %s%n",
                                m, excType.getName(), exc);
                    }
                } catch (Exception exc) {
                    System.out.println("잘λͺ» μ‚¬μš©ν•œ @ExceptionTest: " + m);
                }
            }
        }

        System.out.printf("성곡: %d, μ‹€νŒ¨: %d%n",
                passed, tests - passed);
    }
}

args인자둜 λ„˜μ–΄μ˜¨ ν΄λž˜μŠ€μ— λͺ¨λ“  λ©”μ„œλ“œλ₯Ό λ°˜λ³΅ν•˜λ©° μ–΄λ…Έν…Œμ΄μ…˜ 적용된 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©° ν…ŒμŠ€νŠΈν•œλ‹€. (μ–΄λ…Έν…Œμ΄μ…˜μ„ ν†΅ν•œ 좔가적인 처리)

 

μœ„μ—μ„œ λ§Œλ“  μ–΄λ…Έν…Œμ΄μ…˜κ³Ό ν…ŒμŠ€νŠΈλ₯Ό μ‚¬μš©ν•œ ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€μ–΄λ³΄μž.

public class Sample2 {
    @ExceptionTest(ArithmeticException.class)
    public static void m1() {  // 성곡해야 ν•œλ‹€.
        int i = 0;
        i = i / i;
    }
    @ExceptionTest(ArithmeticException.class)
    public static void m2() {  // μ‹€νŒ¨ν•΄μ•Ό ν•œλ‹€. (λ‹€λ₯Έ μ˜ˆμ™Έ λ°œμƒ)
        int[] a = new int[0];
        int i = a[1];
    }
    @ExceptionTest(ArithmeticException.class)
    public static void m3() { }  // μ‹€νŒ¨ν•΄μ•Ό ν•œλ‹€. (μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•ŠμŒ)
}

μ–΄λ…Έν…Œμ΄μ…˜μ˜ λ§€κ°œλ³€μˆ˜ νƒ€μž…μ΄ Class<? extends Throwable> μ΄λ―€λ‘œ Throwable을 ν™•μž₯ν•œ λͺ¨λ“  클래슀λ₯Ό μˆ˜μš©ν•œλ‹€.

이λ₯Ό 톡해 ν…ŒμŠ€νŠΈμ—μ„œλŠ” ‘μ‹€μ œ λ°œμƒν•œ μ˜ˆμ™Έ'와 ‘μ–΄λ…Έν…Œμ΄μ…˜μ— λͺ…μ‹œλœ μ˜ˆμ™Έ'λ₯Ό λΉ„κ΅ν•΄μ„œ 성곡/μ‹€νŒ¨ μ—¬λΆ€λ₯Ό νŒλ‹¨ν•  수 μžˆλ‹€.

반볡 κ°€λŠ₯ μ• λ„ˆν…Œμ΄μ…˜

‘@Repeatable’이 μžλ°”8 λΆ€ν„° μΆ”κ°€λ˜μ—ˆλ‹€.

이번 μ•„μ΄ν…œμ—μ„œ 보여쀀 ν…ŒμŠ€νŠΈ ν”„λ ˆμž„μ›Œν¬λŠ” κ°„λ‹¨ν•˜μ§€λ§Œ λͺ…λͺ…νŒ¨ν„΄λ³΄λ‹¨ μ• λ„ˆν…Œμ΄μ…˜μ΄ λ‚«λ‹€λŠ” 점을 보여쀀닀.

→ 컴파일 단계 μ—λŸ¬ 작기, μ–΄λ…Έν…Œμ΄μ…˜μ„ ν†΅ν•œ ν…ŒμŠ€νŠΈ μ‹€ν–‰ 및 νŒλ‹¨

κ·ΈλŸ¬λ―€λ‘œ, μ• λ„ˆν…Œμ΄μ…˜μœΌλ‘œ ν•  수 μžˆλŠ” 일은 λͺ…λͺ… νŒ¨ν„΄μœΌλ‘œ μ²˜λ¦¬ν•  μ΄μœ λŠ” μ—†λ‹€

μ•„μ΄ν…œ 40 : ‘@Override’ μ• λ„ˆν…Œμ΄μ…˜μ„ μΌκ΄€λ˜κ²Œ μ‚¬μš©ν•˜λΌ

μ˜€λ²„λΌμ΄λ“œ μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λ©΄ λͺ…μ‹œμ μœΌλ‘œ μž¬μ •μ˜ ν•œ 것을 ν‘œν˜„ν•  수 μžˆλ‹€. 이λ₯Ό 톡해 μ‹€μˆ˜λ‘œ νŒŒλΌλ―Έν„° νƒ€μž…μ„ 잘λͺ» 적어 닀쀑 μ •μ˜ν•˜λŠ” κ²½μš°μ— 컴파일 였λ₯˜λ‘œ λ°”λ‘œ μž‘μ•„λ‚Ό 수 μžˆλ‹€.

κ·ΈλŸ¬λ―€λ‘œ, μƒμœ„ 클래슀의 λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜λ €λŠ” λ©”μ„œλ“œμ—λŠ” λͺ¨λ‘ ‘@Override’ μ• λ„ˆν…Œμ΄μ…˜μ„ λ‹¬μž.

μ•„μ΄ν…œ 41 : μ •μ˜ν•˜λ €λŠ” 것이 νƒ€μž…μ΄λΌλ©΄ 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λΌ

아무 λ©”μ„œλ“œλ„ λ‹΄κ³  μžˆμ§€ μ•Šκ³  단지 μžμ‹ μ„ κ΅¬ν˜„ν•˜λŠ” ν΄λž˜μŠ€κ°€ νŠΉμ • 속성을 가짐을 ν‘œμ‹œν•΄μ£ΌλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό ***‘마컀 μ΄ν„°νŽ˜μ΄μŠ€'***라고 ν•œλ‹€.

  • 예) Serializable μΈν„°νŽ˜μ΄μŠ€
    • 이λ₯Ό κ΅¬ν˜„ν•œ ν΄λž˜μŠ€λŠ” 직렬화할 수 μžˆλ‹€κ³  μ•Œλ €μ€€λ‹€.

마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜λ³΄λ‹€ λ‚«λ‹€.

마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 이λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€λ“€μ„ κ΅¬λΆ„ν•˜λŠ” νƒ€μž…μœΌλ‘œ μ“Έ 수 μžˆλ‹€. (마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ λΆˆκ°€)

→ 마컀 μΈν„°νŽ˜μ΄μŠ€λ„ νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„ 였λ₯˜λ₯Ό 컴파일 νƒ€μž„μ— μž‘μ„ 수 μžˆλ‹€.

인수둜 받은 객체가 Serializable을 κ΅¬ν˜„ν–ˆμ„ 거라 κ°€μ •ν•˜κ³  μ„€κ³„λœ λ©”μ„œλ“œλŠ” 컴파일 νƒ€μž„μ— 였λ₯˜λ₯Ό μž‘μ„ 수 μžˆλ‹€.

마컀 μΈν„°νŽ˜μ΄μŠ€ vs 마컀 μ• λ„ˆν…Œμ΄μ…˜

  • 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 이λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€λ“€μ„ κ΅¬λΆ„ν•˜λŠ” νƒ€μž…μœΌλ‘œ μ“Έ 수 μžˆμœΌλ‚˜, 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ 그렇지 μ•Šλ‹€.
  • 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 적용 λŒ€μƒμ„ 더 μ •λ°€ν•˜κ²Œ 지정할 수 μžˆλ‹€.
    • νŠΉμ • 클래슀 λ˜λŠ” μΈν„°νŽ˜μ΄μŠ€μ˜ ν•˜μœ„ νƒ€μž…μ—λ§Œ μ μš©ν•  수 μžˆλ‹€. ex) Set μΈν„°νŽ˜μ΄μŠ€
  • 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ κ±°λŒ€ν•œ μ• λ„ˆν…Œμ΄μ…˜ μ‹œμŠ€ν…œμ˜ 지원을 받을 수 μžˆλ‹€.
    • μ• λ„ˆν…Œμ΄μ…˜μ„ 적극 ν™œμš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μ—μ„œλŠ” μ• λ„ˆν…Œμ΄μ…˜μ΄ 일관성을 μ§€λ‹ˆλŠ” 데 μœ λ¦¬ν•˜λ‹€

ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€ μ™Έμ˜ ν”„λ‘œκ·Έλž¨ μš”μ†Œ(λͺ¨λ“ˆ, νŒ¨ν‚€μ§€, ν•„λ“œ, μ§€μ—­λ³€μˆ˜ λ“±)에 λ§ˆν‚Ήν•΄μ•Ό ν•  λ•Œ μ• λ„ˆν…Œμ΄μ…˜μ„ μ“Έ 수 밖에 μ—†λ‹€.

“λ§ˆν‚Ήμ΄ 된 객체λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ°›λŠ” λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•  일이 μžˆλ‹€” λ©΄ 마컀 μΈν„°νŽ˜μ΄μŠ€

μ–΄λ–€ 것을 μ‚¬μš©ν•˜λŠ”μ§€ λ‚˜μ„μ§€ 곰곰이 μƒκ°ν•΄λ³΄μž.