Skip to content

Latest commit

ย 

History

History
201 lines (165 loc) ยท 7.87 KB

item88.md

File metadata and controls

201 lines (165 loc) ยท 7.87 KB

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

readObject ๋ฉ”์„œ๋“œ

  • ์šฐ๋ฆฌ๋Š” InputObjectStream / OutputObjectStream ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ฝ๊ณ  ์“ด๋‹ค.
  • ์ด ํด๋ž˜์Šค์— ํฌํ•จ๋œ ๋ฉ”์„œ๋“œ๊ฐ€ readObject() / writeObject() ์ด๋‹ค.
  • ํด๋ž˜์Šค์— readObject() / writeObject() ๊ฐ€ ์ •์˜๋˜์–ด ์žˆ๋‹ค๋ฉด, ๊ธฐ๋ณธ ์ง๋ ฌํ™” ๊ณผ์ •์—์„œ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ง๋ ฌํ™”์™€ ์—ญ์ง๋ ฌํ™”๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    • ์ปค์Šคํ…€ํ•œ ์ง๋ ฌํ™” (์ง๋ ฌํ™”์— ํŠน์ • ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ) ์‚ฌ์šฉ.
    • private ๋ฉ”์„œ๋“œ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.
    • ์ด ๋ฉ”์„œ๋“œ๋“ค์˜ ์ฒ˜์Œ์— defaultWriteObject() / defaultReadObject() ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ธฐ๋ณธ ์ง๋ ฌํ™”๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ํ•ด์•ผํ•œ๋‹ค.
    • ๋ฆฌํ”Œ๋ ‰์…˜์„ ํ†ตํ•ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.


readObject ์˜ ๋ฌธ์ œ์ 

  • ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ํŠน์ดํ•œ public ์ƒ์„ฑ์ž์™€ ๊ฐ™๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ, ์ƒ์„ฑ์ž์ฒ˜๋Ÿผ ์œ ํšจ์„ฑ๊ฒ€์‚ฌ, ๋ฐฉ์–ด์  ๋ณต์‚ฌ ๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ๋ถˆ๋ณ€์‹์„ ๋ณด์žฅํ•˜์ง€ ๋ชปํ•œ๋‹ค.

๋ถˆ๋ณ€์‹์„ ๋ณด์žฅํ•˜์ง€ ๋ชปํ•˜๋Š” ์‚ฌ๋ก€ : Period ํด๋ž˜์Šค ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

  • readObject() ๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š์•„์„œ, ์ž๋ฐ”์˜ ๊ธฐ๋ณธ ์ง๋ ฌํ™”๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.
public final class Period implements Serializable {

   private Date start;
   private 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());
   }
}
  • ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐ”์ดํŠธ์ŠคํŠธ๋ฆผ์œผ๋กœ Period ๊ฐ์ฒด๋กœ ์—ญ์ง๋ ฌํ™”ํ•œ๋‹ค๋ฉด?
public class BogusPeriod {
    // ๋ถˆ๋ณ€์‹์„ ๊นจ๋œจ๋ฆฌ๋„๋ก ์กฐ์ž‘๋œ ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ
    private static final byte[] serializedForm = {
        (byte)0xac, (byte)0xed, 0x00, 0x05, 0x73, 0x72, 0x00, 0x06,
        0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x40, 0x7e, (byte)0xf8,
        0x2b, 0x4f, 0x46, (byte)0xc0, (byte)0xf4, 0x02, 0x00, 0x02,
        0x4c, 0x00, 0x03, 0x65, 0x6e, 0x64, 0x74, 0x00, 0x10, 0x4c,
        0x6a, 0x61, 0x76, 0x61, 0x2f, 0x75, 0x74, 0x69, 0x6c, 0x2f,
        0x44, 0x61, 0x74, 0x65, 0x3b, 0x4c, 0x00, 0x05, 0x73, 0x74,
        0x61, 0x72, 0x74, 0x71, 0x00, 0x7e, 0x00, 0x01, 0x78, 0x70,
        0x73, 0x72, 0x00, 0x0e, 0x6a, 0x61, 0x76, 0x61, 0x2e, 0x75,
        0x74, 0x69, 0x6c, 0x2e, 0x44, 0x61, 0x74, 0x65, 0x68, 0x6a,
        (byte)0x81, 0x01, 0x4b, 0x59, 0x74, 0x19, 0x03, 0x00, 0x00,
        0x78, 0x70, 0x77, 0x08, 0x00, 0x00, 0x00, 0x66, (byte)0xdf,
        0x6e, 0x1e, 0x00, 0x78, 0x73, 0x71, 0x00, 0x7e, 0x00, 0x03,
        0x77, 0x08, 0x00, 0x00, 0x00, (byte)0xd5, 0x17, 0x69, 0x22,
        0x00, 0x78
    };

