item 41 SeungminLee - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

item 41

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

아무 λ©”μ„œλ“œλ„ λ‹΄κ³  μžˆμ§€ μ•Šκ³ , 단지 μžμ‹ μ„ κ΅¬ν˜„ν•˜λŠ” ν΄λž˜μŠ€κ°€ νŠΉμ • 속성을 가짐을 ν‘œμ‹œν•΄μ£ΌλŠ” μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ§ˆμ»€μΈν„°νŽ˜μ΄μŠ€ 라고 ν•œλ‹€. Serializable μΈν„°νŽ˜μ΄μŠ€κ°€ 쒋은 μ˜ˆλ‹€. Serializable은 μžμ‹ μ„ κ΅¬ν˜„ν•  클래슀의 μΈν„°νŽ˜μ΄μŠ€λŠ” ObjectOutputStream을 톡해 μ“Έ 수 μžˆλ‹€κ³  (직렬화 ν•  수 μžˆλ‹€κ³ ) μ•Œλ €μ€€λ‹€.

* @author  unascribed
 * @see java.io.ObjectOutputStream
 * @see java.io.ObjectInputStream
 * @see java.io.ObjectOutput
 * @see java.io.ObjectInput
 * @see java.io.Externalizable
 * @since   JDK1.1
 */
public interface Serializable {
}

마컀 μ• λ„ˆν…Œμ΄μ…˜μ΄ λ“±μž₯ν•˜λ©΄μ„œ 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” ꡬ식이 λ˜μ—ˆλ‹€κ³  ν•˜μ§€λ§Œ μ΄λŠ” 사싀이 μ•„λ‹ˆλ‹€. 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” μ•„λž˜μ™€ 같은 μƒν™©μ—μ„œ 마컀 μ• λ„ˆν…Œμ΄μ…˜λ³΄λ‹€ λ‚«λ‹€.

  • 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 이λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 μΈμŠ€ν„΄μŠ€λ“€μ„ κ΅¬λΆ„ν•˜λŠ” νƒ€μž…μœΌλ‘œ μ“Έ 수 μžˆμœΌλ‚˜, 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ 그렇지 μ•Šλ‹€.
  • 적용 λŒ€μƒμ„ 더 μ •λ°€ν•˜κ²Œ 지정할 수 μžˆλ‹€.

마컀 μ• λ„ˆν…Œμ΄μ…˜ @Test

@Retention(value=RUNTIME)
@Target(value=METHOD)
public @interface Test

아무 λ§€κ°œλ³€μˆ˜ 없이 λ‹¨μˆœνžˆ λŒ€μƒμ— λ§ˆν‚Ήν•œλ‹€ (item 39)

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

마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” μ–΄μ—Ών•œ νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ—, 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν–ˆλ‹€λ©΄ λŸ°νƒ€μž„μ— 발견될 였λ₯˜λ₯Ό 컴파일 νƒ€μž„μ— μž‘μ„ 수 μžˆλ‹€.

/**
     * Underlying writeObject/writeUnshared implementation.
     */
    private void writeObject0(Object obj, boolean unshared)
        throws IOException
    {
        boolean oldMode = bout.setBlockDataMode(false);
        depth++;
        try {
            // handle previously written and non-replaceable objects
            int h;
            if ((obj = subs.lookup(obj)) == null) {
                writeNull();
                return;
            } else if (!unshared && (h = handles.lookup(obj)) != -1) {
                writeHandle(h);
                return;
            } else if (obj instanceof Class) {
                writeClass((Class) obj, unshared);
                return;
            } else if (obj instanceof ObjectStreamClass) {
                writeClassDesc((ObjectStreamClass) obj, unshared);
                return;
            }

            // check for replacement object
            Object orig = obj;
            Class<?> cl = obj.getClass();
            ObjectStreamClass desc;
            for (;;) {
                // REMIND: skip this check for strings/arrays?
                Class<?> repCl;
                desc = ObjectStreamClass.lookup(cl, true);
                if (!desc.hasWriteReplaceMethod() ||
                    (obj = desc.invokeWriteReplace(obj)) == null ||
                    (repCl = obj.getClass()) == cl)
                {
                    break;
                }
                cl = repCl;
            }
            if (enableReplace) {
                Object rep = replaceObject(obj);
                if (rep != obj && rep != null) {
                    cl = rep.getClass();
                    desc = ObjectStreamClass.lookup(cl, true);
                }
                obj = rep;
            }

            // if object replaced, run through original checks a second time
            if (obj != orig) {
                subs.assign(orig, obj);
                if (obj == null) {
                    writeNull();
                    return;
                } else if (!unshared && (h = handles.lookup(obj)) != -1) {
                    writeHandle(h);
                    return;
                } else if (obj instanceof Class) {
                    writeClass((Class) obj, unshared);
                    return;
                } else if (obj instanceof ObjectStreamClass) {
                    writeClassDesc((ObjectStreamClass) obj, unshared);
                    return;
                }
            }

            // remaining cases
            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum<?>) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if (extendedDebugInfo) {
                    throw new NotSerializableException(
                        cl.getName() + "\n" + debugInfoStack.toString());
                } else {
                    throw new NotSerializableException(cl.getName());
                }
            }
        } finally {
            depth--;
            bout.setBlockDataMode(oldMode);
        }
    }

