配列の要素にアクセス

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

このレッスンで分かること

  • arr[i] でインデックス i 番目の要素にアクセスできます (0 始まり)
  • 範囲外アクセス (i < 0i >= arr.length) は ArrayIndexOutOfBoundsException
  • 最小例は if (i < 0 || i >= arr.length) return -1; return arr[i];

配列の要素にアクセス とは

配列の中身を取り出す方法を学ぼう。インデックス指定、0 始まり、ArrayIndexOutOfBoundsException までを一気に押さえる。

配列の要素にアクセスする

配列を作っただけでは、まだ何の役にも立ちません。中に入っている値を取り出して、はじめて「データを使ったプログラム」になります。Java で配列の要素を取り出すには、配列名のあとに [ ] を書いて、その中に インデックス (index) と呼ばれる番号を入れます。たとえば arr[0] arr[1] arr[2] のような書き方です。

インデックスは「何番目か」を表す番号です。Java の配列は 0 始まり なので、最初の要素は arr[0]、次が arr[1]、3 番目が arr[2] になります。日常の「1 番目, 2 番目」という数え方と 1 つズレるので、ここは最初の壁です。

インデックス指定の文法

書き方そのものはとても単純です。次のとおりです。

Java

int[] arr = {10, 20, 30}; int first = arr[0]; // 10 int second = arr[1]; // 20 int third = arr[2]; // 30

arr[0] と書くと配列の中の 0 番目の値、つまり 10 が取り出されます。arr[1] なら 20arr[2] なら 30 です。代入もまったく同じ形でできます。arr[0] = 99; と書けば、最初の要素が 99 に書き換わります。

配列のインデックスと要素の対応を図にすると、次のようになります。

diagram (will load when visible)

図の対応を表でまとめると、次の通りです。

インデックス取り出される値
010
120
230
arr.length - 1最後の要素
arr.length範囲外 (例外)
-1範囲外 (例外)

この「インデックス → 値」のマッピングが、配列の本質です。インデックスは「箱の番号」、値は「箱の中身」と思ってください。int の配列なら、すべての箱に int 型の値が入っています。

最後の要素のインデックス

0 始まりということは、長さ n の配列の最後の要素は arr[n-1] になります。たとえば長さ 3 の配列なら最後は arr[2]、長さ 10 の配列なら最後は arr[9] です。配列の長さは arr.length で取れるので、最後の要素を取り出したいときは次のように書きます。

Java

int[] arr = {10, 20, 30}; int last = arr[arr.length - 1]; // 30

arr.length は配列の 長さ (要素の数) を返します。Strings.length() と違って () が付かない点に注意してください。length は配列が最初から持っているフィールド、length()String クラスのメソッドで、まったくの別物です。

「length と length() の混同」は Java 初心者が必ず一度はやるミスです。配列は length、文字列は length() と覚えましょう。

範囲外アクセスと ArrayIndexOutOfBoundsException

ここからが配列の最大の落とし穴です。配列の長さを超えたインデックスや、マイナスのインデックスを指定するとどうなるでしょうか?

Java

int[] arr = {10, 20, 30}; int x = arr[5]; // ArrayIndexOutOfBoundsException! int y = arr[-1]; // ArrayIndexOutOfBoundsException!

上のようなコードを実行すると、ArrayIndexOutOfBoundsException という例外が発生して プログラムが落ちます。エラーメッセージには「Index 5 out of bounds for length 3」のように、どの index がダメだったかが出ます。

Java では、配列の範囲外アクセスは「気付かないバグ」ではなく「即クラッシュ」として扱われます。これは C 言語などと比べてとても親切な設計で、C だとメモリの変な場所を読み書きしてしまい、見つけにくいバグの原因になります。

では、安全にアクセスするにはどうすればいいでしょう? 答えはシンプルで、読む前にインデックスが範囲内かチェックする ことです。範囲内とは 0 <= index < arr.length のことなので、次のように書けます。

Java

public class Solution { public static int getAt(int[] arr, int index) { if (index < 0 || index >= arr.length) { return -1; } return arr[index]; } }

index < 0 または index >= arr.length のときは「範囲外」と判断して -1 を返し、それ以外なら arr[index] を返します。>= を使う理由は、長さ 3 の配列なら有効な index は 0,1,2 であって、arr[3] はもう範囲外だからです。> ではなく >= を使う点に気をつけましょう。

よくある間違い

