Javaの参照型を文字列操作で理解して文法を総復習【改訂版】Eclipseではじめるプログラミング(8)(2/3 ページ)

» 2009年06月16日 00時00分 公開
[小山博史株式会社ガリレオ]

Stringクラスの文字列比較で参照型を理解する

 では、実際にプログラムを作成してみましょう。文字列を比較するプログラムを作って動作させます。次のような手順で、新規にSample80クラスを作成することにします。

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

 出来上がったSample80を、リスト2のように編集します。

public class Sample80{
 
    char [] cs = { '0', '1', '2', '3' };
    String[] ss = new String[4];
 
    // コンストラクタ
    public Sample80() {
        // ss[0]はStringリテラルを参照
        ss[0] = "0123";
        // ss[1]は「ss[0]が参照するStringリテラル」を参照
        ss[1] = ss[0];
        // ss[2]はcsから生成したStringオブジェクトを参照
        ss[2] = new String(cs);
        // ss[3]はcsの値を持つStringオブジェクトを参照
        ss[3] = String.valueOf(cs);
    }
  
    // == と equalメソッドを使って比較
    public void test() {
        // 文字数の表示
        System.out.println(ss[0].codePointCount(0, ss[0].length()));
 
        // == を使って比較
        System.out.println("----");
        System.out.println(ss[0] == ss[0]); // [1]
        System.out.println(ss[0] == ss[1]); // [2]
        System.out.println(ss[0] == ss[2]); // [3]
        System.out.println(ss[0] == ss[3]); // [4]
 
        // equalメソッドを使って比較
        System.out.println("----");
        System.out.println(ss[0].equals(ss[0])); // [5]
        System.out.println(ss[0].equals(ss[1])); // [6]
        System.out.println(ss[0].equals(ss[2])); // [7]
        System.out.println(ss[0].equals(ss[3])); // [8]
    }
 
    // Sample80のインスタンス生成と、testメソッド実行だけ行う
    public static void main(String[] args) {
        Sample80 sample80 = new Sample80();
        sample80.test();
    }
}
リスト2

コンストラクタとメソッドの違い

 フィールドとしてはcharの配列csと、Stringの配列ssを用意します。csの初期化は文字リテラルの配列を作ることで行っています。また、ssの初期化はSample80のコンストラクタで行っています。

 「public Sample80() { …… } 」の処理は、「コンストラクタ」と呼ばれるものです。ここでは、フィールド「ss」を初期化しています。main()メソッド内で、「new Sample80();」とインスタンス生成をしていますが、このインスタンス生成時に「Sample80()」が呼び出されます。

 メソッドと似ていますが、「メソッドのように返却値の型を指定しない」という点、「識別子がクラス名と同じ名前だ」というのがポイントです。

 メソッドについて忘れてしまった読者は、連載第7回の「クラスの振る舞いを表すJavaの“メソッド”とは?」を復習しておいてください。

Stringの初期化を4つの方法で

 コンストラクタでは、4つの方法でString型の配列要素を初期化しています。

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

等値演算子(==)とequalメソッドを使って比較

 こうして初期化されたString型の変数について、それぞれの関係が分かるような処理を実行するtestメソッドを用意しました。testメソッドでは、文字数をcodePointCountメソッドで取得し、インスタンスが等しいかを「等値演算子(==)」で判定し、文字列が等しいかを「equals」メソッドで判定しています。

 等値演算子について忘れてしまった読者は、連載第3回の「関係演算子と等値演算子って何?」を参照してください。

文字列を連結する「文字列結合演算子(+)」

 そして、それらの結果を画面出力しています。画面出力に当たっては、文字列を連結するために、「文字列結合演算子(+)」を使っています。この+は算術演算子の加算と同じ記号ですが、文法的な意味は異なります。"0123"という文字列と"abcd"という文字列を連結する("0123"+"abcd")と、"0123abcd"という文字列になります。

 算術演算子について忘れてしまった読者は、連載第2回の「コンピュータに“計算”をさせるための“式”と“演算子”」を参照してください。

