Item 88. Read Object Method

readObject ๋ฉ”์„œ๋“œ๋Š” ๋ฐฉ์–ด์ ์œผ๋กœ ์ž‘์„ฑํ•˜๋ผ

๋…ผ๋ฆฌ์ /๋ฌผ๋ฆฌ์  ํ‘œํ˜„์ด ๋ถ€ํ•ฉํ•˜์—ฌ ๊ธฐ๋ณธ ์ง๋ ฌํ™” ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๊ดœ์ฐฎ์„ ๊ฒƒ ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ๋ถˆ๋ณ€์‹์„ ๋ณด์žฅํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

public final class Period implements Serializable {

    private final Date start;
    private final Date end;

    public Period(Date start, Date end) {
        this.start = new Date(start.getTime());
        this.end = new Date(end.getTime());
        if (this.start.compareTo(this.end) > 0) {
            throw new IllegalArgumentException(start + " after " + end);
        }
    }

    public Date start() {
        return new Date(start.getTime());
    }

    public Date end() {
        return new Date(end.getTime());
    }

    // ...
}

์ด์œ ๋Š” readObject๊ฐ€ ์‹ค์งˆ์ ์œผ๋กœ ๋˜ ๋‹ค๋ฅธ public ์ƒ์„ฑใ…ˆ๋ฐ” ์—ญํ• ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ƒ์„ฑ์ž์—์„œ ํ•˜๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ readObject์—์„œ๋„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค. ๋ณดํ†ต์€ ์ •์ƒ์ ์œผ๋กœ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค๋กœ ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ์„ ์ƒ์„ฑํ•ด์„œ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ์ž„์˜๋กœ ์ƒ์„ฑ๋œ ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ์„ ์—ญ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.


private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    s.defaultReadObject();

    // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
    if (start.compareTo(end) > 0) {
        throw new InvalidObjectException(start + " after " + end);
    }
}

์ƒ์„ฑ์ž์™€ readObject ๋ฉ”์„œ๋“œ์—์„œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด, ๋ถˆ๋ณ€์‹์„ ์™„์ „ํžˆ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ๋‹ค๋ฅธ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ๋Š” ์ •์ƒ Period ์ธ์Šคํ„ด์Šค์—์„œ ์‹œ์ž‘๋œ ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ ๋์— private Date ํ•„๋“œ๋กœ์˜ ์ฐธ์กฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฐ€๋ณ€ Period ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

public class MutablePeriod {

    public final Period period;

    public final Date start;
    public final Date end;

    public MutablePeriod() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);

            // ์œ ํšจํ•œ Period ์ธ์Šคํ„ด์Šค๋ฅผ ์ง๋ ฌํ™”
            out.writeObject(new Period(new Date(), new Date()));

            // ์•…์˜์ ์ธ ์ด์ „ ๊ฐ์ฒด ์ฐธ์กฐ
            // ์ด๋ฏธ ์ง๋ ฌํ™”๋œ ๊ฐ์ฒด์ธ Period ๋‚ด๋ถ€์˜ Date ํ•„๋“œ๋กœ์˜ ์ฐธ์กฐ๋ฅผ ์ถ”๊ฐ€ 
            byte[] ref = {0x71, 0, 0x7e, 0, 5};
            bos.write(ref); // ์‹œ์ž‘ ํ•„๋“œ
            ref[4] = 4;
            bos.write(ref); // ์ข…๋ฃŒ ํ•„๋“œ

            // Period ์ธ์Šคํ„ด์Šค ์—ญ์ง๋ ฌํ™”
            ObjectInputStream in = new ObjectInputStream(
                    new ByteArrayInputStream(bos.toByteArray()));
            period = (Period) in.readObject();
            start = (Date) in.readObject(); // Period ๋‚ด๋ถ€์˜ Date ๊ฐ์ฒด ์ฐธ์กฐ
            end = (Date) in.readObject(); // Period ๋‚ด๋ถ€์˜ Date ๊ฐ์ฒด ์ฐธ์กฐ
            // ๊ฒฐ๊ณผ์ ์œผ๋กœ start์™€ end๋Š” period์˜ ๋‚ด๋ถ€ Date ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ๋จ
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

public class Main {

    public static void main(String[] args) {
        MutablePeriod mp = new MutablePeriod();
        Period p = mp.period;
        Date pEnd = mp.end; // pEnd๋Š” p์˜ ๋‚ด๋ถ€ Date ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ

        pEnd.setYear(78); // pEnd ๋ณ€๊ฒฝ -> p๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝ๋จ

        System.out.println(p);
    }
}

Period ์ธ์Šคํ„ด์Šค๋Š” ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•œ ์ฑ„ ์ƒ์„ฑ๋์ง€๋งŒ, ๊ณต๊ฒฉ์ž๊ฐ€ ์˜๋„์ ์œผ๋กœ ๋‚ด๋ถ€์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋๊ณ , ์ด๋Š” Period ์ธ์Šคํ„ด์Šค์˜ ๋ถˆ๋ณ€์„ฑ์„ ๊นจ๋œจ๋ฆฌ๊ฒŒ ๋œ๋‹ค. ์ด๋Š” ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๊ฐ–๋Š” ํ•„๋“œ ๋ชจ๋‘๋ฅผ ๋ฐฉ์–ด์ ์œผ๋กœ ๋ณต์‚ฌํ•˜์—ฌ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    s.defaultReadObject();

    // ๋ฐฉ์–ด์  ๋ณต์‚ฌ, ์žฌํ• ๋‹น์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•„๋“œ์— final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ
    start = new Date(start.getTime());
    end = new Date(end.getTime());

    // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
    if (start.compareTo(end) > 0) {
        throw new InvalidObjectException(start + " after " + end);
    }
}

Last updated