連載
» 2005年06月04日 00時00分 公開

Eclipseではじめるプログラミング(9):Javaの「参照型変数」を理解する (1/2)

[小山博史,@IT]
/fjava/index/index_eclipsejava.html

【改訂版】Eclipseではじめるプログラミング New!
これからプログラミングを学習したい方、Javaは難しそうでとっつきづらいという方のためのJavaプログラミング超入門連載です。最新のEclipse 3.4とJava 6を使い大幅に情報量を増やした、本連載「Eclipseではじめるプログラミング」の改訂版となります

 前回までに、Javaには基本型(プリミティブ型)のほかに配列、クラスといった型があることを解説しました。実はJavaの変数の型は基本型と参照型の2つに大きく分けることができ、配列、クラスというのは参照型に含まれる型になります。今回は、この参照型について解説します。また、参照型の中でもよく使うStringクラスについても解説します。

参照型

 最初にこれまでの復習をしましょう。基本型の変数では、変数宣言をすれば、そのまま値を代入できます。つまり、変数宣言と同時に入れ物の確保がされていて、そのまま使用することができるのです。

 一方、配列やクラスの場合は、変数宣言と入れ物(インスタンス)の確保とは別で、new演算子を使って入れ物の確保をする必要があります。入れ物の確保をすると同時に、入れ物を参照するための値(以降、参照値とします)を宣言されている変数へ代入することにより、これを参照することができるようになります。このことから分かるように、new演算子を使って確保をされた入れ物を参照するので、配列やクラスの型は参照型といわれるのです。

 Javaプログラマは変数が参照している入れ物は使えますが、参照型の変数に具体的にどんな参照値が入っているかを知る必要はありませんし、参照値を変更することもできません。この値はJavaの仮想マシンが管理するものなので、プログラマが勝手に変更できてしまうと困るからです。参照型の変数へは入れ物の参照値が設定されているという点はよく理解しておきましょう。ただし、これだけではイメージがつかみにくいため、分かりづらいと思いますので、もう少し詳しく説明をします。

 リスト1のようなプログラムが実行されるときの入れ物確保のイメージは図1のようになります。

int a; // [1]

a = 1; // [2]

Point p; // [3]

p = new Point( ); // [4]

リスト1
図1 変数の入れ物確保のイメージ 図1 変数の入れ物確保のイメージ

 縦長の長方形は入れ物を確保できる場所全体だとします。灰色の長方形は確保された入れ物を表すとします。基本型に含まれるint型の変数aを宣言した時点(リスト1の[1])では、「int型の値」に必要な入れ物が図1の[1]のように確保されます(どこに入れ物が確保されるかはJavaの仮想マシンが管理しているので、どの場所が使われるかをプログラマは意識する必要はありません)。

 aへ値1を代入する(リスト1の[2])と、図1の[2]のように確保された入れ物に1の値が入ります。参照型に含まれるPoint型の変数pを宣言した時点(リスト1の[3])では、Javaの仮想マシンが管理する「参照値」の保持に必要な入れ物が図1の[3]のように確保されます。

 new演算子でPoint型の入れ物を確保してpへその参照値を代入する(リスト1の[4])と、Point型の値に必要な入れ物が確保されて、それの参照値(図1では425)がpに代入されます(図1の[4])。この値(425)はプログラマからは見えませんが、図1の[4]の矢印が表すような参照関係によって、プログラマはpを使って「Point型の値に必要な入れ物」を参照することができます。

Stringクラス

 それでは、参照型に関する理解を深めるために、文字列を表現するときによく利用されるStringクラスの使い方を見てみましょう。Stringクラスにはいろいろなメソッドが用意されています。このうち、よく使われるメソッドを見てみましょう。ここで、Javaでは基本型のchar型というものも用意されています。この型は単一の文字を表現するので、この配列を使うと文字の並びを表現することができます。つまり、charの配列を使って文字列を表現することもあります。このため、Stringからcharの配列へ変換するメソッドや逆の変換をするメソッドがStringクラスには用意されていて、簡単に変換ができるようになっています。それらも使ってみましょう。

 char型とStringクラスを使う前に、これらに対応するリテラルについて説明をしておきます。基本型の解説をしたときに、プログラムの中で値を表現する文字列のことをリテラルと呼ぶことは説明しました。例えば、324は整数値を表すリテラルでint型になります。同じように、char型へ代入できる文字を表すリテラルもあります。それは、文字リテラルといわれ、'0'のようにシングルクオーテーションマークで文字を囲んで記述し、char型となります。また、文字列を表すリテラルもあります。こちらは文字列リテラルといわれ、“0123”のようにダブルクオーテーションマークで文字列を囲んで記述し、String型となります。char型変数やString型変数の初期化をするに当たって、リテラルはよく使うので覚えておきましょう。

Stringクラスを使ったプログラム例

