μμμ κ³ λ €ν΄ μ€κ³νκ³ λ¬Έμννλ λ°©λ²λ€μ μμ보μ.
1. μμμ© ν΄λμ€λ μ¬μ μν μ μλ λ©μλλ€μ λ΄λΆμ μΌλ‘ μ΄λ»κ² μ΄μ©νλμ§(μκΈ° μ¬μ©) λ¬Έμλ‘ λ¨κ²¨μΌ νλ€. πΊ
μ¬μ μ κ°λ₯ λ©μλλ₯Ό νΈμΆν μ μλ λͺ¨λ μν©μ λ¬Έμλ‘ λ¨κ²¨μΌ νλ€.
μ λͺ ν κ²©μΈ μ€ νλμΈ "μ’μ API λ¬Έμλ 'μ΄λ»κ²'κ° μλ '무μ'μ νλμ§λ₯Ό μ€λͺ ν΄μΌ νλ€"μ λμΉλλ λ΄μ©μ΄κΈ°λ νλ€. νμ§λ§ μμμ΄ μΊ‘μνλ₯Ό ν΄μΉκΈ° λλ¬Έμ ν΄λμ€λ₯Ό μμ νκ² μμν μ μλλ‘ νλ €λ©΄ 'μμλ§ μλμλ€λ©΄ κΈ°μ νμ§ μμμ΄μΌ ν ' λ΄λΆ ꡬν λ°©μμ μ€λͺ ν΄μΌ νλ€.
AbstractCollection.javaμ remove λ©μλλ₯Ό μ΄ν΄λ³΄μ.
μμ κ°μ΄ API λ¬Έμμ λ©μλ μ€λͺ λμ "Implementation Requirements"κ° λΆμ κ±Έ λ³Ό μ μλλ° μ΄κ²μ΄ λ΄λΆ λμ λ°©μμ μ€λͺ νλ κ³³μ΄λ€. IntelliJμ μ€λ₯Έμͺ½ μμ μλ Reader Modeλ₯Ό μ ννλ©΄ μμ κ°μ ννλ‘ λμ¨λ€. μλλ Reader Modeλ₯Ό μ·¨μν κ²½μ°μ΄λ€.
// AbstractCollection.java
/**
* {@inheritDoc}
*
* @implSpec
* This implementation iterates over the collection looking for the
* specified element. If it finds the element, it removes the element
* from the collection using the iterator's remove method.
*
* <p>Note that this implementation throws an
* {@code UnsupportedOperationException} if the iterator returned by this
* collection's iterator method does not implement the {@code remove}
* method and this collection contains the specified object.
*
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean remove(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext()) {
if (it.next()==null) {
it.remove();
return true;
}
}
} else {
while (it.hasNext()) {
if (o.equals(it.next())) {
it.remove();
return true;
}
}
}
return false;
}
ν΄λΉ μ μ λ©μλ μ£Όμμ @implSpec νκ·Έλ₯Ό λΆμ¬μ£Όλ©΄ μλ°λ λκ΅¬κ° μμ±ν΄ μ€λ€. μ΄ νκ·Έλ κΈ°λ³Έκ°μΌλ‘ μ€μ λμ΄ μμ§ μκΈ° λλ¬Έμ λ€μκ³Ό κ°μ μ΅μ μ μΆκ°ν΄μ£Όμ΄μΌ νλ€.
-tag "implSpec:a:Implementation Requirements:"
2. ν΄λμ€μ λ΄λΆ λμ κ³Όμ μ€κ°μ λΌμ΄λ€ μ μλ ν (hook)μ μ μ λ³νμ¬ protected λ©μλ ννλ‘ κ³΅κ°ν΄μΌ ν μλ μλ€. π
java.util.AbstractListμ removeRange λ©μλλ₯Ό μ΄ν΄λ³΄μ.
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
...
public void clear() {
removeRange(0, size());
}
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
}
μ΄ λ©μλλ protectedλ‘ μ 곡νκ³ μλ€. κ·Έ μ΄μ λ clear λ©μλμμ μ΄λ₯Ό μ¬μ©νμ¬ clearλ©μλλ₯Ό κ³ μ±λ₯μΌλ‘ λ§λ€κΈ° μ½κ² νκΈ° μν΄μλ€. λΉμ°ν λ§μ΄μ§λ§ privateλ‘ μ€μ νλ©΄ μμλ°μ κ³³μμ ν΄λΉ λ©μλλ₯Ό μ¬μ©ν μ μκ³ , ν΄λμ€μ λ΄λΆ λμ κ³Όμ μμλ§ μ¬μ©ν κ²μ΄λ―λ‘ publicμΌλ‘ μ€μ ν νμλ μλ€.
3. μμμ© ν΄λμ€λ₯Ό μννλ λ°©λ²μ μ§μ νμ ν΄λμ€λ₯Ό λ§λ€μ΄λ³΄λ κ²μ΄ 'μ μΌ'νλ€. π
2λ²μμ μ΄ν΄λ³Έ κ²κ³Ό κ°μ΄ μμμ© ν΄λμ€λ₯Ό μ€κ³ν λ μ΄λ€ λ©μλλ₯Ό protectedλ‘ λ ΈμΆν΄μΌ ν κΉ? μ ν΄μ§ μ λ΅μ μλ€. μμ½μ§λ§ μ μμΈ‘ν΄ λ³΄κ³ , μ€μ νμ ν΄λμ€λ₯Ό λ§λ€μ΄ μνν΄ λ³΄λ κ²μ΄ μ΅μ μ΄λ€.
μ± μμλ νμ ν΄λμ€λ₯Ό 3κ° μ λ λ§λ€μ΄ 보λ κ²μ μΆμ²νκ³ μλ€. κ·Έλ¦¬κ³ μ΄ μ€ νλ μ΄μμ μ 3μκ° μμ±νλ κ²μ μΆμ²νλ€.
4. μμμ© ν΄λμ€μ μμ±μλ μ§μ μ μΌλ‘λ κ°μ μ μΌλ‘λ μ¬μ μ κ°λ₯ λ©μλλ₯Ό νΈμΆν΄μλ μ λλ€. π
μμ ν΄λμ€μ μμ±μκ° νμ ν΄λμ€μ μμ±μλ³΄λ€ λ¨Όμ μ€νλλ―λ‘ νμ ν΄λμ€μμ μ¬μ μν λ©μλκ° νμ ν΄λμ€μ μμ±μλ³΄λ€ λ¨Όμ νΈμΆλλ€.
μ΄λ κ·Έ μ¬μ μν λ©μλκ° νμ ν΄λμ€μ μμ±μμμ μ΄κΈ°ννλ κ°μ μμ‘΄νλ€λ©΄ μλλλ‘ λμνμ§ μμ κ²μ΄λ€.
public class Super {
// μλͺ»λ μ - μμ±μκ° μ¬μ μ κ°λ₯ λ©μλλ₯Ό νΈμΆνλ€.
public Super() {
overrideMe();
}
public void overrideMe() {
}
}
----------
public class Sub extends Super {
// μ΄κΈ°νλμ§ μμ final νλ. μμ±μμμ μ΄κΈ°νλλ€.
private final Instant instant;
Sub() {
instant = Instant.now();
}
// μ¬μ μ κ°λ₯ λ©μλ. μμ ν΄λμ€μ μμ±μκ° νΈμΆνλ€.
@Override
public void overrideMe() {
System.out.println(instant);
}
}
----------
public static void main(String[] args){
Sub sub = new Sub();
sub.overrideMe();
}
μ½λμμ μ μ μλ―μ΄ μμ ν΄λμ€μ μμ±μκ° μ¬μ μν λ©μλμΈ overrideMe()λ₯Ό νΈμΆνμ¬ NullPointerExceptionμ΄ λ°μνλ€. (νμ§λ§ NullPointerExceptionμ΄ λ°μνμ§ μλλ° κ·Έ μ΄μ λ prinlnμ΄ null μ λ ₯λ λ°μλ€μ΄κΈ° λλ¬Έμ΄λ€.)
λν, Cloneableκ³Ό Serializable μΈν°νμ΄μ€λ μμμ© μ€κ³μ μ΄λ €μμ νμΈ΅ λν΄μ€λ€. cloneκ³Ό readObject λ©μλλ μλ‘μ΄ κ°μ²΄λ₯Ό λ§λ λ€λ μ μμ μμ±μμ λΉμ·ν ν¨κ³Όλ₯Ό λ΄κΈ° λλ¬Έμ΄λ€. κ·Έλ¬λ―λ‘ cloneκ³Ό readObject λͺ¨λ μ§μ μ μΌλ‘λ κ°μ μ μΌλ‘λ μ¬μ μ κ°λ₯ λ©μλλ₯Ό νΈμΆν΄μλ μ λλ€.
5. μμμ κ³ λ €ν΄ μ€κ³νκ³ λ¬Έμννμ§ μμλ€λ©΄, μμμ κΈμ§νλΌ π
μ§κΈκΉμ§ μμμ©μΌλ‘ ν΄λμ€λ₯Ό μ€κ³νκ³ λ¬Έμννλ λ°©λ²μ μμ보μλ€. νμ§λ§ μ΄λ¬ν λ°©λ²λ€μ μ§ν€μ§ μμμ μμμ©μΌλ‘ μ€κ³νμ§ μμ ν΄λμ€κ° μλ€λ©΄ μ΄λ»κ² ν΄μΌ ν κΉ? λΉμ°ν μκΈ°μ§λ§, μμμ κΈμ§ν΄μΌ νλ€.
λν, ν΄λμ€λ₯Ό νμ₯ν΄μΌ ν λͺ νν μ΄μ κ° λ μ€λ₯΄μ§ μμΌλ©΄ μμμ κΈμ§νλ νΈμ΄ λ«λ€.
μμμ κΈμ§νλ 2κ°μ§ λ°©λ²μ΄ μλλ°, 첫 λ²μ§Έλ‘λ ν΄λμ€λ₯Ό finalλ‘ μ μΈνλ λ°©λ²μ΄κ³ , λ λ²μ§Έλ‘λ λͺ¨λ μμ±μλ₯Ό privateμ΄λ package-privateμΌλ‘ μ μΈνκ³ public μ μ ν©ν°λ¦¬λ₯Ό λ§λ€μ΄μ£Όλ λ°©λ²μ΄λ€. (λ κ°μ§ λ°©λ²μ 'λ³κ²½ κ°λ₯μ±μ μ΅μννλΌ - μμ΄ν 17'μ 첫 λ²μ§Έ λ΄μ©κ³Ό λ λ²μ§Έ λ΄μ©μ μ°Έκ³ νμ.)
ν΄λΉ κΈμ λ°±κΈ°μ λμ 'μ΄νν°λΈ μλ° μλ²½ 곡λ΅'μ μ°Έκ³ νμμ΅λλ€.