Serializable μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄ ObjectOutputStream.writeObject λ§€μ„œλ“œμ—μ„œ Seralizable 을 κ΅¬ν˜„ν•˜μ§€ μ•Šμ€ 객체λ₯Ό λ°›μœΌλ©΄ 컴파일 νƒ€μž„μ— 였λ₯˜κ°€ λ‚œλ‹€. 이처럼 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 였λ₯˜λ₯Ό 컴파일 νƒ€μž„μ— μž‘μ„ 수 μžˆμ§€λ§Œ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ“Έ 경우 λ°œμƒλœ 였λ₯˜λ₯Ό λŸ°νƒ€μž„μ— κ°€μ„œμ•Ό μž‘μ„ 수 μžˆλ‹€.

마컀 μΈν„°νŽ˜μ΄μŠ€κ°€ λ‚˜μ€ 점 두 λ²ˆμ§ΈλŠ” 적용 λŒ€μƒμ„ 더 μ •λ°€ν•˜κ²Œ 지정할 수 μžˆλ‹€.

적용 λŒ€μƒ(@Target)을 Element.TYPE 으둜 μ„ μ–Έν•œ μ—λ„ˆν…Œμ΄μ…˜μ€ λͺ¨λ“  νƒ€μž…(클래슀, μΈν„°νŽ˜μ΄μŠ€, μ—΄κ±°νƒ€μž…, μ• λ„ˆν…Œμ΄μ…˜)에 달 수 μžˆλ‹€. λΆ€μ°©ν•  수 μžˆλŠ” νƒ€μž…μ„ 더 μ„Έλ°€ν•˜κ²Œ μž¬ν•œν•˜μ§€λŠ” λͺ»ν•œλ‹€λŠ” λœ»μ΄λ‹€.

package java.lang.annotation;

public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE,
    TYPE_PARAMETER,
    TYPE_USE,
    MODULE;

    private ElementType() {
    }
}

νŠΉμ • μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ ν΄λž˜μŠ€μ—λ§Œ μ μš©ν•˜κ³  싢은 λ§ˆμ»€κ°€ μžˆλ‹€κ³  ν•΄λ³΄μž. 이 마컀λ₯Ό μΈν„°νŽ˜μ΄μŠ€λ‘œ μ •μ˜ν–ˆλ‹€λ©΄ κ·Έλƒ₯ λ§ˆν‚Ήν•˜κ³  싢은 ν΄λž˜μŠ€μ—μ„œλ§Œ κ·Έ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λ©΄ λœλ‹€. 그러면 λ§ˆν‚Ήλœ νƒ€μž…μ€ μžλ™μœΌλ‘œ κ·Έ μΈν„°νŽ˜μ΄μŠ€μ˜ ν•˜μœ„ νƒ€μž…μž„μ΄ 보μž₯λ˜λŠ” 것이닀.

