浅いコピー
日本語 | 浅い複製 |
英語 | shallow copy |
ふりがな | あさいこぴー |
フリガナ | アサイコピー |
インスタンスの複製を作る時に、フィールドのインスタンスの複製は作らない方法。
clone()メソッドで複製を作る時の方法の1つ。「シャローコピー」とも言う。
フィールドが参照型変数の場合、参照値のみコピーする方法を「浅いコピー」と言う。
対して、参照先のインスタンスの複製を作りセットする方法を「深いコピー」と言う。
Objectクラスのclone()メソッドによるコピーは浅いコピーである。
浅いコピーの場合、全てがコピーされるわけではないため、誤ってコピー元のデータを修正してしまう可能性がある。ただし、深いコピーはインスタンスの複製を作るため処理に時間が掛かるというデメリットがあるため、浅いコピーと深いコピー、どちらがいいかは場面によって選択する必要がある。
clone()メソッドで複製を作る時の方法の1つ。「シャローコピー」とも言う。
フィールドが参照型変数の場合、参照値のみコピーする方法を「浅いコピー」と言う。
対して、参照先のインスタンスの複製を作りセットする方法を「深いコピー」と言う。
Objectクラスのclone()メソッドによるコピーは浅いコピーである。
浅いコピーの場合、全てがコピーされるわけではないため、誤ってコピー元のデータを修正してしまう可能性がある。ただし、深いコピーはインスタンスの複製を作るため処理に時間が掛かるというデメリットがあるため、浅いコピーと深いコピー、どちらがいいかは場面によって選択する必要がある。
参考サイト
// Sample.java
public class Sample
{
public static void main( String[] args )
{
try
{
// 自前で複製を作る場合。
// CopyDataクラスを作ります。
CopyData data = new CopyData();
// 浅いコピーされるObjectクラス。
Object object = new Object();
System.out.println( object.toString() );
// java.lang.Object@152544e
data.setObject( object );
// clone()メソッドで複製を作ります。
CopyData newData = (CopyData)data.clone();
// 中のobjectフィールドが参照するインスタンスは、
// 先ほど作ったObjectクラスのインスタンスと同じです。
System.out.println( newData.getObject().toString() );
// java.lang.Object@152544e
// このように、浅いコピーでは、インスタンスの
// 複製は作られません。
}
catch( CloneNotSupportedException e )
{
e.printStackTrace();
}
try
{
// Objectクラスのclone()メソッドで複製を作る場合。
// CopyDataUseObjectCloneクラスを作ります。
CopyDataUseObjectClone data = new CopyDataUseObjectClone();
// 浅いコピーされるObjectクラス。
Object object = new Object();
System.out.println( object.toString() );
// java.lang.Object@1e04cbf
data.setObject( object );
// clone()メソッドで複製を作ります。
CopyDataUseObjectClone newData = (CopyDataUseObjectClone)data.clone();
// 中のobjectフィールドが参照するインスタンスは、
// 先ほど作ったObjectクラスのインスタンスと同じです。
System.out.println( newData.getObject().toString() );
// java.lang.Object@1e04cbf
// このように、浅いコピーでは、インスタンスの
// 複製は作られません。
}
catch( CloneNotSupportedException e )
{
e.printStackTrace();
}
}
}
/**
* コピーするデータクラス。
*/
class CopyData
{
/** 浅いコピーされるフィールド。 */
private Object object;
public void setObject( Object o )
{
object = o;
}
public Object getObject()
{
return object;
}
/**
* Objectクラスのclone()メソッドをオーバーライドします。
*/
protected Object clone() throws CloneNotSupportedException
{
// 自クラスのインスタンスを作り、フィールドをコピーします。
// フィールドは参照値をそのままコピーします。
// これが浅いコピーです。
CopyData newData = new CopyData();
newData.object = this.object;
return newData;
}
}
/**
* コピーするデータクラス。
* ただしObjectクラスのclone()メソッドを使ってコピーします。
*/
class CopyDataUseObjectClone implements Cloneable
{
/** 浅いコピーされるフィールド。 */
private Object object;
public void setObject( Object o )
{
object = o;
}
public Object getObject()
{
return object;
}
/**
* Objectクラスのclone()メソッドをオーバーライドします。
*/
protected Object clone() throws CloneNotSupportedException
{
// Objectクラスのclone()メソッドで複製します。
return super.clone();
}
}
public class Sample
{
public static void main( String[] args )
{
try
{
// 自前で複製を作る場合。
// CopyDataクラスを作ります。
CopyData data = new CopyData();
// 浅いコピーされるObjectクラス。
Object object = new Object();
System.out.println( object.toString() );
// java.lang.Object@152544e
data.setObject( object );
// clone()メソッドで複製を作ります。
CopyData newData = (CopyData)data.clone();
// 中のobjectフィールドが参照するインスタンスは、
// 先ほど作ったObjectクラスのインスタンスと同じです。
System.out.println( newData.getObject().toString() );
// java.lang.Object@152544e
// このように、浅いコピーでは、インスタンスの
// 複製は作られません。
}
catch( CloneNotSupportedException e )
{
e.printStackTrace();
}
try
{
// Objectクラスのclone()メソッドで複製を作る場合。
// CopyDataUseObjectCloneクラスを作ります。
CopyDataUseObjectClone data = new CopyDataUseObjectClone();
// 浅いコピーされるObjectクラス。
Object object = new Object();
System.out.println( object.toString() );
// java.lang.Object@1e04cbf
data.setObject( object );
// clone()メソッドで複製を作ります。
CopyDataUseObjectClone newData = (CopyDataUseObjectClone)data.clone();
// 中のobjectフィールドが参照するインスタンスは、
// 先ほど作ったObjectクラスのインスタンスと同じです。
System.out.println( newData.getObject().toString() );
// java.lang.Object@1e04cbf
// このように、浅いコピーでは、インスタンスの
// 複製は作られません。
}
catch( CloneNotSupportedException e )
{
e.printStackTrace();
}
}
}
/**
* コピーするデータクラス。
*/
class CopyData
{
/** 浅いコピーされるフィールド。 */
private Object object;
public void setObject( Object o )
{
object = o;
}
public Object getObject()
{
return object;
}
/**
* Objectクラスのclone()メソッドをオーバーライドします。
*/
protected Object clone() throws CloneNotSupportedException
{
// 自クラスのインスタンスを作り、フィールドをコピーします。
// フィールドは参照値をそのままコピーします。
// これが浅いコピーです。
CopyData newData = new CopyData();
newData.object = this.object;
return newData;
}
}
/**
* コピーするデータクラス。
* ただしObjectクラスのclone()メソッドを使ってコピーします。
*/
class CopyDataUseObjectClone implements Cloneable
{
/** 浅いコピーされるフィールド。 */
private Object object;
public void setObject( Object o )
{
object = o;
}
public Object getObject()
{
return object;
}
/**
* Objectクラスのclone()メソッドをオーバーライドします。
*/
protected Object clone() throws CloneNotSupportedException
{
// Objectクラスのclone()メソッドで複製します。
return super.clone();
}
}
// Sample.java public class Sample { public static void main( String[] args ) { try { // 自前で複製を作る場合。 // CopyDataクラスを作ります。 CopyData data = new CopyData(); // 浅いコピーされるObjectクラス。 Object object = new Object(); System.out.println( object.toString() ); // java.lang.Object@152544e data.setObject( object ); // clone()メソッドで複製を作ります。 CopyData newData = (CopyData)data.clone(); // 中のobjectフィールドが参照するインスタンスは、 // 先ほど作ったObjectクラスのインスタンスと同じです。 System.out.println( newData.getObject().toString() ); // java.lang.Object@152544e // このように、浅いコピーでは、インスタンスの // 複製は作られません。 } catch( CloneNotSupportedException e ) { e.printStackTrace(); } try { // Objectクラスのclone()メソッドで複製を作る場合。 // CopyDataUseObjectCloneクラスを作ります。 CopyDataUseObjectClone data = new CopyDataUseObjectClone(); // 浅いコピーされるObjectクラス。 Object object = new Object(); System.out.println( object.toString() ); // java.lang.Object@1e04cbf data.setObject( object ); // clone()メソッドで複製を作ります。 CopyDataUseObjectClone newData = (CopyDataUseObjectClone)data.clone(); // 中のobjectフィールドが参照するインスタンスは、 // 先ほど作ったObjectクラスのインスタンスと同じです。 System.out.println( newData.getObject().toString() ); // java.lang.Object@1e04cbf // このように、浅いコピーでは、インスタンスの // 複製は作られません。 } catch( CloneNotSupportedException e ) { e.printStackTrace(); } } } /** * コピーするデータクラス。 */ class CopyData { /** 浅いコピーされるフィールド。 */ private Object object; public void setObject( Object o ) { object = o; } public Object getObject() { return object; } /** * Objectクラスのclone()メソッドをオーバーライドします。 */ protected Object clone() throws CloneNotSupportedException { // 自クラスのインスタンスを作り、フィールドをコピーします。 // フィールドは参照値をそのままコピーします。 // これが浅いコピーです。 CopyData newData = new CopyData(); newData.object = this.object; return newData; } } /** * コピーするデータクラス。 * ただしObjectクラスのclone()メソッドを使ってコピーします。 */ class CopyDataUseObjectClone implements Cloneable { /** 浅いコピーされるフィールド。 */ private Object object; public void setObject( Object o ) { object = o; } public Object getObject() { return object; } /** * Objectクラスのclone()メソッドをオーバーライドします。 */ protected Object clone() throws CloneNotSupportedException { // Objectクラスのclone()メソッドで複製します。 return super.clone(); } }