if 文で数値を比べたときは == を使いました。文字列も同じように書けてしまいますが、結果は書き方によって変わります。この回は、その理由と正しい比べ方を扱います。
実行環境は引き続きブラウザ上のもの(paiza.IO や OneCompiler)です。
== で比べると、うまくいってしまう
うまくいく例から見ます。
public class Main {
public static void main(String[] args) {
String a = "Java";
String b = "Java";
if (a == b) {
System.out.println("同じです");
} else {
System.out.println("違います");
}
}
}
同じです
a と b の中身はどちらも Java で、== は成立しました。ここだけ見ると、文字列も == で比べられるように見えます。
中身が同じでも「違います」になる
次のコードは、b の作り方を変え、中身を確かめるために b を表示する行を足したものです。
public class Main {
public static void main(String[] args) {
String a = "Java";
String head = "Ja";
String b = head + "va";
System.out.println(b);
if (a == b) {
System.out.println("同じです");
} else {
System.out.println("違います");
}
}
}
Java
違います
System.out.println(b) は Java と表示しています。中身は Java で間違いありません。それでも == は「違います」と判定しました。
== が比べているもの
String の変数に入っているのは、文字そのものではなく「文字が置いてある場所」です。== は、その場所が同じかどうかを比べます。
- コードに直接書いた
"Java"は、内容が同じなら1つにまとめて使い回されます。1つ目の例でaとbが同じ場所を指していたのはこのためです head + "va"のように実行中に組み立てた文字列は、別の場所に新しく作られます。2つ目の例では場所が違い、==が成立しませんでした
分かれ目は「実行中に組み立てたかどうか」です。"Ja" + "va" のように書いた時点で中身が決まる式は、コードに直接書いたのと同じ扱いになり、== が成立します。2つ目の例が成立しないのは、head という変数を1つはさんで、実行中に組み立てているからです。
図にすると違いが見えます。1つ目の例では、矢印の先が1つです。
flowchart LR
a1["変数 a"] --> box["Java"]
b1["変数 b"] --> box
2つ目の例では、矢印の先が2つに分かれています。
flowchart LR
a2["変数 a"] --> box1["Java"]
b2["変数 b"] --> box2["Java"]
== が見ているのは矢印の先です。中身が同じでも、箱が分かれていれば成立しません。
書き方によって成立したりしなかったりする以上、== は中身を比べる用途には使えません。
equals で中身を比べる
中身を比べるには equals を使います。変更するのは if 文の1行だけです。
public class Main {
public static void main(String[] args) {
String a = "Java";
String head = "Ja";
String b = head + "va";
System.out.println(b);
if (a.equals(b)) {
System.out.println("同じです");
} else {
System.out.println("違います");
}
}
}
Java
同じです
a.equals(b) は「a の中身と b の中身が同じか」を判定します。System.out.println(...) と同じで、. の左にあるものに対して命令する形です。ここでは System.out の代わりに a という文字列の変数が左に来ています。
文字列で「等しくない」を書くとき
文字列の条件を反転させたいときは、!= ではなく ! を条件の前に付けます。
public class Main {
public static void main(String[] args) {
String head = "ba";
String answer = head + "nana";
if (!answer.equals("apple")) {
System.out.println("apple ではありません");
}
}
}
apple ではありません
! は「〜でない」という意味です。answer != "apple" と書いても文法上は通りますが、== と同じ理由で、比べているのは中身ではありません。
数値の == はそのままでよい
int のような数値の型は、変数に値そのものが入っています。場所ではなく値が入っているので、== で中身を比べられます。
public class Main {
public static void main(String[] args) {
int x = 100;
int y = 50 + 50;
if (x == y) {
System.out.println("数値は == で比べられます");
}
}
}
数値は == で比べられます
y は計算して作った値ですが、== は成立します。これまでの if 文を書き直す必要はありません。
比べ方の使い分け
| 比べるもの | 使うもの | 例 |
|---|---|---|
数値(int など) | == / != | age >= 18、count == 0 |
文字列(String)が同じか | equals | name.equals("Aki") |
| 文字列が違うか | ! と equals | !name.equals("Aki") |
コードを読むときの見方
文字列の比較が出てきたら、次の順で確認します。
- 比べているのが数値か文字列か — 変数の型を見る
- 文字列なら
equalsになっているか —==が使われていれば、そこが疑うところ - 試すときは、変数をはさんで組み立てた値で比べる —
"Java"と直接書いた2つや、"Ja" + "va"のように書いた時点で中身が決まる式では==が成立してしまう。この回のhead + "va"の形で試す
3番目は、AI が出したコードを確かめるときにも使えます。1回動いたことが、正しさの証明にならない場面があります。
次の回へ
次は配列です。同じ型の値をまとめて持ち、番号で取り出す形を扱います。for 文と組み合わせると、複数のデータをまとめて処理できるようになります。