item 56 Jung inchul - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki

Effective Java 3e μ•„μ΄ν…œ 56λ₯Ό μš”μ•½ν•œ λ‚΄μš© μž…λ‹ˆλ‹€.

μžλ°”λ…μ€ μ†ŒμŠ€μ½”λ“œ νŒŒμΌμ—μ„œ λ¬Έμ„œν™” μ£Όμ„μ΄λΌλŠ” νŠΉμˆ˜ν•œ ν˜•νƒœλ‘œ 기술된 μ„€λͺ…을 μΆ”λ € API λ¬Έμ„œλ‘œ λ³€ν™˜ν•΄μ€€λ‹€.

μžλ°” 버전에 따라 μžλ°”λ… νƒœκ·Έλ„ λ°œμ „ν•΄μ™”λ‹€.

  • μžλ°” 5 β†’ @literal, @code
  • μžλ°” 6 β†’ @implSpec
  • μžλ°” 9 β†’ @index

APIλ₯Ό μ˜¬λ°”λ‘œ λ¬Έμ„œν™”ν•˜λ €λ©΄ 곡개된 λͺ¨λ“  클래슀, μΈν„°νŽ˜μ΄μŠ€, λ©”μ„œλ“œ, ν•„λ“œ 선언에 λ¬Έμ„œν™” 주석을 달아야 ν•œλ‹€. 직렬화할 수 μžˆλŠ” 클래슀라면 직렬화 ν˜•νƒœμ— κ΄€ν•΄μ„œλ„ 적어야 ν•œλ‹€.

...
 * {@code AbstractQueuedLongSynchronizer}.
 *
 * <p>This class is Serializable, but all fields are transient,
 * so deserialized conditions have no waiters.
 *
 * @since 1.6
 */
public class ConditionObject implements Condition, java.io.Serializable {

κΈ°λ³Έ μƒμ„±μžμ—λŠ” λ¬Έμ„œν™” 주석을 달 방법이 μ—†μœΌλ‹ˆ 곡개 ν΄λž˜μŠ€λŠ” μ ˆλŒ€ κΈ°λ³Έ μƒμ„±μžλ₯Ό μ‚¬μš©ν•˜λ©΄ μ•ˆλœλ‹€.

public class Person(){
	...

	public Person(String name, int age){
		this.name = name;
		this.age = age;
	}
}

λ©”μ„œλ“œμš© λ¬Έμ„œν™” μ£Όμ„μ—λŠ” ν•΄λ‹Ή λ©”μ„œλ“œμ™€ ν΄λΌμ΄μ–ΈνŠΈ μ‚¬μ΄μ˜ κ·œμ•½μ„ λͺ…λ£Œν•˜κ²Œ κΈ°μˆ ν•΄μ•Ό ν•œλ‹€.

  • howκ°€ μ•„λ‹Œ what을 κΈ°μˆ ν•΄μ•Ό ν•œλ‹€.
  • μ „μ œμ‘°κ±΄(precondition)을 λͺ¨λ‘ λ‚˜μ—΄ν•΄μ•Ό ν•œλ‹€.
  • λ©”μ„œλ“œκ°€ μ„±κ³΅μ μœΌλ‘œ μˆ˜ν–‰λœ 후에 λ§Œμ‘±ν•΄μ•Ό ν•˜λŠ” 사후쑰건도 λͺ¨λ‘ λ‚˜μ—΄ν•΄μ•Ό ν•œλ‹€.
  • μ „μ œμ‘°κ±΄μ€ @throws νƒœκ·Έλ‘œ 비검사 μ˜ˆμ™Έλ₯Ό μ„ μ–Έν•˜μ—¬ μ•”μ‹œμ μœΌλ‘œ κΈ°μˆ ν•œλ‹€.
  • @param νƒœκ·Έλ₯Ό μ΄μš©ν•΄ κ·Έ 쑰건에 영ν–₯ λ°›λŠ” λ§€κ°œλ³€μˆ˜μ— κΈ°μˆ ν•΄μ•Ό ν•œλ‹€.

관둀상 @param νƒœκ·Έμ™€ @return νƒœκ·Έμ˜ μ„€λͺ…은 ν•΄λ‹Ή λ§€κ°œλ³€μˆ˜κ°€ λœ»ν•˜λŠ” κ°’μ΄λ‚˜ λ°˜ν™˜κ°’μ„ μ„€λͺ…ν•˜λŠ” λͺ…사ꡬλ₯Ό μ“΄λ‹€. λ“œλ¬Όκ²ŒλŠ” λͺ…사ꡬ λŒ€μ‹  μ‚°μˆ  ν‘œν˜„μ‹μ„ 쓰기도 ν•œλ‹€. BigInteger의 API λ¬Έμ„œλ₯Ό 참고해보면 λœλ‹€.

/**
 * Returns a BigInteger whose value is {@code (this * val)}.
 *
 * @implNote An implementation may offer better algorithmic
 * performance when {@code val == this}.
 *
 * @param  val value to be multiplied by this BigInteger.
 * @return {@code this * val}
 */
public BigInteger multiply(BigInteger val) {
    return multiply(val, false);
}

@throws μ ˆμ— μ‚¬μš©ν•œ {@code} νƒœκ·ΈλŠ” 두 가지 효과λ₯Ό 가진닀.

