Javaで開発を行っていると、既存の配列を複製して、元のデータには影響を与えずに加工したいという場面が頻繁にあります。
しかし、Javaの配列は「オブジェクト」として扱われるため、単に = 演算子で代入しただけではコピーを作ることができません。
この記事では、Javaにおける配列の正しいコピー方法について、手軽な clone() や Arrays.copyOf()、高速な System.arraycopy() などの使い分けを解説します。
さらに、2次元配列やオブジェクト配列で発生する「シャローコピー(浅いコピー)」の問題と、それを回避する「ディープコピー(深いコピー)」の実装方法まで、現在の開発現場で役立つ知識を徹底解説します。
![]() 執筆者:マヒロ |
|
配列コピーの基本と「参照渡し」の落とし穴
まず、なぜJavaの配列コピーで多くの人がつまずくのか、その原因を確認しておきましょう。
「=」で代入してもコピーにはならない
変数をコピーする感覚で、配列変数を別の変数に代入しても、複製は作られません。
コピーされるのは「データの実体」ではなく、「データがどこにあるかを示す住所(参照)」だけだからです。
public class ReferenceCopyExample {
public static void main(String[] args) {
int[] original = {1, 2, 3};
int[] copy = original; // 参照のみをコピー(同じ実体を見る)
copy[0] = 99; // コピー先を変更
// 元の配列も変わってしまう
System.out.println("original[0]: " + original[0]);
System.out.println("copy[0]: " + copy[0]);
}
}
実行結果
original[0]: 99
copy[0]: 99
int[] copy = original; とした時点で、original と copy はメモリ上の同じ配列データを指し示しています。
そのため、copy を変更すると、当然ながら original も変更されたように見えます。
独立した別の配列として扱いたい場合は、新しいメモリ領域を確保して値を移し替える「複製」処理が必要です。
配列を正しく複製する3つの主要な方法
Javaで配列を複製(コピー)するには、主に以下の3つの方法が使われます。
用途や好みに応じて使い分けるのがベストです。
1. clone() メソッド(最も手軽)
配列オブジェクトが標準で持っている clone() メソッドを使う方法です。
記述量が少なく、型変換(キャスト)も不要なため、最も簡単でよく使われます。
int[] original = {1, 2, 3};
int[] copy = original.clone();
2. Arrays.copyOf()(可読性が高い)
java.util.Arrays クラスの便利メソッドを使う方法です。
「配列をコピーする」という意図が読み取りやすく、さらに「新しい配列のサイズ(長さ)」を指定できるのが特徴です。
import java.util.Arrays;
int[] original = {1, 2, 3};
// 第2引数でコピーする長さを指定(元のサイズと同じなら完全コピー)
int[] copy = Arrays.copyOf(original, original.length);
3. System.arraycopy()(高速・詳細制御)
System クラスのメソッドを使う方法です。 他の方法に比べて記述が少し複雑ですが、処理速度が最も高速です。
また、「コピー元の開始位置」や「コピー先の開始位置」を細かく指定できるため、配列の一部だけをコピーしたい場合などに威力を発揮します。
int[] original = {1, 2, 3};
int[] copy = new int[original.length]; // 先に箱を作る必要がある
// (コピー元, 元の開始位置, コピー先, 先の開始位置, コピーする個数)
System.arraycopy(original, 0, copy, 0, original.length);
シャローコピーとディープコピーの違いに注意
int や double などのプリミティブ型(基本データ型)の配列であれば、上記の方法で問題なく複製できます。
しかし、「2次元配列」や「オブジェクトの配列」の場合、上記の方法では不完全なコピー(シャローコピー)になってしまうため注意が必要です。
シャローコピー(浅いコピー)とは
配列という「入れ物」だけを新しく作り、中身(要素)は元の配列と同じオブジェクトを参照している状態です。
clone() や Arrays.copyOf() は、基本的にこのシャローコピーを行います。
// 2次元配列のシャローコピー問題
public class ShallowCopyExample {
public static void main(String[] args) {
int[][] original = {{1, 2}, {3, 4}};
int[][] copy = original.clone(); // 2次元配列をclone
// コピー先の中身を変更
copy[0][0] = 99;
// 元の配列も変わってしまう!
System.out.println("original[0][0]: " + original[0][0]);
}
}
実行結果
original[0][0]: 99
original.clone() で新しい2次元配列を作りましたが、その中に入っている「1次元配列(行)」への参照はコピーされていません。
つまり、copy[0] と original[0] は同じ配列の実体を共有しているため、中身を書き換えると両方に影響が出ます。
ディープコピー(深いコピー)を実現する方法
元の配列と完全に独立したコピーを作るには、配列の階層をたどって、一つひとつの要素を新しく作り直す「ディープコピー」を実装する必要があります。
2次元配列のディープコピー例
public class DeepCopyExample {
public static void main(String[] args) {
int[][] original = {{1, 2}, {3, 4}};
// 元の配列と同じサイズで新しい配列を作成
int[][] copy = new int[original.length][];
// ループを使って、行(内側の配列)ごとにコピーする
for (int i = 0; i < original.length; i++) {
copy[i] = original[i].clone();
}
// コピー先を変更
copy[0][0] = 99;
// 元の配列は影響を受けない
System.out.println("original[0][0]: " + original[0][0]);
System.out.println("copy[0][0]: " + copy[0][0]);
}
}
実行結果
original[0][0]: 1
copy[0][0]: 99
for 文を使って、外側の配列だけでなく、内側の配列ひとつひとつに対して clone() を実行しています。
これにより、すべての階層で新しい実体が生成され、完全に独立した2次元配列が完成しました。
3次元以上の配列や、自作クラスの配列の場合も同様に、中身を一つずつ複製する処理が必要です。
【応用】配列の一部だけを切り出してコピーする
「配列の3番目から5番目までを抜き出したい」といった場合は、Arrays.copyOfRange メソッドが便利です。
import java.util.Arrays;
public class RangeCopyExample {
public static void main(String[] args) {
int[] original = {10, 20, 30, 40, 50};
// インデックス1から、インデックス4の手前(3)までをコピー
int[] subArray = Arrays.copyOfRange(original, 1, 4);
// 配列の中身を表示
System.out.println(Arrays.toString(subArray));
}
}
実行結果
[20, 30, 40]
Arrays.copyOfRange(元配列, 開始インデックス, 終了インデックス) を使用します。
重要なのは、第3引数の「終了インデックス」は範囲に含まれない(未満)という点です。
上記の例では 1, 4 と指定しているため、インデックス 1, 2, 3 の要素がコピーされます。
Javaのスキルを活かして年収を上げる方法
以上、Javaで配列をコピーする方法について解説してきました。
なお、Javaのスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。
Javaエンジニアの需要は非常に高いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなJavaの案件を探しやすくなります。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。


