

valの値が空かどうか判別したいのですが  
以下の二つのif文の違いがよくわかりません。  
どちらも同じ意味なのでしょうか。  
参照型である文字列は「!=」や「==」を使わない方が良いのでしょうか。

【コード1】

[code]

    String val = "";
    if (val != "") {
    
    }
    
[/code]

【コード2】

[code]

    String val = "";
    if (val.isEmpty()) {
    
    }
    
[/code]


CC BY-SA 4.0
2018-05-14T05:00:32.483
43969
2018-05-14T18:07:06.767
2018-05-14T05:03:57.083
3068
25778
question
java
javaで空文字かどうか判定する方法


> どちらも同じ意味なのでしょうか。

質問に書かれているコード例は、たまたまプログラマーの意図した通りに動きますが、厳密には異なります。

[code]

    public class Main {
    
        static String empty1 = "";
        static String empty2 = "";
        static String empty3 = new String("");
    
        static String abc1 = "abc";
        static String abc2 = "abc";
    
        public static void main(String[] args) {
    
            // equals はオブジェクト同士が同じ値か(値が等しいか)を判別する
            System.out.println("s1 eq s2 : " + empty1.equals(empty2));
            System.out.println("s1 eq s3 : " + empty1.equals(empty3));
    
            // == は同じオブジェクト(インスタンス)かどうかを判別する
            System.out.println("s1 == s1 : " + (empty1 == empty1));
            System.out.println("s1 == s2 : " + (empty1 == empty2));
            System.out.println("s1 == s3 : " + (empty1 == empty3));
    
            System.out.println("abc1 == abc2 : " + (abc1 == abc2));
        }
    }
    
[/code]

[code]

    s1 eq s2 : true
    s1 eq s3 : true
    s1 == s1 : true
    s1 == s2 : true
    s1 == s3 : false
    abc1 == abc2 : true
    
[/code]

`==`は比較対象同士がまったく同じオブジェクトかどうか(同じインスタンスかどうか、同じ参照かどうか)を判別するために使います。

そのため、上記のサンプルコードとその結果のように`""`と`new String("")`は一致せず、`false`が返ります。  
(`new String()`は新しいインスタンスを生成します)

では、empty1とempty2が`==`で等しくなり、同じインスタンスを指していると判別されている理由ですが、JVM(Java仮想マシーン)にはRun-
Time Constant
Poolという仕組みがあり、文字リテラルはすべてこのプール内で管理され、同じ値をもつ文字リテラルは1つのインスタンスだけ持つようにまとめられているからです。

つまり、ソースコード上に何個`""`(空文字列)を書いても、すべて1つの同じインスタンスを参照しています。

<https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html>

> The Java programming language requires that identical string literals (that
> is, literals that contain the same sequence of code points) must refer to
> the same instance of class String (JLS §3.10.5).

<https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5>

> ### 3.10.5. String Literals
>
> Moreover, a string literal always refers to the same instance of class
> String. This is because string literals - or, more generally, strings that
> are the values of constant expressions (§15.28) - are "interned" so as to
> share unique instances, using the method String.intern.

* * *

> 参照型である文字列は「!=」や「==」を使わない方が良いのでしょうか。

文字列の場合、前記の理由もあり、`isEmpty()`を使用したほうが良いです。  
(文字列同士の値の比較は`equals()`を使用する)

文字列やコレクションが空かどうかを判別する場合、 **基本的に`isEmpty()`の使用が推奨されます。**  
(文字列はchar型のコレクションと見ることもできます)

理由の1つとして、コレクションの内部構造毎にコレクションが空かどうかを判別する具体的かつ最適な方法が異なるためで、各コレクション毎にその最適な方法が`isEmpty()`というメソッドによって隠蔽されているからです。

まれにコレクションのsizeが0かどうかで、コレクションが空かどうかを判別しているコードを見かけますが、コレクションの内部構造によってはsizeを取得する処理に時間がかかる物もありますので、推奨されません。

**String#isEmpty()**

[code]

    /**
     * Returns {@code true} if, and only if, {@link #length()} is {@code 0}.
     *
     * @return {@code true} if {@link #length()} is {@code 0}, otherwise
     * {@code false}
     *
     * @since 1.6
     */
    public boolean isEmpty() {
        return value.length == 0;
    }
    
[/code]

**ArrayDeque#isEmpty()**

[code]

    /**
     * Returns {@code true} if this deque contains no elements.
     *
     * @return {@code true} if this deque contains no elements
     */
    public boolean isEmpty() {
        return head == tail;
    }
    
[/code]


CC BY-SA 4.0
2018-05-14T17:38:33.667
43986
2018-05-14T18:07:06.767
2018-05-14T18:07:06.767
3068
3068
43969
answer