3. 比較演算
Javaでは2つの値を比較して値が等しいかどうか、もしくは値が大きいか小さいかなどを比較することがよくあります。また、Javaでの比較結果は次の2種類のものがあります。
- 結果をboolean値で返すもの
- 結果をint値で返すもの
結果がboolean値の場合は値が等しければ「true」、違うなら「false」を返します。そして、結果がint値の場合は比較した値が等しければ「0」、対象の値が比較したものの値より大きければ0より大きいプラスの値、小さければマイナスの値を返します。
それでは結果がどのようなものになるのか分かったところで、さまざまな論理演算を見ていきましょう。
3.1. 主な比較演算子の種類
Javaで使われる主な比較演算子は次のものになります。これらは主に基本データ型での比較に使われます。
| 比較演算子 | 意味 | 概要 |
| == | 等しい | 例えば1 == 1の場合、結果はtrueになります。 |
| != | 等しくない | 例えば1 != 0の場合、結果はtrueになります。 |
| > | 左が右より大きい |
例えば1 > 0の場合、結果はtrueになります。 また右と左の値が同じ場合、例えば1 > 1の場合、結果はfalseになります。 |
| >= | 左が右以下 |
例えば1 >= 0の場合、結果はtrueになります。 また右と左の値が等しい場合も同様に、例えば1 >= 1の場合も結果はtrueになります。 |
| < | 左が右より小さい |
例えば1 < 2の場合、結果はtrueになります。 また右と左の値が等しい場合、例えば1 < 1の場合、結果はfalseになります。 |
| <= | 左が右以下 |
例えば1 <= 2の場合、結果はtrueになります。 また右と左の値が等しい場合も同様に、例えば1 <= 1の場合も結果はfalseになります。 |
それでこれらを使ったサンプルを見てみましょう。
package jp.codezine.java.sample03;
/**
* 比較演算のサンプルを実行し、その内容を確認するクラス。
*/
public class RelationalOperator1 {
/**
* 比較演算を実行し、その内容を確認します。
*
* @param args
* プログラムの引数。今回は使われません。
*/
public static void main(String[] args) {
// [1] 「==」 等しい
int value1 = 1;
int value2 = 0;
boolean result = value1 == value2;
System.out.println("[1] 1 == 0 → result = " + result);
value1 = 1;
value2 = 1;
result = value1 == value2;
System.out.println("[1] 1 == 1 → result = " + result);
// [2] 「!=」 等しくない
value1 = 1;
value2 = 0;
result = value1 != value2;
System.out.println("[2] 1 != 0 → result = " + result);
value1 = 1;
value2 = 1;
result = value1 != value2;
System.out.println("[2] 1 != 1 → result = " + result);
// [3] 「>」右は左より大きい
value1 = 1;
value2 = 0;
result = value1 > value2;
System.out.println("[3] 1 > 0 → result = " + result);
value1 = 1;
value2 = 1;
result = value1 > value2;
System.out.println("[3] 1 > 1 → result = " + result);
// [4] 「>=」右は左以上
value1 = 1;
value2 = 0;
result = value1 >= value2;
System.out.println("[4] 1 >= 0 → result = " + result);
value1 = 1;
value2 = 1;
result = value1 >= value2;
System.out.println("[4] 1 >= 1 → result = " + result);
value1 = 1;
value2 = 2;
result = value1 >= value2;
System.out.println("[4] 1 >= 2 → result = " + result);
// [5] 「<」右は左より小さい
value1 = 1;
value2 = 2;
result = value1 < value2;
System.out.println("[5] 1 < 2 → result = " + result);
value1 = 2;
value2 = 2;
result = value1 < value2;
System.out.println("[5] 2 < 2 → result = " + result);
// [6] 右は左以下
value1 = 1;
value2 = 2;
result = value1 <= value2;
System.out.println("[6] 1 <= 2 → result = " + result);
value1 = 2;
value2 = 2;
result = value1 <= value2;
System.out.println("[6] 2 <= 2 → result = " + result);
value1 = 3;
value2 = 2;
result = value1 <= value2;
System.out.println("[6] 3 <= 2 → result = " + result);
}
}
[1] 1 == 0 → result = false [1] 1 == 1 → result = true [2] 1 != 0 → result = true [2] 1 != 1 → result = false [3] 1 > 0 → result = true [3] 1 > 1 → result = false [4] 1 >= 0 → result = true [4] 1 >= 1 → result = true [4] 1 >= 2 → result = false [5] 1 < 2 → result = true [5] 2 < 2 → result = false [6] 1 <= 2 → result = true [6] 2 <= 2 → result = true [6] 3 <= 2 → result = false
Javaでは、これらの演算子を使って右の値と左の値を比較できます。しかし、比較対象が基本データ型ではなく参照型の場合に比較演算子を使って比較すると、インスタンスの値の比較ではなく、データが持つ参照先アドレスを比較することになるため、意図した値の比較にならないことに注意してください。参照型の値を比較する場合は、次のequalsメソッドやcompareToメソッドを使います。
3.2. 参照型の比較
Javaで参照型のデータの比較をする際に比較演算子を使うと参照先アドレスの比較になってしまい、インスタンスの値の比較にはなりません。

