[ Top ] > [ Communication ] > [ study ] > [ Java ]
> 文字列を扱う -1-
a
 
 

文字列を扱う-1-

05/01/28
Perl言語やPHP言語などでは、文字列を扱うのが簡単でした。
ところが、C言語、Java言語になるとそうはいきません。
C言語の場合は、配列に壱文字壱文字いれて扱ったりします。
私がC言語を学んだときは、ポインタを使ってました。つまり、文字数分のメモリ空間を確保して、そこにいれる。みたいな。
Java言語になって、char型の変数には、日本語のような2バイト文字も1文字いれられるようになりました。
では文字列はというと、 String型のオブジェとして扱われるようです。
とは言っても、Perl言語に比べて扱いにくいのはかわりありません。(x_x)

Java言語は、ポインタの概念がない なんていわれているようですが、C言語を学んだ(と、いっても1〜2ヶ月ほどなので、自信を持っては言えませんが)私が思うに、ポインタらしき概念はある。と、思うのですが・・・。たとえば、このページで扱う文字列です。

C言語ではポインタ変数なんていうのが出てきますが、えっと、C言語をやったことない人に説明すると、変数を宣言するということは、その変数用にメモリ空間を確保してやるって事です。だから、C言語で byte型の変数を宣言した場合は、1バイト(でしたっけ?汗)OSが用意してくれます。
文字列を扱う場合は、え〜っと、その文字列がメモリ空間に確保されそのアドレスをポインタ変数にいれて扱ったりします。なんかJavaの場合もそんな感じに見えるのですが・・・。
この辺は後に置いておいて、簡単な文字列の扱いをプログラムで見てみましょう。

> strTest.java
class strTest{


	public static void main(String args[]){


		String str = new String();
		String str2 = "2222";
		str = "1111";
		
		System.out.println("str :" + str);
		System.out.println("str2:" + str2);
	}
}

実行結果

>java strTest
str:1111
str2:2222
>

こんな感じです。String型の変数にいれているっていう感じに見えますね。では、以下のプログラムを見てみましょう。

> strTest2.java

class strTest2{
public static void main(String args[]){
String str = new String();
String str2 = "1111";
String str3 = "11";
str = "1111";
if(str == str2){
System.out.println("同じです");
}
str2 = str3 + str3;
if(str == str2){
System.out.println("こちらも同じです");
}else{
System.out.println("違います。");
System.out.println("str :" + str);
System.out.println("str2:" + str2);
}
}
}

実行結果は、

>java strTest2
同じです
違います
str :1111
str2:1111

と、なります。どちらも同じ「1111」なのに、同じではないという結果になってしまいました。
これがJavaもポイントらしき概念がある。といったゆえんです。
つまり、str も str2 も、それぞれメモリ空間のアドレスを格納しており、str2 には、str3 + str3 を実行し、新しいメモリ空間に実行結果(ここでは 1111) が作成され、そのアドレスがホントは str2 に入っている。のではないのかなぁ。と。
だから、str にはほんとうは、「4FF4F000」のようなメモリアドレスが、str2 にも「4FF50000」のようなアドレスが格納されていて、どちらもこのアドレスが違う値なので「 == 」は成り立たない。と。

ただ、この辺はJavaにおいてはそんなもんなんだ(つまり、「 == 」で比べられない)。程度に覚えておけばよいと思います。C言語では、今のアドレスを元にいろいろ出来ましたがJavaでは出来ません(たぶん)。

では、同じ文字列かどうかを比べるときはどうするかっていうと、Stringクラスのメソッドでもある equals を使います。⇒参照
equals は、引数としてオブジェクトを渡してやると(たいていは、というよりほとんどStringクラスのオブジェでしょうが)、同じ文字列であれば true を返します。
よって、先ほどのプログラムを修正するとすると、

 if(str.equals(str2)){ //str == str2 だった部分
System.out.println("こちらも同じです");
}else{
System.out.println("違います。");
System.out.println("str :" + str);
System.out.println("str2:" + str2);
}

これで期待した結果が出ます。
ここで一つ疑問が出てきました。なぜ、最初のテストの時は、同じという結果になったのでしょうか。

String str = "1111";
String str2 = "1111";

この二つを「 == 」で比べると成り立ちました。 これは、同じリテラル(プログラム中に出てくる値や文字列)だと、同じものを参照(Javaではポインタといわないかわりに参照というようです)するからです。
str2 = str3 + str3;
これは、 str3 を2つくっつけて新しい Stringクラスのオブジェとして作成し、それを str2 に入れているので、全く違うアドレスになってしまうのだと思います。