0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Javaの固定長配列、「サイズ変更できない」の意味をちゃんと考えていなかった

0
Posted at

この記事を書いた理由

配列はJavaを触り始めた頃から使っているが、「固定長」という性質について、なんとなく「後から増やせない」と覚えているだけで、その背景をちゃんと理解していなかったと気づいた。

特に、サイズを超えてアクセスしたときに ArrayIndexOutOfBoundsException が出る理由や、サイズを変えたいときに内部で何が起きているかを、言語化できていなかった。少し掘り下げて整理しておく。


宣言と初期化の基本

int[] numbers = new int[5];

これで int 型の要素を5つ持つ配列が確保される。配列の要素はメモリの連続したブロックに格納される。インデックスは0始まりなので、アクセスできるのは numbers[0] から numbers[4] まで。

初期値を指定して作る書き方もある。

int[] numbers = new int[]{20, 13, -12, 2, 5};

初期化時に値を渡さない場合、int 型は 0、参照型は null で自動的に埋まる。この挙動は知っていたが、「なぜそうなるのか」をちゃんと説明できなかった。メモリを確保した時点でデフォルト値で初期化されるのがJavaの仕様であり、未初期化のメモリを参照できるC系の言語とは異なる設計だと理解した。


length プロパティの扱い

length は配列が持つプロパティで、要素数を返す。メソッドではないので () は不要。

int[] arr = new int[]{20, 13, -12, 2, 5};

for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

arr.length は宣言時に決まり、その後変更されない。サイズを超えたインデックスにアクセスしようとすると ArrayIndexOutOfBoundsException が発生する。

// arr[5] = 3; // サイズは5なので、インデックス5は存在しない → 例外が発生する

「存在しないインデックスへのアクセスがなぜ危険か」については、配列がメモリの連続領域を確保していることを考えると自然に理解できる。そのブロックの外に書き込もうとしても、Javaの仕様上は例外として弾かれる。


サイズを変えたいときに起きていること

一度作成した配列のサイズは変更できない。では要素を追加したいときはどうするか。

int[] arr = new int[]{20, 13};

// 現在の2倍のサイズで新しい配列を作る
int[] newArr = new int[arr.length * 2];

// 古い配列の内容をコピーする(O(n) の処理)
for (int i = 0; i < arr.length; i++) {
    newArr[i] = arr[i];
}

// 追加の要素を設定する
newArr[2] = 3;
newArr[3] = 15;

新しい配列を作ってコピーするというのが基本的な手順になる。2倍のサイズで確保するのは成長係数の考え方で、頻繁に拡張が必要な場合に毎回ぴったりのサイズで作り直すと、コピー処理が積み重なって非効率になるためだ。

余談だが、ArrayList の内部でも同様の仕組みが使われている。要素数が容量を超えると内部配列を拡張し、コピーが走る。「ArrayList は動的配列」と言われるのは、この拡張処理を自動で行ってくれるからであって、固定長配列の制約がなくなっているわけではない。


頻繁に追加・削除があるなら ArrayList を選ぶ

要素数が変動するケースでは、固定長配列よりも ArrayList が適している。サイズ管理を意識せずに add()remove() が使えるからだ。

一方で、サイズが決まっていてパフォーマンスを意識する場面や、プリミティブ型を扱う場合は固定長配列のほうがシンプルで効率がよい。どちらが「正解か」ではなく、用途によって選ぶという判断が重要だと思っている。


振り返って

「固定長配列はサイズを変えられない」という知識は持っていたが、メモリの連続確保という背景と結びついていなかった。今回整理することで、例外が出る理由やコピーが必要になる理由が、仕様の暗記ではなく構造として理解できた気がする。

まだ整理できていないのは、プリミティブ配列と参照型配列でコピー時の挙動がどう違うか(特に多次元配列のシャローコピーとディープコピーの話)。これは別途手を動かして確認したい。


この記事を書いた人について

株式会社Flexibilityでエンジニアをしています。
DX推進・システム開発を軸に、エンジニアが自律的に動ける環境を大事にしている会社です。

技術的に面白いことをやっていきたい方や、働き方に柔軟さを求めている方は、
よかったら一度のぞいてみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?