    public static void main(String[] args) {
        Period p = (Period) deserialize(serializedForm);
        System.out.println(p.start);
        System.out.println(p.end);
    }
    
    static Object deserialize(byte[] sf) {
        try {
            return new ObjectInputStream(new ByteArrayInputStream(sf)).readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new IllegalArgumentException(e);
        }
    }
}
  • ์œ„ ๋ฐ”์ดํŠธ์ŠคํŠธ๋ฆผ์˜ ์ •๋ณด๋Š”, start ์˜ ์‹œ๊ฐ์ด end ์˜ ์‹œ๊ฐ๋ณด๋‹ค ๋Š๋ฆฌ๊ฒŒ ์กฐ์ž‘ํ–ˆ๋‹ค.
  • ์ฆ‰, ๋ถˆ๋ณ€์‹์„ ๊บ ๋œจ๋ฆฐ ๊ฐ์ฒด๋กœ ์—ญ์ง๋ ฌํ™”ํ•˜๋„๋ก ์กฐ์ž‘๋˜์—ˆ๋‹ค.
Fri Jan 01 12:00:00 PST 1999 // start ๊ฐ€ ๋” ๋Š๋ฆฌ๋‹ค.
Sun Jan 01 12:00:00 PST 1984 // end ๊ฐ€ ๋” ์ด๋ฅด๋‹ค.

ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

  • readObject ๋ฅผ ์ •์˜ํ•˜๊ณ , ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์‹ค์‹œํ•œ๋‹ค.
  • Period ํด๋ž˜์Šค์— ๋‹ค์Œ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    s.defaultReadObject(); // ๊ธฐ๋ณธ ์ง๋ ฌํ™” ์ˆ˜ํ–‰
    if (start.compareTo(end) > 0) { // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
        throw new InvalidObjectException(start + " ๊ฐ€ " + end + " ๋ณด๋‹ค ๋Šฆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
    }
}


๋ถˆ๋ณ€์‹์„ ๋ณด์žฅํ•˜์ง€ ๋ชปํ•˜๋Š” ์‚ฌ๋ก€ : 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()));

           /*
            * ์•…์˜์ ์ธ start, end ๋กœ์˜ ์ฐธ์กฐ๋ฅผ ์ถ”๊ฐ€.
            */
           byte[] ref = { 0x71, 0, 0x7e, 0, 5 }; // ์•…์˜์ ์ธ ์ฐธ์กฐ
           bos.write(ref); // ์‹œ์ž‘ ํ•„๋“œ
           ref[4] = 4; // ์•…์˜์ ์ธ ์ฐธ์กฐ
           bos.write(ref); // ์ข…๋ฃŒ ํ•„๋“œ

           // ์—ญ์ง๋ ฌํ™” ๊ณผ์ •์—์„œ Period ๊ฐ์ฒด์˜ Date ์ฐธ์กฐ๋ฅผ ํ›”์นœ๋‹ค.
           ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
           period = (Period) in.readObject();
           start = (Date) in.readObject();
           end = (Date) in.readObject();
       } catch (IOException | ClassNotFoundException e) {
           throw new AssertionError(e);
       }
   }
}
    public static void main(String[] args) {
        MutablePeriod mp = new MutablePeriod();
        Period mutablePeriod = mp.period; // ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ์ƒ์„ฑํ•œ Period
        Date pEnd = mp.end; // MutablePeriod ํด๋ž˜์Šค์˜ end ํ•„๋“œ
        
        pEnd.setYear(78); // MutablePeriod ์˜ end ๋ฅผ ๋ฐ”๊ฟจ๋Š”๋ฐ ?
        System.out.println(mutablePeriod.end()); // Period ์˜ ๊ฐ’์ด ๋ฐ”๋€๋‹ค.
        
        pEnd.setYear(69);
        System.out.println(mutablePeriod.end());
    }
  • ๊ฒฐ๊ณผ
