JavaA2Z

KAB-studio > プログラミング > JavaA2Z > cloneとは

clone

日本語 複製、コピー、クローン
英語 clone
ふりがな くろーん
フリガナ クローン

解説

Objectクラスのclone()メソッド
インスタンスを複製するためのメソッド
 
このメソッドには複雑なルールがある。
まず、Objectクラスのclone()メソッドprotectedメソッドのため、外のクラスから直接呼び出すことはできない。このメソッドオーバーライドするか、またはオーバーライドしたclone()メソッド内で呼び出す
 
サブクラスからObjectクラスのclone()メソッド呼び出すことで、そのサブクラスの複製を作成することができる。サブクラスインスタンスが作られ、フィールドの値が全てコピーされてから、Objectクラスのclone()メソッド戻り値としてインスタンス参照が返される。
ただし、Objectクラスのclone()メソッドは、サブクラスCloneableインターフェイス実装クラスでない場合、CloneNotSupportedException例外投げる。つまりObjectクラスのclone()メソッドは、このメソッドが呼ばれることを証明するために、サブクラスCloneableインターフェイス実装を強制する。
 
Objectクラスのclone()メソッドによる複製は、フィールドの値をそのままコピーする。フィールド参照変数の場合、その参照値がそのままコピーされるため、参照先のインスタンスは複製されない。これを「浅いコピー」(シャローコピー)という。
インスタンスも複製する「深いコピー」(ディープコピー)をう場合には、オーバーライドしたclone()メソッド内で各フィールド参照変数参照するインスタンスの複製を作り、セットする必要がある。
 
clone()メソッドによる複製は面倒だが、Javaではクラス参照を通してのみ管理することができ、参照の複製のみではインスタンスは複製されない以上、必須のシステムである。
Javaクラスインスタンス参照を理解した上で、適切に実装できることが望まれる。

(KAB-studioからのおしらせです)

サンプルプログラム(とか)サンプルを別ウィンドウで表示サンプルをクリップボードへコピー(WindowsでIEの場合のみ)

