javaの値と参照,equals()と==演算子

ちょっとちゃんと整理したくなったのでまとめておきます
以下の内容はjavaにおけるものです。

値オブジェクトと参照オブジェクト

全てのオブジェクトは以下の2種類のいずれかに分類できる

値オブジェクト

別名基本データ型, プリミティブ型

boolean, byte, char,short,int float, long, doubleがこれに属する。
メモリには上記の型のサイズ分の容量が確保され、直接そこに
値(trueや’A’, 12345等)が格納される

参照オブジェクト

基本データ型に属さない型(String含)は全て参照オブジェクト

インスタンスが生成されると、ヒープ領域にそのインスタンスのデータが格納され
インスタンス変数自体はそのメモリアドレスへの参照を保持する。


javaにおける引数に渡されたオブジェクトの扱い

  1. 値オブジェクトが渡されたときは値(trueや’A’, 65543等)をコピーして渡す
  2. 参照オブジェクトが渡されたときは参照値(メモリアドレス)をコピーして渡す

つまりはどちらも値渡し。2が『参照の値渡し』と言われる所以ですね。


Stringはイミュータブル

Stringのインスタンスは一度生成すると、そのインスタンスの情報を直接
変更することはできない。

1でAAAAAが代入され出力、そして2でBBBBBが代入され出力しているが
3ではAAAAAが出力されている。

  1. funcにstrが渡される時にstrの参照がコピー
  2. func内でargStr = “BBBBB”をしているのはAAAAAを受け取ってBBBBBにしたのではなく
    BBBBBのStringインスタンスを作成して参照を変えたため、AAAAAはそのまま
  3. 3の箇所でstrはAAAAAのインスタンスの参照を持っているのでAAAAAが出力される

ちなみにStringインスタンスを+演算子で連結させるときは
内部的にStringBuilder(StringBuffer)が利用されているが

大量のStringインスタンスを連結させたいときは
最初からStringBuilder使ったほうが高速

Stringの連結にはStringBuilderを、というのはこの辺が影響している。

※通常、自分で定義したクラスは、意図して書かれない限りはミュータブル(変更可能)です。
なぜStringクラスが言語レベルでイミュータブルなのか、というのは参考リンクを
見ていただければと思います。


== 演算子とequalsの違い

== は値が等しいか、equalsは(Stringクラスでは)参照している値が等しいかをそれぞれチェックしている
(という理解で間違っていないか不安・・・)

java.lang.Stringクラスのequals()実装が以下

まずは単純に == でチェック。これで正しいならその場でtrueを返す。
以降はインスタンスがString型であることをチェックした上で、その
文字列を1文字ずつchar型として == チェック。
全てtrueならtrueを返す。非常にわかりやすい実装。

==によるStringインスタンスの比較の結果とコードはこんな感じ。

  1. “”で初期化したStringインスタンスは擬似プリミティブ型といって、
    “AAA”という値をもったStringインスタンスを渡してくる。
    (この部分だけを例えるならHashMap的なイメージ?)
    (既にメモリにあればそれを、なければ作成して参照を持たせる)
    (case0,1より)
  2. new String()のように、明示的にコンストラクタを利用すると、
    同じ内容でも別の領域に値を確保してその参照を持たせる
    (case6,7より)
    • 演算子で結合させた結果を取得する場合も2と同じ。
      (”AAA”と”AA”+”A”は値は同じだが、比較ではfalseになる)
      (case2,3,4より)

ということがわかる。(case3の結果はこの辺を知ると納得なんだけど、式だけ見るととても興味深い)

※ちなみに上記コードの比較はequalsでは全てtrueになります。


参考リンク

蛇足

ピアソンのリファクタリングを読んでいるときに、少し混乱があったので
この内容をまとめたい、というのがこの記事を書き始めたそもそもの動機だったんですが、
P175-P185に書かれている『値オブジェクト』と『参照オブジェクト』という
表現は、上記のものとは別、だと思います。

この本のこの箇所における

  • 値オブジェクトとは、イミュータブルで独立している。あるオブジェクトが個々に持っているもの
    複数のユーザが保持していて、メンバーも値が同じでも別のオブジェクトとなっているもの
  • 参照オブジェクトとは、ミュータブルで変更が利用者全体に影響するもの
    複数のユーザが保持していても、それらは同一インスタンスを参照しているもの

を指している、のかも・・・?

もうちょっと理解が進まないとダメかもしれません・・・。
誤解を与えてしまったら申し訳ないです。コメントやメール、Twitterで
ご連絡いただけると喜びます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です