Set μΈν„°νŽ˜μ΄μŠ€λ„ μΌμ’…μ˜ 마컀 μΈν„°νŽ˜μ΄μŠ€λ‘œ λ³Ό 수 μžˆλ‹€.

  • Collection ν•˜μœ„ νƒ€μž…μ—λ§Œ μ μš©ν•  수 μžˆλ‹€.
  • Collection이 μ •μ˜ν•œ add, equals, hashCode λ“±μ˜ λ©”μ„œλ“œ μ™Έμ—λŠ” μƒˆλ‘œ μΆ”κ°€ν•œ 것이 μ—†λ‹€.
  • 이런 마컀 μΈν„°νŽ˜μ΄μŠ€λŠ” 객체의 νŠΉμ • 뢀뢄을 λΆˆλ³€μ‹μœΌλ‘œ κ·œμ •ν•˜κ±°λ‚˜ κ·Έ νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λŠ” λ‹€λ₯Έ 클래슀의 νŠΉμ • λ©”μ„œλ“œκ°€ μ²˜λ¦¬ν•  수 μžˆλ‹€λŠ” 사싀을 λͺ…μ‹œν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©ν•  수 μžˆλ‹€. (ex: Serializable μΈν„°νŽ˜μ΄μŠ€λŠ” ObjectOutPutStream이 μ²˜λ¦¬ν•  수 μžˆλŠ” μΈμŠ€ν„΄μŠ€)

λ°˜λŒ€λ‘œ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ΄ 마컀 μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€ λ‚˜μ€ μ μœΌλ‘œλŠ” κ±°λŒ€ν•œ μ• λ„ˆν…Œμ΄μ…˜ μ‹œμŠ€ν…œμ˜ 지원을 λ°›λŠ”λ‹€λŠ” 점을 λ“€ 수 μžˆλ‹€. λ”°λΌμ„œ μ• λ„ˆν…Œμ΄μ…˜μ„ 적극 ν™œμš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μ—μ„œλŠ” 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ“°λŠ” μͺ½μ΄ 일관성을 μ§€ν‚€λŠ”λ° μœ λ¦¬ν•  것이닀.

κ·Έλ ‡λ‹€λ©΄ μ–΄λ–€ λ•Œμ— 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„, 또 μ–΄λ–€ λ•Œμ— 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ¨μ•Όν• κΉŒ?

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

  • μ• λ„ˆν…Œμ΄μ…˜μ„ ν™œλ°œνžˆ ν™œμš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μ—μ„œ μ‚¬μš©ν•˜λŠ” 마컀라면 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” 편이 쒋을 것이닀.

  • 마컀λ₯Ό μΈν„°νŽ˜μ΄μŠ€λ‚˜ ν΄λž˜μŠ€μ— μ μš©ν•΄μ•Ό ν•œλ‹€λ©΄?

    "이 λ§ˆν‚Ήμ΄ 된 객체λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ°›λŠ” λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•  일이 μžˆμ„κΉŒ?" 라고 μžλ¬Έν•΄λ³΄μž.

    'κ·Έλ ‡λ‹€' β†’ 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ¨μ•Όν•œλ‹€. κ·Έ 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν•΄λ‹Ή λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜ νƒ€μž…μœΌλ‘œ μ‚¬μš©ν•˜μ—¬ 컴파일 νƒ€μž„μ— 였λ₯˜λ₯Ό μž‘μ•„λ‚Ό 수 μžˆλ‹€.

    '그런 일은 μ ˆλŒ€ μ—†λ‹€' β†’ μ•„λ§ˆλ„ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ΄ λ‚˜μ€ 선택이닀.

sum up

마컀 μΈν„°νŽ˜μ΄μŠ€μ™€ 마컀 μ• λ„ˆν…Œμ΄μ…˜μ€ 각자의 μ“°μž„μ΄ μžˆλ‹€. μƒˆλ‘œ μΆ”κ°€ν•˜λŠ” λ©”μ„œλ“œ 없이 단지 νƒ€μž… μ •μ˜κ°€ λͺ©μ μ΄λΌλ©΄ 마컀 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μž. 적용 λŒ€μƒμ΄ ElementType.TYPE인 마컀 μ• λ„ˆν…Œμ΄μ…˜μ„ μž‘μ„±ν•˜κ³  μžˆλ‹€λ©΄, μž μ‹œ μ—¬μœ λ₯Ό 가지고 정말 μ• λ„ˆν…Œμ΄μ…˜μœΌλ‘œ κ΅¬ν˜„ν•˜λŠ”κ²Œ μ˜³μ€μ§€, ν˜Ήμ€ 마컀 μΈν„°νŽ˜μ΄μŠ€κ°€ λ‚«μ§€λŠ” μ•Šμ„μ§€ 곰곰이 μƒκ°ν•΄λ³΄μž.