// Sample.java
public class Sample
{
    public static void main( String[] args )
    {
        try
        {
            // DataNotUseSuperクラスの使用例。
            
            // 元インスタンスを作ります。
            DataNotUseSuper data = new DataNotUseSuper();
            data.setData( 100 );
            System.out.println( data.getData() );
            // 100

            // clone()メソッドで複製を作ります。
            DataNotUseSuper dataCloned = (DataNotUseSuper)data.clone();

            // 出力します。
            System.out.println( dataCloned.getData() );
            // 100
        }
        catch( CloneNotSupportedException e )
        {
            e.printStackTrace();
        }

        try
        {
            // DataUseSuperクラスの使用例。

            // 元インスタンスを作ります。
            DataUseSuper data = new DataUseSuper();
            data.setData( 200 );
            System.out.println( data.getData() );
            // 200

            // clone()メソッドで複製を作ります。
            DataUseSuper dataCloned = (DataUseSuper)data.clone();

            // 出力します。
            System.out.println( dataCloned.getData() );
            // 200
        }
        catch( CloneNotSupportedException e )
        {
            e.printStackTrace();
        }

        try
        {
            // DataNotCloneableImplementedクラスの使用例。

            // 元インスタンスを作ります。
            DataNotCloneableImplemented data = new DataNotCloneableImplemented();
            data.setData( 300 );
            System.out.println( data.getData() );
            // 300

            // clone()メソッドで複製を作ります。
            DataNotCloneableImplemented dataCloned = (DataNotCloneableImplemented)data.clone();
        }
        catch( CloneNotSupportedException e )
        {
            // DataNotCloneableImplementedクラスは、Cloneableインターフェイス
            // の実装クラスじゃないのに、Objectクラスのclone()メソッドで
            // 複製を作ろうとしたので、CloneNotSupportedException例外が投げられます。
            e.printStackTrace();
            // java.lang.CloneNotSupportedException: DataNotCloneableImplemented
            //     at java.lang.Object.clone(Native Method)
            //     at DataNotCloneableImplemented.clone(Sample.java:170)
            //     at Sample.main(Sample.java:61)
        }

        // Objectクラスのclone()メソッドはprotectedなので、
        // オーバーライドしないと呼び出せません。
        DataNotCloneOverride data = new DataNotCloneOverride();
        // data.clone();
        // コンパイルエラー:
        // メソッド clone() は型 Object で不可視です。
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドして、
*   手作業でインスタンスを作りフィールドをコピーする例。
*/
class DataNotUseSuper
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

    /**
    *   Objectクラスのclone()メソッドをオーバーライドします。
    */
    protected Object clone() throws CloneNotSupportedException
    {
        // 自クラスのインスタンスを作り、フィールドをコピーします。
        // (自クラスなので、privateフィールドもアクセスできます)
        DataNotUseSuper newData = new DataNotUseSuper();
        newData.data = this.data;
        return newData;
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドして、
*   Objectクラスのclone()メソッドを使用して複製を作ります。
*/
class DataUseSuper implements Cloneable
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

    /**
    *   Objectクラスのclone()メソッドをオーバーライドします。
    */
    protected Object clone() throws CloneNotSupportedException
    {
        // Objectクラスのclone()メソッドで複製を作ります。
        // Cloneableインターフェイスの実装クラスでないと
        // CloneNotSupportedException例外が投げられます。
        return super.clone();
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドして、
*   Objectクラスのclone()メソッドを使用して複製を作ります。
*   ただし、Cloneableインターフェイスの実装クラスでは
*   ありません(つまり間違った例です)。
*/
class DataNotCloneableImplemented
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

    /**
    *   Objectクラスのclone()メソッドをオーバーライドします。
    */
    protected Object clone() throws CloneNotSupportedException
    {
        // Objectクラスのclone()メソッドで複製を作ります。
        // でも、Cloneableインターフェイスの実装クラスではないので
        // CloneNotSupportedException例外が投げられます。
        return super.clone();
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドしていいないクラス。
*   これも間違った例です。
*/
class DataNotCloneOverride
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }
}
// Sample.java
public class Sample
{
    public static void main( String[] args )
    {
        try
        {
            // DataNotUseSuperクラスの使用例。
            
            // 元インスタンスを作ります。
            DataNotUseSuper data = new DataNotUseSuper();
            data.setData( 100 );
            System.out.println( data.getData() );
            // 100

            // clone()メソッドで複製を作ります。
            DataNotUseSuper dataCloned = (DataNotUseSuper)data.clone();

            // 出力します。
            System.out.println( dataCloned.getData() );
            // 100
        }
        catch( CloneNotSupportedException e )
        {
            e.printStackTrace();
        }

        try
        {
            // DataUseSuperクラスの使用例。

            // 元インスタンスを作ります。
            DataUseSuper data = new DataUseSuper();
            data.setData( 200 );
            System.out.println( data.getData() );
            // 200

            // clone()メソッドで複製を作ります。
            DataUseSuper dataCloned = (DataUseSuper)data.clone();

            // 出力します。
            System.out.println( dataCloned.getData() );
            // 200
        }
        catch( CloneNotSupportedException e )
        {
            e.printStackTrace();
        }

        try
        {
            // DataNotCloneableImplementedクラスの使用例。

            // 元インスタンスを作ります。
            DataNotCloneableImplemented data = new DataNotCloneableImplemented();
            data.setData( 300 );
            System.out.println( data.getData() );
            // 300

            // clone()メソッドで複製を作ります。
            DataNotCloneableImplemented dataCloned = (DataNotCloneableImplemented)data.clone();
        }
        catch( CloneNotSupportedException e )
        {
            // DataNotCloneableImplementedクラスは、Cloneableインターフェイス
            // の実装クラスじゃないのに、Objectクラスのclone()メソッドで
            // 複製を作ろうとしたので、CloneNotSupportedException例外が投げられます。
            e.printStackTrace();
            // java.lang.CloneNotSupportedException: DataNotCloneableImplemented
            //     at java.lang.Object.clone(Native Method)
            //     at DataNotCloneableImplemented.clone(Sample.java:170)
            //     at Sample.main(Sample.java:61)
        }

        // Objectクラスのclone()メソッドはprotectedなので、
        // オーバーライドしないと呼び出せません。
        DataNotCloneOverride data = new DataNotCloneOverride();
        // data.clone();
        // コンパイルエラー:
        // メソッド clone() は型 Object で不可視です。
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドして、
*   手作業でインスタンスを作りフィールドをコピーする例。
*/
class DataNotUseSuper
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

    /**
    *   Objectクラスのclone()メソッドをオーバーライドします。
    */
    protected Object clone() throws CloneNotSupportedException
    {
        // 自クラスのインスタンスを作り、フィールドをコピーします。
        // (自クラスなので、privateフィールドもアクセスできます)
        DataNotUseSuper newData = new DataNotUseSuper();
        newData.data = this.data;
        return newData;
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドして、
*   Objectクラスのclone()メソッドを使用して複製を作ります。
*/
class DataUseSuper implements Cloneable
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

    /**
    *   Objectクラスのclone()メソッドをオーバーライドします。
    */
    protected Object clone() throws CloneNotSupportedException
    {
        // Objectクラスのclone()メソッドで複製を作ります。
        // Cloneableインターフェイスの実装クラスでないと
        // CloneNotSupportedException例外が投げられます。
        return super.clone();
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドして、
*   Objectクラスのclone()メソッドを使用して複製を作ります。
*   ただし、Cloneableインターフェイスの実装クラスでは
*   ありません(つまり間違った例です)。
*/
class DataNotCloneableImplemented
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }

    /**
    *   Objectクラスのclone()メソッドをオーバーライドします。
    */
    protected Object clone() throws CloneNotSupportedException
    {
        // Objectクラスのclone()メソッドで複製を作ります。
        // でも、Cloneableインターフェイスの実装クラスではないので
        // CloneNotSupportedException例外が投げられます。
        return super.clone();
    }
}

/**
*   Objectクラスのclone()メソッドをオーバーライドしていいないクラス。
*   これも間違った例です。
*/
class DataNotCloneOverride
{
    private int data;

    public void setData( int i )
    {
        data = i;
    }

    public int getData()
    {
        return data;
    }
}

この単語を含むページ

「みだし」に含まれているページ

「解説」に含まれているページ

「サンプルプログラムとか」に含まれているページ

はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
Yahoo!ブックマーク 詳細を表示 users
del.icio.us 登録する RSSに登録
サンプルを別ウィンドウで表示
サンプルをクリップボードへコピー(WindowsでIEの場合のみ)
update:2005/07/25
このページは、Javaプログラミング言語についての用語を網羅した辞書「JavaA2Z」の一ページです。
詳しくは「JavaA2Z」表紙の説明をご覧ください。