Fri Apr 07 19:59:32 KST 1978
Mon Apr 07 19:59:32 KST 1969
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด Period ๋ฅผ ์ง๋ ฌํ™” / ์—ญ์ง๋ ฌํ™”ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ,
  • ์œ„์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ถˆ๋ณ€์‹์„ ๊นจ๋œจ๋ฆด ์ˆ˜ ์žˆ๋‹ค.
  • ์‹ค์ œ๋กœ String ์ด ๋ถˆ๋ณ€์ด๋ผ๋Š” ์‚ฌ์‹ค์— ๊ธฐ๋Œ„ ๋ณด์•ˆ ๋ฌธ์ œ๋“ค์ด ์กด์žฌํ•œ๋‹ค.

ํ•ด๊ฒฐ๋ฒ•

  • ๊ฐ์ฒด๋ฅผ ์—ญ์ง๋ ฌํ™”ํ•  ๋•Œ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†Œ์œ ํ•ด์„œ๋Š” ์•ˆ๋˜๋Š” ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๊ฐ–๋Š” ํ•„๋“œ๋ฅผ ๋ชจ๋‘ ๋ฐฉ์–ด์  ๋ณต์‚ฌํ•œ๋‹ค.
  • ๋ถˆ๋ณ€ ํด๋ž˜์Šค ์•ˆ์˜ ๋ชจ๋“  private ๊ฐ€๋ณ€ ์š”์†Œ๋ฅผ ๋ฐฉ์–ด์  ๋ณต์‚ฌํ•œ๋‹ค.
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
   s.defaultReadObject();

   // ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ํ†ตํ•ด ์ธ์Šคํ„ด์Šค์˜ ํ•„๋“œ๊ฐ’ ์ดˆ๊ธฐํ™”
   start = new Date(start.getTime());
   end = new Date(end.getTime());

   // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
   if (start.compareTo(end) > 0)
       throw new InvalidObjectException(start +" after "+ end);
}
  • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ณด๋‹ค ๋จผ์ € ๋ฐฉ์–ด์  ๋ณต์‚ฌ
    • ๋ฐ˜๋Œ€๋ผ๋ฉด, ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์ดํ›„ ๋ฐฉ์–ด์  ๋ณต์‚ฌ ์ด์ „์— ๋ถˆ๋ณ€์‹์„ ๊นจ๋œจ๋ฆด ํ‹ˆ์ด ์ƒ๊ธด๋‹ค. (item 50)
  • final ํ•„๋“œ๋Š” ๋ฐฉ์–ด์  ๋ณต์‚ฌ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ํ•„๋“œ๋ฅผ final ์ด ์•„๋‹ˆ๊ฒŒ ํ•ด์•ผํ•จ.


๊ธฐ๋ณธ readObject() vs readObject ์ง์ ‘ ์ •์˜ ?

transient ํ•„๋“œ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ํ•„๋“œ์˜ ๊ฐ’์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์—†์ด ํ•„๋“œ์— ๋Œ€์ž…ํ•˜๋Š” public ์ƒ์„ฑ์ž ๋ฅผ ์ถ”๊ฐ€ํ•ด๋„ ๊ดœ์ฐฎ์€๊ฐ€ ?

  • Yes -> ๊ธฐ๋ณธ readObject
  • No -> readObject ์ง์ ‘ ์ •์˜ ํ›„ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์™€ ๋ฐฉ์–ด์  ๋ณต์‚ฌ ์ˆ˜ํ–‰. or ์ง๋ ฌํ™” ํ”„๋ก์‹œ ํŒจํ„ด์‚ฌ์šฉ.

๋งˆ์ง€๋ง‰ ํŒ

  • readObject ๋ฉ”์„œ๋“œ์—์„œ ์žฌ์ •์˜ ๊ฐ€๋Šฅ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ๋œ๋‹ค. (item 19)
    • ํด๋ž˜์Šค๊ฐ€ final ์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋งŒ ํ•ด๋‹น
    • ์ด ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๋ถˆ๋ฆฌ๊ธฐ ์ด์ „์— ์ƒ์„ฑ์ž์˜ ์žฌ์ •์˜๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฏ€๋กœ ์˜ค๋ฅ˜๋ฅผ ๋ฑ‰๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.