深いコピー
日本語 | 深い複製 |
英語 | deep copy |
ふりがな | ふかいこぴー |
フリガナ | フカイコピー |
インスタンスの複製を作る時に、フィールドのインスタンスの複製を作る方法。
clone()メソッドで複製を作る時の方法の1つ。「ディープコピー」とも言う。
フィールドが参照型変数の場合、参照先のインスタンスの複製を作りセットする方法を「深いコピー」と言う。
対して、参照値のみコピーする方法を「浅いコピー」と言う。
深いコピーはフィールドが参照するインスタンスの複製を作るため、複製前のデータを誤って修正してしまう、ということがない。
ただし、インスタンスを新たに作成してしまうため、処理に時間が掛かるというデメリットがある
浅いコピーと深いコピー、どちらがいいかは場面によって選択する必要がある。
clone()メソッドで複製を作る時の方法の1つ。「ディープコピー」とも言う。
フィールドが参照型変数の場合、参照先のインスタンスの複製を作りセットする方法を「深いコピー」と言う。
対して、参照値のみコピーする方法を「浅いコピー」と言う。
深いコピーはフィールドが参照するインスタンスの複製を作るため、複製前のデータを誤って修正してしまう、ということがない。
ただし、インスタンスを新たに作成してしまうため、処理に時間が掛かるというデメリットがある
浅いコピーと深いコピー、どちらがいいかは場面によって選択する必要がある。
参考サイト
// Sample.java
public class Sample
{
public static void main( String[] args )
{
try
{
// 自前で複製を作る場合。
// CopyDataクラスを作ります。
CopyData data = new CopyData();
// シャローコピーされるIntegerクラス。
Integer integer = new Integer( 100 );
// そのIntegerクラスをセットします。
data.setInteger( integer );
// clone()メソッドで複製を作ります。
CopyData newData = (CopyData)data.clone();
// 中のintegerフィールドが参照するインスタンスは、
// 先ほど作ったIntegerクラスのインスタンスとは
// 異なります。
if( integer != newData.getInteger() )
{
System.out.println( "異なるインスタンスです。" );
// 異なるインスタンスです。
}
// このように、深いコピーでは、インスタンスの
// 複製が作られます。
}
catch( CloneNotSupportedException e )
{
e.printStackTrace();
}
}
}
/**
* コピーするデータクラス。
*/
class CopyData
{
/** 深いコピーされるフィールド。 */
private Integer integer;
public void setInteger( Integer i )
{
integer = i;
}
public Integer getInteger()
{
return integer;
}
/**
* Objectクラスのclone()メソッドをオーバーライドします。
*/
protected Object clone() throws CloneNotSupportedException
{
// 自クラスのインスタンスを作り、フィールドをコピーします。
// フィールドは参照先のclone()メソッドを呼び、複製を作ります。
// これが深いコピーです。
CopyData newData = new CopyData();
newData.integer = new Integer( this.integer.intValue() );
return newData;
}
}
public class Sample
{
public static void main( String[] args )
{
try
{
// 自前で複製を作る場合。
// CopyDataクラスを作ります。
CopyData data = new CopyData();
// シャローコピーされるIntegerクラス。
Integer integer = new Integer( 100 );
// そのIntegerクラスをセットします。
data.setInteger( integer );
// clone()メソッドで複製を作ります。
CopyData newData = (CopyData)data.clone();
// 中のintegerフィールドが参照するインスタンスは、
// 先ほど作ったIntegerクラスのインスタンスとは
// 異なります。
if( integer != newData.getInteger() )
{
System.out.println( "異なるインスタンスです。" );
// 異なるインスタンスです。
}
// このように、深いコピーでは、インスタンスの
// 複製が作られます。
}
catch( CloneNotSupportedException e )
{
e.printStackTrace();
}
}
}
/**
* コピーするデータクラス。
*/
class CopyData
{
/** 深いコピーされるフィールド。 */
private Integer integer;
public void setInteger( Integer i )
{
integer = i;
}
public Integer getInteger()
{
return integer;
}
/**
* Objectクラスのclone()メソッドをオーバーライドします。
*/
protected Object clone() throws CloneNotSupportedException
{
// 自クラスのインスタンスを作り、フィールドをコピーします。
// フィールドは参照先のclone()メソッドを呼び、複製を作ります。
// これが深いコピーです。
CopyData newData = new CopyData();
newData.integer = new Integer( this.integer.intValue() );
return newData;
}
}
// Sample.java public class Sample { public static void main( String[] args ) { try { // 自前で複製を作る場合。 // CopyDataクラスを作ります。 CopyData data = new CopyData(); // シャローコピーされるIntegerクラス。 Integer integer = new Integer( 100 ); // そのIntegerクラスをセットします。 data.setInteger( integer ); // clone()メソッドで複製を作ります。 CopyData newData = (CopyData)data.clone(); // 中のintegerフィールドが参照するインスタンスは、 // 先ほど作ったIntegerクラスのインスタンスとは // 異なります。 if( integer != newData.getInteger() ) { System.out.println( "異なるインスタンスです。" ); // 異なるインスタンスです。 } // このように、深いコピーでは、インスタンスの // 複製が作られます。 } catch( CloneNotSupportedException e ) { e.printStackTrace(); } } } /** * コピーするデータクラス。 */ class CopyData { /** 深いコピーされるフィールド。 */ private Integer integer; public void setInteger( Integer i ) { integer = i; } public Integer getInteger() { return integer; } /** * Objectクラスのclone()メソッドをオーバーライドします。 */ protected Object clone() throws CloneNotSupportedException { // 自クラスのインスタンスを作り、フィールドをコピーします。 // フィールドは参照先のclone()メソッドを呼び、複製を作ります。 // これが深いコピーです。 CopyData newData = new CopyData(); newData.integer = new Integer( this.integer.intValue() ); return newData; } }