どれがtrueになるか分かりますか?

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

 初期化されたStringの配列ssの各要素の値がどうなっているかをよく考えて、実行結果がどうなるか予測してみてください。[1]から[8]のうち、どれがtrueとなるでしょうか?

 等値演算子では何を比較し、equalsメソッドでは何を比較しているかを理解していれば、難しくはないはずです。予測したら実行をしてみましょう。実行結果は、下記のようになります。

 4
 ----
 true
 true
 false
 false
 ----
 true
 true
 true
 true
リスト2の実行結果

 結果を見ると、文字列"0123"の文字数は4だということが分かります。また、ss[0]と同じインスタンスを参照しているss[0]とss[1]は等値演算子(==)による判定とequalsメソッドによる判定のどちらもtrueになることが分かります。

 しかし、new演算子を使って作成したり、StringのvalueOfメソッドを使って作成したりしたインスタンスを参照するss[2]やss[3]の変数については、等値演算子の判定はfalse、equalsメソッドの判定はtrueとなることが分かります。

同じ値の文字列かを判定したい場合はequalsメソッドを使えばよい?

 このことから、同じ参照値かを判定したいときは等値演算子(==)を、同じ値の文字列かを判定したい場合はequalsメソッドを使う必要があるということが分かります。

 このように参照型では、同じかどうかを判定するときに単純に等値演算子が使えないことがあります。この違いを理解して、等値演算子(==)を使うか、equalsメソッドを使うかの判断をするようにしてください。

Stringクラスでメソッドを使いこなす練習をしよう

substringメソッド・startsWithメソッドを使った文字列の比較

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

public class Sample81{
    String s = "0123";
    public void test() {
        // 文字列から部分文字列を取得
        String s0 = s.substring(0, 2);
        String s1 = s.substring(1, 2);
        String s2 = s.substring(2, 3);
 
        // 取得した部分文字列を表示
        System.out.print(s0 + ":");
        System.out.println(s.startsWith(s0));
        System.out.print(s1 + ":");
        System.out.println(s.startsWith(s1));
        System.out.print(s2 + ":");
        System.out.println(s.startsWith(s2));
    }
 
    public static void main(String[] args) {
        Sample81 sample81 = new Sample81();
        sample81.test();
    }
}
リスト3

 substringメソッドは、取得する部分文字列の開始位置と終了位置をパラメータとして受け取ります。文字の位置は0から始まる添え字で指定できます。終了位置は取得する部分文字列の最後の位置に1を加えた値を指定します。

 従って、開始位置0、終了位置2を指定すると、先頭から2文字分の部分文字列"01"が取得できます。開始位置1、終了位置2を指定すると、先頭の次の文字から1文字分の部分文字列"1"が取得できます。

 このプログラムでは、こうしてsubstringメソッドで取得した部分文字列をコンソール画面へ出力するのと同時に、sがこの部分文字列で開始するかをstartsWithメソッドで判定して、その結果も出力するようにしています。

 startsWithメソッドは実行結果を見た方が早いので、このプログラムを実行して確認してみましょう。結果は、下記のようになります。

01:true
1:false
2:false
リスト3の実行結果

 まず、substringメソッドにより、s0は"01"、s1は"1"、s2は"2"という文字列になっているのが分かります。次に、これらの文字列をstartsWithメソッドへパラメータとして渡して得られる値は、s0("01")に対してはtrue、s1("1")対してはfalse、s2("2")に対してはfalseとなっています。

 このことから「s0はsの接頭辞と一致している」「s1とs2はsの接頭辞と一致していない」という判定はstartsWithメソッドを使えばできることが分かるはずです。

 次ページでは、もう少しStringクラスでメソッドの使い方を練習して、最後にメソッドのパラメータが参照型の場合の注意点を説明します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

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

メールマガジン登録

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