Jelenlegi hely

12.4.1. A clone metódus

A clone metódust akkor használjuk, ha létre szeretnénk hozni egy objektumot, egy már meglévő objektumból (másolatot készíteni róla). Az adott osztállyal megegyező típusú új példányt hoz létre:

aCloneableObject.clone();

A metódus a CloneNotSupportedException kivételt dobja, ha a klónozás nem támogatott az osztály számára. A klónozás akkor támogatott, ha az osztály implementálja a Cloneable interfészt. Habár az Object tartalmazza a Clone metódust, nincsen megvalósítva az interfész. Ha az objektum, ahol a clone-ra hivatkoztunk, nem implementálja a cloneable interfészt, egy eredetivel azonos típusú és értékű objektum jön létre. Legegyszerűbb azonban, ha az osztály deklarációban létrehozunk egy implements Cloneable sort.

Bizonyos osztályoknál a helyes működés feltétele a clone felüldefiniálása. Tekintsünk egy Stack osztályt, mely tartalmaz egy tagváltozót, mely az Object-ek tömbjére hivatkozik. Ha a Stack az Object osztály clone metódusára épül, akkor az eredeti és a másolt Stack ugyanazokat az elemeket fogja tartalmazni, mivel az adattag tömb, és másoláskor csak referencia másolás fog történni.

A Stack osztálynak olyan clone implementációra van szüksége, amely lemásolja a Stack objektum adattagjait, ezzel biztosítva a megfelelő tartalom szétválasztást:

public class Stack implements Cloneable {
    private Object[] items;
    private int top;
    ...
    protected Stack clone() {
        try {
            Stack s = (Stack)super.clone(); //clone the stack
            s.items = (Object)items.clone(); //clone the array
            return s; // return the clone
        } catch (CloneNotSupportedException e) {
           //This shouldn't happen because Stack is Cloneable.
            throw new InternalError();
        }
    }
}

Az implementáció viszonylag egyszerű. Először a clone metódus Object implementációja hívódik meg a super.clone segítségével, mely létrehoz és inicializál egy Stack objektumot. Ilyenkor mindkét objektum ugyanazokat az objektumokat tartalmazza. Ezután a metódus lemásolja az objektumokat, és a metódus Stack-el tér vissza.

Megjegyzés: A clone metódus nem a new-t használja a másolat létrehozásánál és nem hív konstruktorokat, helyette a super.clone-t használja, mely létrehozza az objektumot a megfelelő típussal, és engedélyezi a másolást, minek eredményeképpen a kívánt másolatot kapjuk.

Érdemes még azt is megfigyelni, hogy az adattag másolását sem „kézzel” végezte a metódus, hanem a tömb objektum clone metódusával. Ez a metódus egy másik azonos méretű tömböt hoz létre, aminek elemeiről is másolat készül. (A tömbben tárolt tagokról már nem fog másolat készülni, de ez nem is célja egy verem másolásnak.)