EeBlog(テクニカルブログ)

第28回 cloneメソッド

今回のテーマは「cloneメソッド」です。

cloneメソッドは自分自身の複製を行うメソッドです。 Objectクラスで宣言されているprotectメソッドであり、Objectクラスを除く全てのクラスはObjectクラスのサブクラスなので、どのクラスでもcloneメソッドを呼び出すことが可能です。 しかし、呼び出すことが可能であっても、使うことができるとは限りません。 というのは、cloneメソッドを使用するためには、Cloneableインターフェースをインプリメントする必要があるからです。 もしCloneableインターフェースをインプリメントせずにcloneメソッドを実行した場合、CloneNotSupportedExceptionが発生します。 Cloneableインターフェース自体はマーカーインターフェースであり、特別なメソッドを実装する必要はありません。

それでは実際にサンプルを見て確認していきましょう。 まずはいつものSportsインターフェースとその具象クラスです。

public interface Sports {
    void play();
}
public class Badminton implements Sports {     
    @Override
    public void play() {
        System.out.println("バドミントンして遊びます。");
    }
}

今回はPlayerクラスでcloneメソッドを使用しています。

public class Player implements Cloneable {
    private Sports sports;

    public Player(Sports sports) {
        this.sports = sports;         
        System.out.println("コンストラクタです。"); 
    }
    public void play() { 
        System.out.println("ウォームアップします。");

        sports.play();

        System.out.println("クールダウンします。");
    }
    public Player createClone() {
        Player player = null; 
        try {         
            player = (Player) clone(); 
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();
        }         
        return player;  
   }
}

Mainクラスでは実際に複製を行います。

public class Main {     
    public static void main(String[] args) throws Exception { 
        Player player = new Player(new Badminton());    
        player.play();    
        System.out.println();

        Player clonePlayer = player.createClone();      
        clonePlayer.play();       
        System.out.println(player == clonePlayer);    
    }
}

Badmintonを保持したPlayerが複製されました。 当然、複製元と複製先のインスタンスは異なります。 またcloneメソッドによるインスタンス生成時には、コンストラクタが呼ばれません。 コンストラクタが呼ばれない特殊なインスタンス生成として覚えておきましょう。

 

次回はcloneメソッドに関連して、シャローコピーとディープコピーについて学びます。