この図に出ているメモリ領域について簡単に説明すると、Javaでは設定した値をメモリ領域に確保します。また、設定したデータはメモリ領域にあるスタック領域に設定されます。この際に基本データ型は設定するサイズが決まっているため、スタック領域に値とともに設定されます。しかし、クラスなどの参照型データの場合、インスタンス化されるまでどの程度メモリの領域が使われるのかが分かりません。そのため、参照型データの場合は参照先アドレスを設定できるサイズを確保しておき、インスタンス化された際にその値をメモリ領域のヒープ領域というところに格納します。その際に、スタック領域にある参照型データの値はどのヒープ領域を見ればいいのか分かるように、そのインスタンスの参照先アドレスが格納されます。そのため、参照型データの値を比較しても参照先アドレスを比較することになり、インスタンスの値自体の比較はできていないことになります。
しかし、Javaでは参照型データのインスタンスの値を比較するために、次のequalsメソッドとcompareToメソッドを用意しています。
| メソッド | 戻り値 | 概要 |
| equals | boolean | 引数で受け取ったインスタンスの値と等しい場合はtrueを返します。すべてのクラスにあるメソッドです。 |
| compareTo | int |
引数で受け取ったインスタンスの値が等しい場合は0、引数の値より大きい場合は0より大きい数値、引数の値より小さい場合はマイナスの値を返します。 このメソッドはjava.lang.Comparableインターフェイスを実装しているクラスのみにあるメソッドです。 |
それでは次のサンプルを実行してみましょう。
RelationalOperator2.java
package jp.codezine.java.sample03;
/**
* 比較演算のサンプルを実行し、その内容を確認するクラス。
*/
public class RelationalOperator2 {
/**
* 比較演算を実行し、その内容を確認します。
*
* @param args
* プログラムの引数。今回は使われません。
*/
public static void main(String[] args) {
// [1] 参照型データを演算子で比較した場合
boolean result = new Integer("1") == new Integer("1");
System.out.println("[1] new Integer(\"1\") == new Integer(\"1\") → result = " + result);
// [2] 参照型データをequalsメソッドで比較した場合
result = new Integer("1").equals(new Integer("1"));
System.out.println("[2] new Integer(\"1\").equals(new Integer(\"1\")) → result = " + result);
// [3] 参照型データをcompareToメソッドで比較した場合
int resultValue = new Integer("1").compareTo(new Integer("1"));
System.out.println("[3] new Integer(\"1\").compareTo(new Integer(\"1\")) → resultValue = " + resultValue);
resultValue = new Integer("1").compareTo(new Integer("2"));
System.out.println("[3] new Integer(\"1\").compareTo(new Integer(\"2\")) → resultValue = " + resultValue);
resultValue = new Integer("2").compareTo(new Integer("1"));
System.out.println("[3] new Integer(\"2\").compareTo(new Integer(\"1\")) → resultValue = " + resultValue);
}
}
[1] new Integer("1") == new Integer("1") → result = false
[2] new Integer("1").equals(new Integer("1")) → result = true
[3] new Integer("1").compareTo(new Integer("1")) → resultValue = 0
[3] new Integer("1").compareTo(new Integer("2")) → resultValue = -1
[3] new Integer("2").compareTo(new Integer("1")) → resultValue = 1
3.3. String(文字列)の比較
ただし文字列の場合は特殊で、「"」で囲った文字列同士の比較を「==」演算子をつかって比較した場合、結果がtrueになります。これはJavaでは「"」で囲った文字列を内部で管理していて、「"」で囲った文字列が定義された際は、同じ文字列が持つ参照先アドレスを指すように内部で設定されているためです。しかし、Stringのコンストラクタから作成された場合、内部で管理している文字列とは別の、新たに作成したインスタンスとなるため、参照先のアドレスが異なり、「==」演算子をつかって比較すると結果はfalseとなります。そのため、文字列オブジェクトの比較でも「==」の演算子を使うことは避け、equalsメソッドを使って比較するようにしましょう。
package jp.codezine.java.sample03;
/**
* 比較演算のサンプルを実行し、その内容を確認するクラス。
*/
public class RelationalOperator3 {
/**
* 比較演算を実行し、その内容を確認します。
*
* @param args
* プログラムの引数。今回は使われません。
*/
public static void main(String[] args) {
// [1] 文字列を「==」演算子で比較した場合
boolean result = "あいうえお" == "あいうえお";
System.out.println("[1] \"あいうえお\" == \"あいうえお\" → result = " + result);
// [2] Stringのコンストラクタから生成されたインスタンスを「==」演算子で比較した場合
result = new String("あいうえお") == new String("あいうえお");
System.out.println("[2] new String(\"あいうえお\") == new String(\"あいうえお\") → result = " + result);
}
}
[1] "あいうえお" == "あいうえお" → result = true
[2] new String("あいうえお") == new String("あいうえお") → result = false
3.4. 型の比較(instanceof演算子)
Javaでは対象のデータが指定したインスタンスかどうかを確認する「instanceof」演算子が用意されています。これは対象のデータが指定したクラスもしくはそのクラスを継承したクラスの場合や、指定したインターフェイスを実装していた場合にtrueを結果として返します。クラスの継承やインターフェイスについては次回以降の連載で説明しますが、ここでは同じクラスのインスタンスならtrueを返す演算子だと覚えてください。それでは次のサンプルを実行してみましょう。
package jp.codezine.java.sample03;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 比較演算のサンプルを実行し、その内容を確認するクラス。
*/
public class RelationalOperator4 {
/**
* 比較演算を実行し、その内容を確認します。
*
* @param args
* プログラムの引数。今回は使われません。
*/
public static void main(String[] args) {
// [1] 型の比較
String value = "あいうえお";
boolean result = value instanceof String;
System.out.println("[1] \"あいうえお\" instanceof String → result = " + result);
// [2] 継承元クラスとの型の比較
result = value instanceof Object;
System.out.println("[2] \"あいうえお\" instanceof Object → result = " + result);
// [3] インターフェイスとの型の比較
result = value instanceof Serializable;
System.out.println("[3] \"あいうえお\" instanceof Serializable → result = " + result);
// [4] 一致しない型との比較
Object object = "あいうえお";
result = object instanceof BigDecimal;
System.out.println("[4] \"あいうえお\" instanceof BigDecimal → result = " + result);
}
}
[1] "あいうえお" instanceof String → result = true [2] "あいうえお" instanceof Object → result = true [3] "あいうえお" instanceof Serializable → result = true [4] "あいうえお" instanceof BigDecimal → result = false
