深いコピー
| 日本語 | 深い複製 |
| 英語 | 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;
}
}




