• PE-BANKと契約して26歳で年収800万になった大阪のフリーランスですが全てを語ります




連載4日目最終日です。1~3日目がまだの人は1日目から読むことをオススメします。


全体はこんな感じ。


参照周りで押さえておきたい内容について4回に渡って解説していきます。

1~3日目の話で値(プリミティブ)型と参照(オブジェクト)型の違いメモリの使い方など解説してきたので、

ここまで読んだ人はかなりイメージが沸いているのではないでしょうか。

しかしこれまで話した内容を頭に入れつつ1つ気を付けないければならないのが



String型変数の特殊性



です。


最後にString変数の特殊性を押さえて4日間の集中講座を終わりとしましょう。

それでは最終日いきましょう~(/・ω・)/

イミュータブルな変数とは?

イミュータブルとはJavaのみでなく、全てのプログラムを組む上で大事な考え方です。

意味は「不変性」という意味で、対極の言葉としてミュータブル(変性)という言葉もあります。

1度定義したオブジェクトなどを変えないという思想ですね。


考える人考える人

定数みたいなもんか?

じゃけぇじゃけぇ

ん~まぁイメージはそんな感じかな!

定数の場合は明示的に final などを付けたりしますが、Javaでは仕様としてイミュータブル(不変)となっているが存在します。


その代表がString型です。

解説していきましょう。

String型はイミュータブル(不変)である!

考える人考える人

ちょっと待てい!Stringは変えれるじゃろ!わしのコードを見てみい!


考える人考える人

ほれ!str1の中身変わっとるじゃないか(ドヤ顔)

じゃけぇじゃけぇ

確かに一見str1の値が書き換えられているように見えるね。それはJavaが使い易いように中で上手くやってくれているからなんだよね。

考える人考える人

どういうことじゃ??

じゃけぇじゃけぇ

実際に何が起きているか図で確認してみよう。

まずStringは参照(オブジェクト)型なので、1~3日目で解説してきたように
・スタック領域に参照値
・ヒープ領域に実際の値


が格納されます。
(newしないで使えるのはJavaが使いやすいようにしてくれているから)





ここからが大切で、str1に別の値を代入したときに内部的に何が起こっているかというと、こんなことが起きています。





str1に”い”という文字列を代入しようとした時、Stringがイミュータブル(不変)なので、


新たな参照値が確保され別の領域に”い”という値が保持される


のです。



えーー?ほんとに??


と思った方は以下のコードで確認することができます。
(3日目の内容は頭に入れておいてください)



もしstr1に”い”を代入した時点で値を上書きするだけなら、参照値の比較は一緒ですとなるはずです。

ですが”い”を代入した時点で新たな参照が作成されているため、str1とstr2の参照値は異なるということが分かります。

これがString型がイミュ―タブル(不変)であるということです。

String型は再利用される!

もう1つ覚えておかないといけないのはString型は再利用されるということです。

変数に値を代入する時、もしその値が既に存在すればその参照が使われる

ということになります。


考える人考える人

???さっぱりじゃ

じゃけぇじゃけぇ

これも図で説明しよう




String型の変数にある値を代入しようとした時、Javaではヒープ領域にその値が既にあるかどうかをチェックします。
・既に存在する場合
 ⇒その参照を割り当てる
・存在しない場合
 ⇒新たな参照を割り当てる


という動きになります。

String型においてメモリを効率良く使いまわすためにこうなっています。

これもコードで確認することができます。



「==で一緒です。」と出力され、異なる変数名で同じ参照値を持っていることが分かります。

因みにStringはnewを省略できますが、newを記述することもできます。(まぁ使うことはありませんが…)

その場合は「必ず新しい参照を作成する」という意思表示になります。以下のコードを見てみましょう。


明示的にnewした場合は、参照が再利用されていないことが分かりますね。


考える人考える人

ややこしいのぉ~

こういったイミュータブルや再利用の特性があるため、



String型の比較はequalsで!



とルール化されているわけです。意図しない比較になる可能性があるためです。

String型を扱うときに注意すること

以上2点の特殊性を頭に入れておくことで、String型を扱う時に注意するべきポイントが見えてきます。

それは


String型の変数を大量に書き換えるような処理の場合メモリが圧迫される



ということです。

上記で説明したように、Stringに他の文字列を代入するときはその値を書き換えるのではなくて、新しい参照を作成します。

そのため何万件、何十万件とループしながら処理する中でStringを書き換えるような場合、何も考えずにやっているとメモリがいっぱいになって落ちる。なんてことが起きてしまうかもしれません。

String型のメモリの使い方を知らない人は何が起きているのかさっぱり分からないでしょう。

そういった時は、明示的にGC(ガベージコレクション)を行うなど、適切にプログラムを組む必要があります。
(ガベージコレクションではヒープ領域の中で、参照が既に存在しない値があればメモリを解放してくれます)

ガベージコレクションについては色々深いので、興味ある人は調べてみてください。

機会があればこのブログでも取り上げたいと思います。

さいごに(4日間集中講義のまとめ)

さて、4日間の集中講義ということでJavaの参照周りで押さえておきたい知識について図とコードを多めに解説してきました。


1~4日まで全部読んでないよって人は是非1日目から読んでみて下さい^^



ここで解説してきたことを理解してプログラムを組むか、知らずに組むのかではエンジニアとして非常に大きな差が出てきます。

1つの言語でメモリの使い方を習得しておけば、他の言語でも雰囲気で掴めるようになりますし、言語ごとの良さや特徴も掴みやすいと思います。

じゃけぇじゃけぇ

まぁJavaではまずこれまで解説してきた「左にスタック領域、右にヒープ領域」の図を覚えておくと良いね

考える人考える人

儂も今ならスマートなコードが書ける気がするわ!

以上となります。少しでもJavaを勉強中の方々の手助けになれば幸いです。

もしツッコミあれば訂正しますのでコメントください。

また、イイねやコメント、SNSへの拡散等大歓迎ですので宜しくお願いしますm(__)m


それでは!また!!

最後まで読んで頂きありがとうございます!
これ以外にも興味ある記事がきっとあると思うので厳選記事をご査収あれ('◇')ゞ
厳選!目的別にオススメ記事を紹介-あなたの欲しい情報がここに-


新着記事の投稿通知を受け取りたい方は↓からお願いします。
今後メルマガ登録者に様々な情報共有をしていくことも考えています^^