配列アクセスは、初心者が必ずつまずく定番ポイントです。よくある間違いを 4 つ整理します。

  • arr.lengtharr.length() の混同 — 配列は length でフィールド、Stringlength() でメソッド。逆にすると「cannot find symbol」コンパイルエラーになる
  • 最後の要素を arr[arr.length] で取ろうとする — 0 始まりなので最後は arr[arr.length - 1]arr[arr.length] は範囲外で ArrayIndexOutOfBoundsException
  • 負のインデックスを渡す — 一部の言語 (例えば Python) では arr[-1] で末尾要素が取れますが、Java では 負のインデックスはすべて例外。便利機能はないので、自分で arr.length - 1 を書く必要がある
  • length == 0 の配列で先頭にアクセスする — 空配列に対して arr[0] を呼ぶと例外。要素にアクセスする前に arr.length > 0 をチェックする習慣を付ける

さらに、int[] arr = new int[3]; のように new で確保した配列は、デフォルト値で初期化されます。int なら 0String なら nullboolean なら false です。「中身を入れた覚えがないのに 0 が返ってくる」のは初期化のせいで、バグではありません。

例外が出たら、まず「どのインデックスでどの長さの配列だったか」を読みましょう。Index 7 out of bounds for length 5 と出たら、length 5 の配列に対して index 7 を読もうとした、という意味です。

この章のポイント

ここまでの要点 配列は 0 始まり。最後は arr[arr.length - 1]、範囲外は例外。アクセス前に 0 <= i < arr.length をチェックする習慣を付ける。

やってみよう

このレッスンの課題では、安全に要素を取り出すメソッド getAt を作ります。仕様は次のとおりです。

  1. 引数の int[] arrint index を受け取る
  2. index が 0 以上かつ arr.length 未満なら、arr[index] を返す
  3. それ以外 (index < 0 または index >= arr.length) なら -1 を返す

例として、getAt(new int[]{10, 20, 30}, 1)20 を返し、getAt(new int[]{10, 20, 30}, 5)-1 を、getAt(new int[]{10, 20, 30}, -1)-1 を返します。

書き上がったら、頭の中で何パターンか動きを追ってみましょう。arr.length3 のとき、index = 2 は OK で、index = 3 は NG。index = 0 は OK で、index = -1 は NG。境界線がどこにあるかを意識すると、>>= の使い分けが体になじみます。

配列の要素アクセスは、これから先のレッスンで何度も出てきます。for ループで全要素を回す、特定の要素を探す、合計を求める、最大値を取る、どれも今回のインデックス指定が基本です。

よくある質問

Q. Java と他言語の文法はどう違いますか?

A. Java は静的型付けで、変数宣言時に型を明示します(int x = 0;)。中括弧でブロックを表し、文末にセミコロンが必要です。Python の動的型付けや JavaScript の柔軟さに慣れていると最初は窮屈ですが、コンパイル時にバグが発見できる安全性がメリットです。

Q. コードが動かないときに最初に見るべき場所は?

A. コンパイルエラーは行番号とエラー種別(cannot find symbol、incompatible types など)が表示されます。実行時例外はスタックトレースの最初の at ... が原因行です。IDE(IntelliJ / VS Code)の警告も丁寧に潰すと、半分のバグは未然に防げます。

Q. Java の習得後に学ぶべき技術は何ですか?

A. 基本構文を抑えたら java-intermediate(コレクション / ジェネリクス / Stream / 例外)に進み、Spring Boot や Web 開発に展開するのが王道です。クラウド時代は Kotlin / Scala への展開も視野に入りますが、まずは Java 標準を固めるのが効率的です。

次のレッスン

次は 配列を for で走査 で、配列の中身を取り出す方法を学ぼう を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. 要素アクセス の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 要素アクセス とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. メソッド名は getAt、引数は int[] arrint index の 2 つ、戻り値の型は int にすること
  2. index0 以上かつ arr.length 未満のとき、arr[index] を返すこと
  3. index0 未満、または arr.length 以上のときは -1 を返すこと (ArrayIndexOutOfBoundsException を発生させない)

入出力例

test-cases.txt

getAt([10,20,30], 1)20 getAt([10,20,30], 0)10 getAt([10,20,30], 5)-1 getAt([10,20,30], -1)-1 getAt([10,20,30], 3)-1 getAt([], 0)-1

ヒント

main.java
main.java
学習モード

メモ

配列の要素にアクセス

⌘S で保存