 |
 |
●配列−2.配列のコピー |
|
| このページでは配列に用意されているlength属性及び、配列のコピーの方法についての説明を
行います。 |
length |
| length属性は配列すべてに用意されている配列サイズを返す属性です。
length( )と言うものもありますが、これはStringオブジェクトやStringBufferオブジェクトの文字列数を返すメソッドであり、配列の属性lengthとは異なります。
length属性はしばしばforループ内で配列に何らかの処理を行いたい時などに使用します。 |
public class ExArray {
public static void main(String[] args) {
int[] intArray = new int[10]; //(1)
for (int i = 0; i < intArray.length; i++) { //(2)
intArray[i] = i * 10; //(3)
System.out.println(intArray[i]); //(4)
}
}
} |
|
| 【解説1】 |
| (1). |
int型の配列intArrayを宣言・生成します。 |
| (2). |
forループの条件式で配列サイズを超えない限り(配列の最後の要素まで)forループの実行文を実行する意味の条件式を記載します。 |
| (3). |
変数i×10の値を順番に配列intArrayの中に代入します。 |
| (4). |
printlnメソッドで配列内に代入された値の表示を行います。 |
D:\JAVA>javac
ExArray.java
D:\JAVA>java ExArray
0
10
20
30
40
50
60
70
80
90
D:\JAVA> |
|
配列のコピー |
| 配列を他の配列へコピーしたいといったことがあります。ここでは配列のコピーの仕方をforループを使用した場合、cloneメソッドを使用した場合、arraycopyメソッドを使用した場合の3つに分け、それぞれ説明します。 |
forループを使用した場合 |
forループを使用し配列のコピーを行う場合は配列のlength属性を使用します。 |
| 【例2】 |
public class ExArray2 {
public static void main(String[] args) {
char[] charArray1 = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; //(1)
char[] charArray2 = new char[charArray1.length]; //(2)
for (int i = 0; i < charArray1.length; i++) { //(3)
charArray2[i] = charArray1[i];
}
for (int i = 0; i < charArray2.length; i++) { //(4)
System.out.println(charArray2[i]);
}
}
}
|
|
| 【解説2】 |
| (1). |
コピー元の配列charArray1を宣言・生成します。 |
| (2). |
コピー先の配列charArray2をcharArray1と同じサイズで宣言・生成します。 |
| (3). |
forループを使用し、charArray1の最後の要素まで順番にcharArray2にデータの代入を行います。 |
| (4). |
コピーが正しく行われているか、charArray2の配列のデータの内容を順番に表示します。 |
D:\JAVA>javac
ExArray2.java
D:\JAVA>java ExArray2
A
B
C
D
E
F
G
D:\JAVA> |
|
cloneメソッドを使用した場合 |
cloneメソッドを使用することによりある配列を別の配列へコピーすることができます。
cloneメソッドはオブジェクトのコピーを行うメソッドです。 |
|
| 【例3】 |
public class ExArray3 {
public static void main(String[] args) {
char[] charArray1 = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; //(1)
char[] charArray2 = (char[])charArray1.clone(); //(2)
for (int i = 0; i < charArray2.length; i++) { //(3)
System.out.println(charArray2[i]);
}
}
} |
|
| 【解説3】 |
| (1). |
コピー元の配列charArray1を宣言・生成します。 |
| (2). |
cloneメソッドを使用し、コピー先の配列charArray2へコピーを行います。cloneメソッドは戻り型としてObject型を返すため、char型配列でキャストします。 |
| (3). |
コピーが正しく行われているか、charArray2の配列のデータの内容を順番に表示します。 |
D:\JAVA>javac
ExArray3.java
D:\JAVA>java ExArray3
A
B
C
D
E
F
G
D:\JAVA> |
|
arraycopyメソッドを使用した場合 |
| arraycopyメソッドを使用することにより配列の範囲を指定して、別の配列へコピーすることができます。arraycopyメソッドはSYSTEMクラスで用意されているメソッドの一つです。 |
|
| 【例4】 |
public class ExArray4 {
public static void main(String[] args) {
int[] FromInt = {1, 2, 3, 4, 5, 6, 7}; //(1)
int[] ToInt = new int[10]; //(2)
System.arraycopy(FromInt, 1, ToInt, 3, 5); //(3)
for (int i = 0; i < ToInt.length; i++) { //(4)
System.out.println(ToInt[i]);
}
}
} |
|
| 【解説4】 |
| (1). |
コピー元の配列FromIntを宣言・生成します。 |
| (2). |
コピー先の配列ToIntを宣言・生成します。 |
| (3). |
arraycopyメソッドを使用し、配列のコピーを行います。ここではFromInt配列のインデックス番号1から5インデックス分をToInt配列のインデックス番号3から順番にコピーをすることを意味します。 |
| (4). |
コピーが正しく行われているか、ToInt配列のデータの内容を順番に表示します。 |
D:\JAVA>javac
ExArray4.java
D:\JAVA>java ExArray4
0
0 //データがコピーされていない個所は初期値である0が表示されます。
0
2 //FromInt配列のインデックス番号1のデータがコピーされています。
3
4
5
6
0
0
D:\JAVA> |
|
配列のコピーの注意点 |
ここでは配列のコピーを行う際の注意点について説明します。Javaではオブジェクトのコピーを行う際、シャローコピー(shallowコピー)、ディープコピー(deepコピー)という2つの方式を意識する必要があります。
シャローコピーとはコピー先のオブジェクトに対し、そのオブジェクトの参照情報のみ複写する方法です。つまりコピー元、コピー先とも同じオブジェクトを参照しています。ディープコピーとはコピー先のオブジェクトに対し、参照情報だけでなくオブジェクトの実体も複写する方法です。シャローコピーを行った場合は、コピー先のオブジェクトの値を変更するとコピー元のオブジェクトの値も変更されます。
配列もオブジェクトですからシャローコピーとディープコピーを考慮する必要があります。cloneメソッド、arraycopyメソッドを使用した場合はシャローコピーとなります。forループを使用した場合はループ内の実装方法の違い(新たなインスタンスを生成するか(ディープ)、代入演算子=によりコピーを行うか(シャロー)。)によりディープコピーにもなりますし、シャローコピーにもなります。どちらの方法を使用するかはケースにより異なります。 |
| 【シャローコピー】 |
|
| 【ディープコピー】 |
 |
