こんにちは!ピョコです!
半年ほどエンジニアとしてプロジェクトに参画しておりました。
そんな私がプロジェクト内で受けたよくある質問や私自身が資格勉強(特にJavaSilver)で悩んだところを簡単に分かりやすく説明いたします。
本日のテーマはString型についてです。
String型は意識しないと何となくで進んでしまいますが、これ以外と難しいんですよ。ここをしっかり理解できているか、いないかでかなり変わってくるので、しっかりポイントを押さえて理解しましょう。
この記事を読んでほしい人
■ String型についてあまり理解ができていない人
■ Javaの資格勉強でつまづく人
ではさっそく学んでいきましょう
参照型のString
String型は参照型と呼ばれるデータの型を取ります。よくプリミティブ型と参照型という言葉を聞くと思います。
プリミティブ型というのは簡単に言うと、その変数にデータが入ってるもののことを言います。
例えば下記のようなプリミティブ型の変数があるとします。
int s = 1;
この変数sというものには1というデータが入っています。
しかしながらString型は少し違います。
String型はデータが入るのではなく参照先が入るのです。
もう少し詳しく書きましょう。
例えば下記のようなString型の変数があるとします。
String s = "A";
多くの人が変数sにAという文字が入っていると勘違いをするのですが実はこのsにはAのデータが入ってる場所の情報が入っているのです。
これで見てわかるように変数sにはデータが入ってる場所を示していて、そのデータ先(参照先)のAという値を見ているのです。
プリミティブ型と違い、直接データを見ていない(参照先の値を見ている)ので参照型といいます。
不変なString
Stringクラスは不変なものであるということをご存じでしょうか。
知らないよという方は今、1つ知識が増えましたね!
String型は一度作った値の情報は書き換えることができません。
先ほどの例でいうとデータ番号132に入っているAという文字を書き換えることはできません。
え、でも私書き換えたことあるよ?replaceとかで書き換えたもん。
という方。今からそのからくりを説明します。
String s = "A";
s.replace("A" , "B");
というコードがあるとします。
この場合どのようなことが起こっているかというと
上図のように変数sの参照先の値が変わるのではなく新しいデータBというのが生成されるのです。
少し難しい話になってしまいますがStringクラスはfinalで定義されており、定数(書き換えることができない)として生成されます。そのため中身を書き換えることができず、毎回新しくデータを作り出します。
ではこの変数を下記のコードで表示した場合何が出力されるでしょうか?
String s = "A";
s.replace("A" , "B");
System.out.println(s);
答えはAです。
え、なんで?
少し頭を使うことになるのですが変数sが参照先として見ているところはどこでしょう。そう132番なのです。
133番は新しく生成されましたが変数sが参照している場所は変わっていません。ではどうすればいいのか。
String s = "A";
s = s.replace("A" , "B");
System.out.println(s);
上記のように変数sが参照する場所を133番(s.replaceによって生成された場所)にしなければいけません。
このように参照先を意図的に変えなければならないのがString型です。
きっとこの説明を聞いても分からない方もいるとは思いますが、最初から分かる人はいないので反復して何度も自分で考えてみてください。そうすれば少しずつ理解が深まるはずです。
String型のNullについて
まずは皆さまNullについてはご存じでしょうか?
よく何もない状態、空っぽの状態。空文字ではない。
などなど色々なことが書かれてると思います。
正直これ分かりにくくないですか?
私自身これがよく分からなくてNullが嫌いになりそうでした。
悩んで悩んで悩んで、そして辿り着いた答えがあります。
何もない状態(Null)とは参照先がないことを表す。
詳しく図で説明したいと思います。
今までのことを復習するとString型は参照型で参照先の値を見るといいました。
String s = null;
では上記の場合だとどうなるか
イメージとしてはこうなります。参照先がありませんよね。
よくNullが代入されるとかNullを具現化してしまう人がいるんですが、
これだと配列のところで絶対につまづくのでやめたほうがいいです。
話を戻して参照先がないことを表すのがNullだと考えれば…
そうプリミティブ型でNullが使えない理由もわかりますよね。
プリミティブ型は参照先を見るのではなく値(データ)を保持しています。なのに参照先がないことを表すNullを使えるはずがないんです。
なのでプリミティブ型でNullは代入できないのです。
ここを理解できれば応用も効いてくるのでしっかり覚えましょう!
ちなみに
String s = null;
①System.out.println(s);
②System.out.println(s.indexOf(0));
①では例外が発生しないのに②では例外が発生する理由はわかりますか??
①では参照先がない変数を見ているに過ぎないのでNullが出力されるだけです。
②では参照先がない変数のメソッドを使用しようとしています。参照先がないのにメソッドを使おうとしても参照先がないのでメソッドもないです。何もないのにメソッドなんてあるわけないですもんね。
まとめ
どうだったでしょう?
理解は深められましたでしょうか。正直まだ分からないよという方もいるかもしれません。
安心してください。最初からできる人なんていません。何度も繰り返し学んでいくことで、少しずつ理解が深まってきます。
時間をかければどんどん分かってきます。諦めないで考えて悩んでください!
ただ暗記になってしまうのはやめましょう。
Stringクラスは不変…Stringクラスは不変…Stringクラスは不変…Stringクラスは不変
って覚えても何も意味がありません。それよりは【なぜ】不変なのかを考えて答えを出すことができれば覚えようとしなくても勝手に覚えます。
考える癖もつきます。応用もできます。
大変だと思いますが逃げずに考える癖をつけていってみてください。