  1. νƒœκ·Έλ‘œ 감싼 λ‚΄μš©μ„ μ½”λ“œμš© 폰트둜 λ Œλ”λ§ν•œλ‹€.
  2. νƒœκ·Έλ‘œ 감싼 λ‚΄μš©μ— ν¬ν•¨λœ HTML μš”μ†Œλ‚˜ λ‹€λ₯Έ μžλ°”λ… νƒœκ·Έλ₯Ό λ¬΄μ‹œν•œλ‹€.

클래슀λ₯Ό μƒμ†μš©μœΌλ‘œ 섀계할 λ•ŒλŠ” μžκΈ°μ‚¬μš© νŒ¨ν„΄(self-use patten)에 λŒ€ν•΄μ„œλ„ λ¬Έμ„œμ— 남겨 λ‹€λ₯Έ ν”„λ‘œκ·Έλž˜λ¨Έμ—κ²Œ κ·Έ λ©”μ„œλ“œλ₯Ό μ˜¬λ°”λ‘œ μž¬μ •μ˜ν•˜λŠ” 방법을 μ•Œλ €μ€˜μ•Ό ν•œλ‹€. μžκΈ°μ‚¬μš© νŒ¨ν„΄μ€ μžλ°” 8에 μΆ”κ°€λœ @implSpec νƒœκ·Έλ‘œ λ¬Έμ„œν™”ν•œλ‹€.

@implSpec 주석은 ν•΄λ‹Ή λ©”μ„œλ“œμ™€ ν•˜μœ„ 클래슀 μ‚¬μ΄μ˜ 계약을 μ„€λͺ…ν•˜μ—¬, ν•˜μœ„ ν΄λž˜μŠ€λ“€μ΄ κ·Έ λ©”μ„œλ“œλ₯Ό μƒμ†ν•˜κ±°λ‚˜ super ν‚€μ›Œλ“œλ₯Ό μ΄μš©ν•΄ ν˜ΈμΆœν•  λ•Œ κ·Έ λ©”μ„œλ“œκ°€ μ–΄λ–»κ²Œ λ™μž‘ ν•˜λŠ”μ§€λ₯Ό λͺ…ν™•νžˆ μΈμ§€ν•˜κ³  μ‚¬μš©ν•˜λ„λ‘ ν•΄μ€˜μ•Ό ν•œλ‹€.

/**
 * Returns a sequential {@code Stream} with this collection as its source.
 *
 * <p>This method should be overridden when the {@link #spliterator()}
 * method cannot return a spliterator that is {@code IMMUTABLE},
 * {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}
 * for details.)
 *
 * @implSpec
 * The default implementation creates a sequential {@code Stream} from the
 * collection's {@code Spliterator}.
 *
 * @return a sequential {@code Stream} over the elements in this collection
 * @since 1.8
 */
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

API μ„€λͺ…에 HTML λ©”νƒ€λ¬Έμžλ₯Ό ν¬ν•¨μ‹œν‚€λ €λ©΄ @literal νƒœκ·Έλ‘œ 감싸면 λœλ‹€. **@code νƒœκ·Έμ™€ λΉ„μŠ·ν•˜μ§€λ§Œ μ½”λ“œ 폰트둜 λ Œλ”λ§ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€.**

/**
 * A suspect, such as Colonel Mustard or {@literal Mrs. Peacock}.
 */
public class Suspect { ... }

μžλ°” 10λΆ€ν„°λŠ” {@summary}λΌλŠ” μš”μ•½ μ„€λͺ… μ „μš© νƒœκ·Έκ°€ μΆ”κ°€λ˜μ–΄, ν•œκ²° κΉ”λ”ν•˜κ²Œ μ²˜λ¦¬ν•  수 μžˆλ‹€.

/**
 *{@summary A suspect, such as Colonel Mustard or @literal Mrs. Peacock.}
 */
public class Suspect { ... }

λ©”μ„œλ“œμ™€ μƒμ„±μžμ˜ μš”μ•½ μ„€λͺ…은 ν•΄λ‹Ή λ©”μ„œλ“œμ™€ μƒμ„±μžμ˜ λ™μž‘μ„ μ„€λͺ…ν•˜λŠ” (μ£Όμ–΄κ°€ μ—†λŠ”) 동사ꡬ여야 ν•œλ‹€.

/**
 * Constructs an empty list with the specified initial capacity.
 *
 * @param  initialCapacity  the initial capacity of the list
 * @throws IllegalArgumentException if the specified initial capacity
 *         is negative
 */
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

클래슀, μΈν„°νŽ˜μ΄μŠ€, ν•„λ“œμ˜ μš”μ•½ μ„€λͺ…은 λŒ€μƒμ„ μ„€λͺ…ν•˜λŠ” λͺ…μ‚¬μ ˆμ΄μ–΄μ•Ό ν•œλ‹€.

/**
 * The {@code double} value that is closer than any other to
 * <i>pi</i>, the ratio of the circumference of a circle to its
 * diameter.
 */
public static final double PI = 3.14159265358979323846;

μžλ°” 9λΆ€ν„°λŠ” μžλ°”λ…μ΄ μƒμ„±ν•œ HTML λ¬Έμ„œμ— 검색(색인) κΈ°λŠ₯이 μΆ”κ°€λ˜μ–΄ κ΄‘λŒ€ν•œ API λ¬Έμ„œλ“€μ„ ν•œκ²° μˆ˜μ›”ν•΄μ‘Œλ‹€.

* This method complies with the {@index IEEE 754} standard.

μ œλ„€λ¦­ νƒ€μž…μ΄λ‚˜ μ œλ„€λ¦­ λ©”μ„œλ“œλ₯Ό λ¬Έμ„œν™”ν•  λ•ŒλŠ” λͺ¨λ“  νƒ€μž… λ§€κ°œλ³€μˆ˜μ— 주석을 달아야 ν•œλ‹€.

* @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 *
 * @author  Josh Bloch
 * @see HashMap
 * @see TreeMap
 * @see Hashtable
 * @see SortedMap
 * @see Collection
 * @see Set
 * @since 1.2
 */
public interface Map<K, V> { ... }

μ—΄κ±° νƒ€μž…μ„ λ¬Έμ„œν™”ν•  λ•ŒλŠ” μƒμˆ˜λ“€μ—λ„ 주석을 달아야 ν•œλ‹€.

μ• λ„ˆν…Œμ΄μ…˜ νƒ€μž…μ„ λ¬Έμ„œν™”ν•  λ•ŒλŠ” 멀버듀에도 λͺ¨λ‘ 주석을 달아야 ν•œλ‹€.

/**
 * An instrument section of a symphony orchestra.
 */
public enum OrchestraSection {
	/** Woodwinds, such as flute, clarinet, and oboe. */
	WOODWIND,

