概要
Arrays.copyOfRange(original, from, to) は、元の配列の一部分を抜き出して新しい配列を作るメソッドです。
ポイントは インデックスのルール:
fromは「含む(inclusive)」開始インデックス。toは「含まない(exclusive)」終了インデックス(つまりto-1までが抜き出される)。- 新しい配列の長さは
to - from。
基本の使い方(整数配列の例)
import java.util.Arrays;
public class SliceExample {
public static void main(String[] args) {
int[] src = {12, 24, 18, 35, 21};
// src[1] から src[3] まで(1,2,3)を抜き出す → 24,18,35
int[] part = Arrays.copyOfRange(src, 1, 4);
System.out.println(Arrays.toString(src)); // [12, 24, 18, 35, 21]
System.out.println(Arrays.toString(part)); // [24, 18, 35]
}
}
Javafrom = 1、to = 4→ 取り出す要素はsrc[1],src[2],src[3]。- 新しい配列は元とは別物(コピーされる)。元配列を変えても新配列は影響を受けない(ただしオブジェクト配列は参照の“浅いコピー”)。
よくある間違い・注意点
toは含まれない(toの要素は結果に入らない)。
例:from=0, to=3はsrc[0], src[1], src[2]の3要素。- 例外が出るケース
originalがnull→NullPointerExceptionfrom < 0またはfrom > original.length→ArrayIndexOutOfBoundsExceptionfrom > to→IllegalArgumentException
toが元配列の長さを超える場合はパディングされる- プリミティブ型(int など):超過分は
0で埋まる。 - 参照型(String など):超過分は
nullで埋まる。
例:元配列長が 5、from=3, to=7の場合、新配列長は 4(7-3)。src[3], src[4], 0, 0のように残りはデフォルト値。
- プリミティブ型(int など):超過分は
- オブジェクト配列の挙動
- 配列の中身(オブジェクト自体)はコピーされず、参照がコピーされるだけ(浅いコピー)。つまり元の要素オブジェクトを変更すると新配列の要素にも影響することがあります。
例:to が配列長を超える例(挙動確認)
import java.util.Arrays;
public class PaddingExample {
public static void main(String[] args) {
int[] src = {1, 2, 3, 4, 5};
int[] a = Arrays.copyOfRange(src, 3, 7); // from=3, to=7
System.out.println(Arrays.toString(a)); // -> [4, 5, 0, 0]
}
}
Javaaは長さ7-3 = 4。src[3]とsrc[4]が入り、残りは0で埋まる。
参照型の例:
String[] s = {"A", "B", "C"};
String[] t = Arrays.copyOfRange(s, 1, 5);
// t -> ["B", "C", null, null]
Javaオブジェクト配列(参照の浅いコピー)例
import java.util.Arrays;
class Item {
String name;
Item(String n){ name = n; }
public String toString(){ return name; }
}
public class ShallowCopy {
public static void main(String[] args) {
Item[] items = { new Item("apple"), new Item("banana"), new Item("cherry") };
Item[] part = Arrays.copyOfRange(items, 0, 2); // apple, banana
// 元のオブジェクトを書き換えると、コピー側も見た目は変わる
items[0].name = "apricot";
System.out.println(Arrays.toString(part)); // [apricot, banana]
}
}
Javapart[0]とitems[0]は同じItemオブジェクトを参照しているため、nameの変更が両方に見える。
完全に同じ長さで配列全体をコピーしたいとき
配列全体をコピーする場合は:
int[] copy = Arrays.copyOfRange(src, 0, src.length);
// または
int[] copy2 = Arrays.copyOf(src, src.length);
Java実践練習
問題1
int[] arr = {5, 10, 15, 20, 25} から 10, 15 を取り出すコードを書け(出力は [10, 15])。
答えのヒント:from = 1, to = 3。
問題2
String[] names = {"Tom","Hanako","Yuki","Sara"} から "Hanako","Yuki","Sara","null" のように長さ4の配列を作るにはどうする?(to と from を指定して)
答えのヒント:from=1, to=5 を使うと、元の長さを超えた分が null で埋まるので結果は ["Hanako","Yuki","Sara",null]。
問題3(注意問題)
次は何が起きる?Arrays.copyOfRange(arr, 4, 2);
→ どうなるか説明せよ。
答え:from > to なので IllegalArgumentException が投げられます。
トラブルシューティング(実際に困りやすいポイント)
- 「配列の終端の要素が入らない!」 →
toをlengthにするのを忘れている可能性あり(toは含まれない)。 - 「例外が出た」 →
fromとtoの値を確認(負の値やfrom>length、from>toになっていないか)。 - 「オブジェクトの中身だけ変わった」 → オブジェクト配列は浅いコピー。元のオブジェクトを変更するとコピー側も変わる。
まとめ(初心者が覚えるべき最重要ポイント)
fromは含む、toは含まない(to-1まで)。- 新しい配列の長さは
to - from。 from < 0/from > length/from > toは例外。toが長さを超えるとデフォルト値で埋められる(int→0、参照型→null)。- オブジェクト配列は参照の浅いコピー。
