0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Java】 String型の正しい比較

Last updated at Posted at 2020-05-05

#String型比較を深堀してみる
String型の値の比較について、整理しました。

##等比較の方法
###1. ==
 ・プリミティブ型では値の比較を行う。
 ・オブジェクト型ではオブジェクトの参照値を比較し、オブジェクトが同一か判断する。

###2. equals()
 オブジェクト型でのみ使用可能で、オブジェクトの内容比較を行い、オブジェクトが同値か判断する。
 ※Objectクラスにequalsが定義されている。
  Stringクラスではoverrideしている。

つまり、Strng型は参照型のオブジェクトだから、equalsを使えばOKですね。

##検証(==だと本当に比較できないのか)

StringSample.java
    String str1 = "A";
    String str2 = "A";
    String str3 = new String("A");
    System.out.println(str1.hashCode());
    System.out.println(str2.hashCode());
    if(str1 == str2) {
        System.out.println("TRUE");
    }else {
        System.out.println("FALSE");
    }
    if(str1 == str3) {
        System.out.println("TRUE");
    }else {
        System.out.println("FALSE");
    }

##結果

100
100
TRUE

TRUEになった。String型は==でも比較していいのか。

#調査
String型は初期化された際にヒープ領域に値が作られるが、同じ値を使用する場合は使いまわすらしい。

※newされた場合は新しく領域が作られる。

#図解してみた
String比較.png

メモリ節約のため、newせずに値"A"が一致する領域(アドレス=100)を使いまわす。
※参照値:参照先のメモリアドレス

##Stringの値を変更した場合の動作
String比較2.png

変数の値を書き換えると参照元の値(アドレス=100)が変更されるのではなく、"B"の新しい領域をnewして参照先を変更するんですね。(参照先アドレスを100→200に変更)
※Stringはイミュータブルのため、参照先の値を変更できない。

#Stringオブジェクトのequalsはなにをやっているか

String.class
    private final char value[];

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;                //自オブジェクトのvalue
                char v2[] = anotherString.value;  //比較先オブジェクトのvalue
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])           //Stirngをcharに分解して値比較
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

Stringオブジェクトをchar[]に分解して1つずつ値を比較している。

#結論
Stringオブジェクトはメモリ節約のために同じ値の場合は異なるローカル変数でも参照値(参照先アドレス)が同一になる可能性があるが、保証はされていないので、equalsで比較するべし。

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?