文字列を比較するプログラム

 では、実際にプログラムを作成してみましょう。最初に使い方を示すメソッドをコーディングするクラスの作成をしておきます。手順は以下のとおりです。まずは、Sample90クラスを作成します。第2回の「Eclipseの基本操作に慣れる」と同様にEclipseを起動し、パースペクティブを[Java]に切り替えておいてください。パースペクティブが[Java]になっていないときは、メニューの[ウィンドウ]→[パースペクティブを開く]→[Java]を指定すれば、切り替えることができます。次のような手順で新規にクラスを作成することにします。

  1. [パッケージ・エクスプローラー]の[Sample]をマウス右ボタンでクリック
  2. 表示されるポップアップメニューで[新規]→[クラス]を指定
  3. 表示される[新規Javaクラス]ダイアログで、[名前]にSample90と入力
  4. 同じ[新規Javaクラス]ダイアログで、[どのメソッド・スタブを作成しますか?]のところにある[public static void main(String[] args)]がチェックされていたら、そのチェックを外す
  5. [終了]ボタンをクリック

 出来上がったSample90に、リスト2の水色部分を追加します。フィールドとしてはcharの配列csと、Stringの配列ssを用意します。csの初期化は文字リテラルの配列を作ることで行っています。また、ssの初期化はSample90のコンストラクタで行っています。そこでは、さまざまな方法でString型の配列要素を初期化しています。

 ss[0] は文字列リテラルを代入して初期化しています。ss[1]へはss[0]の参照値を代入しています。ss[2]へは、new String(cs)のようにStringのコンストラクタへcharの配列を渡して作成したインスタンスの参照値を代入しています。ss[3]へは String.valueOf(cs)のようにnew演算子を使わずにcharの配列からStringインスタンスを得て、この参照値を代入しています。

 こうして初期化されたString型の変数について、それぞれの関係が分かるような処理を実行するtestメソッドを用意しました。testメソッドでは、文字列の長さをlengthメソッドで取得し、インスタンスが等しいかを等価演算子(==)で判定し、文字列が等しいかをequalsメソッドで判定しています。そして、それらの結果を画面出力しています。画面出力に当たっては、文字列を連結するために、文字列結合演算子(+)を使っています。この+は算術演算子の加算と同じ記号ですが文法的な意味は異なります。“0123”という文字列と“abcd”という文字列を連結する("0123"+"abcd")と、“0123abcd”という文字列になります。

 mainメソッドはプログラムを起動するための処理を記述しています。Sample90のインスタンスを作成し、そのtestメソッドを実行しています。

リスト2 リスト2

 実行結果は画面1のようになります。結果を見ると、文字列“0123”の長さである4が確かに出力されています。また、ss[0]と同じインスタンスを参照しているss[0]とss[1]は等価演算子(==)による判定とequalsメソッドによる判定のどちらもtrueになることが分かります。しかし、new演算子を使って作成したり、StringのvalueOfメソッドを使って作成したりしたインスタンスを参照するss[2]、ss[3]の変数については、等価演算子の判定はfalse、equalsメソッドの判定はtrueとなることが分かります。このことから、同じ参照値かを判定したいときは等価演算子(==)を、同じ値の文字列かを判定したい場合はequalsメソッドを使う必要があるということが分かります。このように参照型では同じかどうかを判定するときに単純に等価演算子が使えないことがあります。この違いを理解して等価演算子(==)を使うか、equalsメソッドを使うかの判断をするようにしてください。

4

----

true

true

false

false

----

true

true

true

true

画面1

starsWithメソッドを使った文字列の比較

 次に、部分文字列を取得するsubstringメソッドと、文字列が指定された接頭辞で始まるかどうかを判定するstartsWithメソッドの使い方を見てみます。Sample90と同様にして、Sample91を作成してください。出来上がったSample91に、次の水色部分を追加します(リスト3)。

 substringメソッドは、取得する部分文字列の開始位置と終了位置をパラメータとして受け取ります。文字の位置は0から始まる添え字で指定することができます。終了位置は取得する部分文字列の最後の位置に1を加えた値を指定します。従って、開始位置0、終了位置2を指定すると、先頭から2文字分の部分文字列“01”が取得できます。開始位置1、終了位置2を指定すると、先頭の次の文字から1文字分の部分文字列“1”が取得できます。このプログラムでは、こうしてsubstringメソッドで取得した部分文字列をコンソール画面へ出力するのと同時に、sがこの部分文字列で開始するかをstartsWithメソッドで判定して、その結果も出力するようにしています。

 startsWithメソッドは実行結果を見た方が早いので、このプログラムを実行して確認してみましょう。結果は画面2のようになります。まず、substringメソッドにより、s0は“01”、s1は“1”、s2は“2”という文字列になっているのが分かります。次に、これらの文字列をstartsWithメソッドへパラメータとして渡して得られる値は、s0("01")に対してはtrue、s1("1")対してはfalse、s2("2")に対してはfalseとなっています。このことから、s0はsの接頭辞と一致している、s1とs2はsの接頭辞と一致していない、という判定はstartsWithメソッドを使えばできることが分かるはずです。

リスト3 リスト3

01:true

1:false

2:false

画面2

toCharArray()メソッドを使った文字列処理

 次に、String型の文字列をcharの配列へ変換するtoCharArray()メソッドを使ってみましょう。Sample90と同様にして、Sample92を作成してください。出来上がったSample92に、次の水色部分を追加します。(リスト4)。

リスト4 リスト4

 このプログラムは、toCharArray()メソッドによって変換されたcharの配列について、要素の値を1つずつ画面へ出力しています。実行結果は画面3のようになり、確かに文字列“0123”の各文字が配列へ順番に格納されているのが分かります。

s.toCharArray():0 1 2 3

画面3

 ここまでStringクラスの重要なメソッドを見てきましたが、このほかにもたくさんのメソッドがあります。文字列を処理するプログラムを作成する機会は多いので、日ごろからAPIリファレンスを見て使えそうなメソッドを探しておくとよいでしょう。

       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。