	/** Brass instruments, such as french horn and trumpet */
	BRASS,

	/** Percussion instruments, such as timpani and cymbals. */
	PERCUSSION
}

API λ¬Έμ„œν™”μ—μ„œ 자주 λˆ„λ½λ˜λŠ” μ„€λͺ…이 두 가지 μžˆμœΌλ‹ˆ, λ°”λ‘œ μŠ€λ ˆλ“œ μ•ˆμ „μ„±κ³Ό 직렬화 κ°€λŠ₯성이닀. 클래슀 ν˜Ήμ€ 정적 λ©”μ„œλ“œκ°€ μŠ€λ ˆλ“œ μ•ˆμ „ν•˜λ“  그렇지 μ•Šλ“ , μŠ€λ ˆλ“œ μ•ˆμ „ μˆ˜μ€€μ„ λ°˜λ“œμ‹œ API μ„€λͺ…에 포함해야 ν•œλ‹€.

μžλ°”λ…μ€ λ©”μ„œλ“œ 주석을 '상속'μ‹œν‚¬ 수 μžˆλ‹€. λ˜ν•œ {@InhertitDocs} νƒœκ·Έλ₯Ό μ‚¬μš©ν•΄ μƒμœ„ νƒ€μž…μ˜ λ¬Έμ„œν™” 주석을 μž¬μ‚¬μš©ν•  수 μžˆλ‹€λŠ” λœ»μ΄λ‹€.

public abstract class AbstractMemberBuilder extends AbstractBuilder {
	/**
	 * Returns true if this subbuilder has anything to document.
	 *
	 * @return true if this subbuilder has anything to document
	 */
	public abstract boolean hasMembersToDocument();
	...
}
public class MethodBuilder extends AbstractMemberBuilder {

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean hasMembersToDocument() {
	    return !methods.isEmpty();
	}
}
⚠️ **GitHub.com Fallback** ⚠️