| 【例5】 |
| forループでディープコピーした場合とcloneメソッドをシャローコピーした場合のコピーを違いを比較します。 |
|
public class ExArray5 {
public static void main(String[] args) {
StringBuffer[] FromShallow = new StringBuffer[2]; //(1)
FromShallow[0] = new StringBuffer("Sunday");
FromShallow[1] = new StringBuffer("Monday");
StringBuffer[] FromDeep = new StringBuffer[2]; //(2)
FromDeep[0] = new StringBuffer("Sunday");
FromDeep[1] = new StringBuffer("Monday");
StringBuffer[] ToShallow = new StringBuffer[2]; //(3)
StringBuffer[] ToDeep = new StringBuffer[2]; //(4)
//cloneメソッドを使用し、配列のコピーを行います。
ToShallow = (StringBuffer[])FromShallow.clone(); //(5)
//forループを使用し、配列のコピーを行います。
for (int i=0; i < FromDeep.length; i++) { //(6)
ToDeep[i] = new StringBuffer(FromDeep[i].toString());
}
//シャローコピー、ディープコピーが同コピー元に影響を与えるか、
//コピー先のデータを変更しています。
ToShallow[0] = ToShallow[0].replace(0, 3, "Mon"); //(7)
ToDeep[0]= ToDeep[0].replace(0, 3, "Mon"); //(8)
System.out.println
("FromShallow[0]の値Sundayは" + FromShallow[0]); //(9)
System.out.println
("FromDeep[0]の値Sundayは" + FromDeep[0]); //(10)
}
}
|
|
| 【解説5】 |
| (1). |
シャローコピーのコピー元の配列FromShallowを宣言・生成し、その後各配列の要素にStringBufferオブジェクトの生成を行っています。 |
| (2). |
ディープコピーのコピー元の配列FromDeepを宣言・生成し、その後各配列の要素にStringBufferオブジェクトの生成を行っています。 |
| (3). |
FromShallowと同じサイズのシャローコピーのコピー先の配列ToShallowを宣言・生成します。 |
| (4). |
FromDeepと同じサイズのディープコピーのコピー先の配列ToDeepを宣言・生成します。 |
| (5). |
cloneメソッドを使用し、FromShallowの内容をToShallowにコピーします。 |
| (6). |
forループを使用し、FromDeepの内容をToDeepにコピーします。 |
| (7). |
StringBufferクラスのメソッドreplaceを使用し、ToShallowの内容をSundayからMondayに変更しています。 |
| (8). |
StringBufferクラスのメソッドreplaceを使用し、ToDeepの内容をSundayからMondayに変更しています。 |
| (9). |
コピー元配列FromShallowに影響がないか、printlnメソッドで確認を行います。 |
| (10). |
コピー元配列ToShallowに影響がないか、printlnメソッドで確認を行います。 |
D:\JAVA>javac
ExArray5.java
D:\JAVA>java ExArray5
FromShallow[0]の値SundayはMonday //シャローコピーの方はコピー元の
FromDeep[0]の値SundayはSunday //データも変更されています。
D:\JAVA> |
|
配列 |
|
| 2.配列のコピー |
|
|
|
 |
|
 |
 |