ITEM 13: overriding clone judiciously
public interface Cloneable {
}
λ©μλ νλ μλ Cloneable
μΈν°νμ΄μ€λ Objectμ protected λ©μλμΈ clone
μ λμλ°©μμ κ²°μ νλ€. Cloneable
μ ꡬνν ν΄λμ€μ μΈμ€ν΄μ€μμ clone
μ νΈμΆνλ©΄ κ·Έ κ°μ²΄μ νλλ€μ νλνλ 볡μ¬ν κ°μ²΄λ₯Ό λ°ννλ©°, ꡬννμ§ μμ ν΄λμ€μ μΈμ€ν΄μ€μμ νΈμΆνλ©΄ CloneNotSupportException
μ λμ§λ€.
μΈν°νμ΄μ€λ₯Ό ꡬννλ€λ κ²μ μΌλ°μ μΌλ‘ ν΄λΉ ν΄λμ€κ° κ·Έ μΈν°νμ΄μ€μμ μ μν κΈ°λ₯μ μ 곡νλ€κ³ μ μΈνλ νμμΈλ°, Cloneable
μ κ²½μ°μλ μμ ν΄λμ€μ μ μλ λμ λ°©μμ λ³κ²½ν κ²μ΄λ―λ‘ λ°λΌνλ κ²μ μ’μ§ μλ€.
λΆλ³ ν΄λμ€λ κ΅³μ΄ clone
μ μ 곡νμ§ μλ κ²μ΄ μ’λ€.
public final class PhoneNumber implements Cloneable{
private final short areaCode, prefix, lineNum;
private int hashCode;
@Override
public PhoneNumber clone(){
try{
// νλ³ν
return (PhoneNumber) super.clone();
}catch (CloneNotSupportedException e){
throw new AssertionError();
}
}
}
public class Object {
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
try-catchλ‘ κ΅¬νν μ΄μ λ Objectμ clone()
μ΄ CloneNotSupportedException
μ λμ Έμ£Όκ³ μκΈ° λλ¬Έμ΄λ©°, Cloneable
μ ꡬννλ©΄ CloneNotSupportedException
μ΄ λ°μνμ§ μμ κ²μ μλ€.
Object λ©μλλ CloneNotSupportedException
μ λμ§λ€κ³ μ μΈνμ§λ§, μ¬μ μν λ©μλμμλ throws
μ μ μμ λ κ²μ΄ μ’λ€. κ²μ¬ μμΈλ₯Ό λμ§μ§ μμμΌ κ·Έ λ©μλλ₯Ό μ¬μ©νκΈ° νΈνκΈ° λλ¬Έμ΄λ€.(λΉκ²μ¬ μμΈ-item71)
clone()
μ μλ³Έ κ°μ²΄μ μλ¬΄λ° ν΄λ₯Ό λΌμΉμ§ μλ λμμ 볡μ λ κ°μ²΄μ λΆλ³μμ 보μ₯ν΄μΌνλ€.
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_CAPACITY];
}
public void push(Object e){
ensureCapacity();
elements[size++] = 0;
}
public Object pop(){
if(size == 0){
throw new EmptyStackException();
}
return elements[--size];
}
// μμλ₯Ό μν 곡κ°μ μ μ΄λ νλ μ΄μ μ¬μ λ₯Ό λλ©°, λλ €μΌνλ κ²½μ° λλ°° μ΄μ λλ¦°λ€.
private void ensureCapacity(){
if(elements.length == size){
elements = Arrays.copyOf(elements, 2*size+1);
}
}
}
μ stack ν΄λμ€λ κ°λ³κ°μ²΄λ₯Ό μ°Έμ‘°νκ³ μλ€.
@Override
public Stack clone() {
try{
Stack result = (Stack) super.clone();
result.elements = elements.clone();
return result;
}catch (CloneNotSupportedException e){
throw new AssertionError();
}
}
μλ³Έ κ°μ²΄λ₯Ό μ μ§νλ©΄μ 볡μ λ κ°μ²΄μ λΆλ³μ μ μ§νλ κ°μ₯ μ¬μ΄ λ°©λ²μ elements λ°°μ΄μ clone
μ μ¬κ·μ μΌλ‘ νΈμΆν΄μ£Όλ κ²μ΄λ€ .μ΄λ, λ°°μ΄μ cloneμ λ°νμ νμ
κ³Ό μ»΄νμΌνμ νμ
λͺ¨λκ° μλ³Έ λ°°μ΄κ³Ό λκ°μ λ°°μ΄μ λ°ννλ―λ‘ λ³λλ‘ νλ³νμ ν΄μ€ νμλ μλ€. λ°λΌμ λ°°μ΄μ 볡μ ν λλ λ°°μ΄μ clone λ©μλλ₯Ό μ¬μ©νλ κ²μ κΆμ₯νλ€.
ννΈ μ Stack ν΄λμ€μ elements νλκ° finalμ΄μλ€λ©΄ final νλλ μλ‘μ΄ κ°μ ν λΉν μ μκΈ°λλ¬Έμ μ clone() λ©μλ λ°©μμ μλνμ§ μλλ€.
Cloneable μν€ν
μ²λ κ°λ³ κ°μ²΄λ₯Ό μ°Έμ‘°νλ νλλ finalλ‘ μ μΈνλΌλ μΌλ° μ©λ²κ³Ό μΆ©λνλ€. μλ³Έκ³Ό 볡μ λ κ°μ²΄κ° κ°λ³ κ°μ²΄λ₯Ό 곡μ ν΄λ λλ€λ©΄ μκ΄μμ§λ§, 볡μ ν μ μλ ν΄λμ€λ₯Ό λ§λ€κΈ° μν΄ μΌλΆ νλμμ final
νμ μλ₯Ό μ κ±°ν΄μΌν μλ μλ€.
public class HashTable implements Cloneable{
private Entry[] buckets = new Entry[10];
private static class Entry {
final Object key;
Object value;
Entry next;
Entry(Object key, Object value, Entry next){
this.key = key;
this.value = value;
this.next = next;
}
Entry deepCopy(){
// ν΄λΉ μνΈλ¦¬κ° κ°λ¦¬ν€λ μ°κ²° 리μ€νΈλ₯Ό μ¬κ·μ μΌλ‘ 볡μ¬
// μ¬κ· νΈμΆμ΄κΈ° λλ¬Έμ, 리μ€νΈμ μμ μ λ§νΌ μ€ν νλ μμ μλΉν΄ 리μ€νΈκ° κΈΈλ©΄ μ€ν μ€λ²νλ‘μ° λ°μ μν μμ.
// return new Entry(key, value, next == null ? null : next.deepCopy());
// μ€νμ€λ²νλ‘μ° λ¬Έμ λ₯Ό νΌνκΈ° μν΄ λ°λ³΅μλ₯Ό μ¬μ©
Entry result = new Entry(key,value, next);
for(Entry p = result; p.next != null; p = p.next)
p.next = new Entry(p.next.key, p.next.value, p.next.next);
return result;
}
}
/**
* μλͺ»λ Clone
* μλ³Έκ³Ό κ°μ μ°κ²° 리μ€νΈλ₯Ό μ°Έμ‘° ν΄ μλ³Έκ³Ό 볡μ λ³Έ λͺ¨λ μκΈ°μΉ μκ² λμν κ°λ₯μ± μκΉ
* @return
* @Override
* public HashTable clone(){
* try{
* HashTable result = (HashTable) super.clone();
* result.buckets = buckets.clone();
* return result;
* }catch (CloneNotSupportedException e){
* throw new AssertionError();
* }
* }
*/
/**
*
* @return
*/
@Override
public HashTable clone(){
try{
HashTable result = (HashTable) super.clone();
result.buckets = new Entry[buckets.length];
for(int i =0 ; i < buckets.length; i++){
if(buckets[i] != null){
result.buckets[i] = buckets[i].deepCopy();
}
}
return result;
}catch (CloneNotSupportedException e){
throw new AssertionError();
}
}
}
HashTable
ν΄λμ€λ₯Ό 보면, Stack
κ³Ό λμΌν λ°©λ²μΌλ‘ clone()
μ ꡬννλ©΄ μλ³Έκ³Ό κ°μ μ°κ²° 리μ€νΈλ₯Ό μ°Έμ‘° ν΄ μλ³Έκ³Ό 볡μ λ³Έ λͺ¨λ μκΈ°μΉ μκ² λμν κ°λ₯μ± μκΈΈ μ μκΈ°λλ¬Έμ, deepCopy()
λ₯Ό λ³λλ‘ κ΅¬ννμ¬ ν΄λΉ μνΈλ¦¬κ° κ°λ¦¬ν€λ μ°κ²° 리μ€νΈλ₯Ό μ¬κ·μ μΌλ‘ 볡μ¬ν΄μ£Όμλ€.
clone()
λ©μλλ μ¬μ μλ μ μλ λ©μλλ₯Ό νΈμΆν΄μλ μλλ€. λ§μ½ clone()
μ΄ νμ ν΄λμ€μμ μ¬μ μν λ©μλλ₯Ό νΈμΆνλ©΄, νμ ν΄λμ€λ 볡μ κ³Όμ μμ μμ μ μνλ₯Ό κ΅μ ν μ μλ κΈ°νλ₯Ό μΌκ²λμ΄ μλ³Έκ³Ό μνκ° λ¬λΌμ§ κ°λ₯μ±μ΄ 컀μ§κ²λλ€.
μμ½νμλ©΄, Cloneable
μ ꡬννλ λͺ¨λ ν΄λμ€λ clone()
μ μ¬μ μν΄μΌ νλ€. μ΄λ μ κ·Ό μ νμλ publicμΌλ‘, λ°ν νμ
μ ν΄λμ€ μμ μΌλ‘ λ³κ²½νλ€. κ°μ₯ λ¨Όμ super.clone
μ νΈμΆν ν νμν νλλ₯Ό μ λΆ μ μ ν μμ ν΄μ€μΌ νλ€. μΌλ°μ μΌλ‘ 'κΉμ ꡬ쑰'μ μ¨μ΄ μλ λͺ¨λ κ°λ³ κ°μ²΄λ₯Ό 볡μ¬νκ³ , 볡μ λ³Έμ΄ κ°μ§ κ°μ²΄ μ°Έμ‘° λͺ¨λκ° λ³΅μ¬λ κ°μ²΄λ€μ κ°λ¦¬ν€κ² ν΄μΌνλ€. κΈ°λ³Έ νμ
νλμ λΆλ³ κ°μ²΄ μ°Έμ‘°λ§μ κ°λ ν΄λμ€λΌλ©΄ μ무 νλλ μμ ν νμλ μλ€.
Cloneable
μ ꡬννμ§ μμ ν΄λμ€λΌλ©΄ λ³΅μ¬ μμ±μμ λ³΅μ¬ ν©ν°λ¦¬λΌλ λ λμ κ°μ²΄ λ³΅μ¬ λ°©μμ μ 곡ν μ μλ€.
// 볡μ¬μμ±μ
public Item(Item item){...};
// λ³΅μ¬ ν©ν°λ¦¬
public static Item newInstance(Item item){...};
λ³΅μ¬ μμ±μλ λ¨μν μμ κ³Ό κ°μ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μΈμλ‘ λ°λ μμ±μλ₯Ό λ§νλ€.
λ³΅μ¬ μμ±μ/ν©ν°λ¦¬λ
μμ±μλ₯Ό μ°μ§ μλ λ°©μμ κ°μ²΄ μμ± λ©μ»€λμ¦μ μ¬μ©νμ§ μλλ€.
μμ±νκ² λ¬Έμνλ κ·μ½μ κΈ°λμ§ μκ³ , μ μμ μΈ final νλ μ©λ²κ³Όλ μΆ©λνμ§ μλλ€.
λΆνμν κ²μ¬ μμΈλ₯Ό λμ§μ§ μκ³ , νλ³νλ νμμΉ μλλ€.
ν΄λΉ ν΄λμ€κ° ꡬνν μΈν°νμ΄μ€ νμ μ μΈμ€ν΄μ€λ₯Ό μΈμλ‘ λ°μ μ μλ€.
λͺ¨λ λ²μ© 컬λ μ
ꡬν체λ Collection
μ΄λ Map
νμ
μ λ°λ μμ±μλ₯Ό μ 곡νλ€. μ΄λ₯Ό μ΄μ©νλ©΄ ν΄λΌμ΄μΈνΈλ μλ³Έμ ꡬν νμ
μ μ½λ§€μ΄μ§ μκ³ λ³΅μ λ³Έμ νμ
μ μ§μ μ νν μ μλ€. (HashSet
μ TreeSet
νμ
μΌλ‘ 볡μ κ°λ₯)
new TreeSet<>(s);
Last updated
Was this helpful?