【Java入門】第10回 Javaの演算子|さまざまな演算子と演算の内容
2024.06.14
プログラムでは四則演算だけでなく、分岐の判定などの様々な判断や、値の編集を行います。
ここではJava言語に定義されている演算子について説明します。
演算子とは
演算子とは?
四則演算や値の一致や大小の比較など、変数やリテラルに対して行う処理(演算)を示す記号のことを演算子と呼びます。
Java を含めたプログラム言語では、四則演算の記号(+、-、*、/)など、演算子によって実行される処理が決まっています。
演算子とオペランド
オペランドとは、演算子によって演算が行われる対象である変数やリテラルのことを指します。
以下の例では、int型の変数 x に10の値を設定しています。
このとき「=」は演算子(代入演算子)、その両辺の「x」「10」がオペランドになります。
int x = 10;
代入演算子「=」は、左側のオペランド「x」に右側のオペランドの値「10」を設定する演算子で、この演算子で値や参照を設定することを「代入する」と呼びます。
また、次の例では変数 x に対して、100 + 200 の計算結果を代入しています。
x = 100 + 200;
ここでは「100 + 200」という処理を、「100」「200」というオペランドと、「+」という演算子で構成して、加算の処理(演算処理)を実行しています。
このように、演算子とオペランドで構成された演算処理を実行することを「評価する」と表現します。
Javaの演算子
四則演算・単項演算子
四則演算
基本的な四則演算を行うための演算子です。
四則演算を行う演算子の両側のオペランドは、数値またはそのラッパークラスのインスタンスである必要があります。
演算子 | 概要 | 処理の内容 |
+ | 加算 | 演算子の左右のオペランドを加算した値(和)を返却する。 |
- | 減算 | 演算子の左のオペランドから右のオペランドを減算した値(差)を返却する。 |
* | 乗算 | 演算子の左右のオペランドを乗算した値(積)を返却する。 |
/ | 除算 | 演算子の左のオペランドを右のオペランドで割った値(商)を返却する。 ・記号の右側のオペランドが0の場合はエラー |
% | 剰余 | 演算子の左のオペランドを右のオペランドで割った際の、余りの値を返却する。 ・割り切れる場合は0となる |
乗算の演算子は「×」ではなく「*」、除算の演算子は「÷」ではなく「/」で記述します。
除算の結果は余りの部分は切り捨てられ、商が返ります。
除算の余りを取得したい場合は、剰余の演算子「%」を利用して取得します。
System.out.println(10 + 3); // 13 が出力される
System.out.println(10 - 3); // 7 が出力される
System.out.println(10 * 3); // 30 が出力される
System.out.println(10 / 3); // 3 が出力される
System.out.println(10 % 3); // 1(10 ÷ 3 = 3 余り 1)が出力される
加算の演算子「+」は、例外的に文字列(Stringインスタンス)の連結にも利用できます。
また、文字列の連結のために利用する場合は「文字列とプリミティブ型」でも動作が可能ですが、この場合は「式の結果が文字列になる」ことに注意してください。
System.out.println("百" + "円"); // 文字列「百円」が出力される
System.out.println(100 + "円"); // 文字列「100円」が出力される
System.out.println("222" + 111); // 文字列「222111」が出力される
char型は文字列ではなくプリミティブ型なので、「+」演算子では文字の連結が連結できない(数値で加算が実行される)ことに注意してください。
例えば、下記のコードでは「AB」ではなく「131」が出力されます。
これは「'A' + 'B'」の式の結果が、char型の'A'のコードポイント(0x0041 = 65)と、'B'のコードポイント(0x0042 = 66)が加算された結果の値(131)となるためです。
System.out.println('A' + 'B'); // 131 が出力される(65 + 66 = 131)
単項演算子
単項演算子は、1つの数値型の変数に対して値を1加算または減算を行う演算子です。
演算子 | 概要 | 処理の内容 |
++ | インクリメント | 値を1加算する。 ・変数の前に書いた場合(前置)は、変数を使用する前に加算する。 ・変数の後ろに書いた場合(後置)は、変数を使用した後に加算する。 |
-- | デクリメント | 値を1減算する。 ・変数の前に書いた場合は、変数を使用する前に減算する。 ・変数の後ろに書いた場合は、変数を使用した後に減算する。 |
インクリメント、デクリメントは、数値型(またはそのラッパークラス)の変数の値に、1加算または減算を行います。
これらの記号は、変数の前、後ろどちらにも記述できますが、前に記述した場合と後ろに記述した場合で、以下のように少し動作が異なります。
・変数の前に記述した場合は、変数を評価(値を利用)する前に、加算/減算を行う。
・変数の後ろに記述した場合は、変数を評価(値を利用)した後に、加算/減算を行う。
・記述した行の次行以降は、どちらの場合でも加算/減算された後の値となる。
それぞれのパターンで単項演算子を記述した場合の動作を以下に示します。
・前置インクリメント(++変数)
int i1 = 100; // ↓ 出力結果
System.out.println(++i1); // 101 (i1に1加算してから、加算後の値(101)を出力)
System.out.println(i1); // 101 (次行以降は加算後の値(101)を出力)
・後置インクリメント(変数++)
int i2 = 100; // ↓ 出力結果
System.out.println(i2++); // 100 (現在の値(100)を出力した後に、i2に1加算する)
System.out.println(i2); // 101 (次行以降は加算後の値(101)が出力される)
・前置デクリメント(--変数)
int i3 = 100; // ↓ 出力結果
System.out.println(--i3); // 99 (i3から1減算した後に、減算後の値(99)を出力)
System.out.println(i3); // 99 (次行以降は減算後の値(99)を出力)
・後置デクリメント(変数--)
int i4 = 100; // ↓ 出力結果
System.out.println(i4--); // 100 (現在の値(100)を出力した後に、i4から1減算する)
System.out.println(i4); // 99 (次行以降は減算後の値(99)を出力)
代入演算子と算術代入演算子
代入演算子は、左辺の変数に値を代入(設定)する演算子です。
そのまま値を代入する演算子(=)と、左辺と右辺の値を計算した後の結果を代入する算術代入演算子があります。
代入演算子
演算子 | 概要 | 処理の内容 |
= | 代入 | 演算子の左側のオペランド(変数)に右側のオペランドを代入する。 ・代入するものとしては、値、他の変数(の値)、式(の結果)などを記述することができる。 ・参照型の変数にインスタンスへの参照を代入することができる。 |
代入演算子の左側に指定するオペランドは、変数である必要があります。「123 = x」 のように、左側に値を記述することはできません。
演算子の右辺には、値、式、変数を記述することができます。
int a, b, c;
a = 123; // 変数aに123を設定
b = 100 + 200; // 変数bに式の結果(100+200=300)を設定
c = a; // 変数cに変数aの値(123)を設定
左辺が参照型の変数の場合は、右辺も参照型である必要があります。
(プリミティブ型のラッパークラスを除く)
また左辺の型は、右辺の値、式の結果、変数と互換可能な型である必要があります。
String s1 = "111"; // s1に"111"の文字列を代入
String s2 = s1; // s2にはs1が持つインスタンス参照を代入
int i = 100;
long l = i; // longの方がintより範囲が大きいので、longにはintの値を設定できる
/* 以下はコンパイルエラーになる */
i = l; // intはlongより範囲が小さいので、格納できない(可能性がある)ためエラー
i = s1; // s1は数字の「文字列」なので、数値型のiには代入できない
s1 = i; // 文字列の参照型にintの値をそのまま設定することはできない
算術代入演算子(四則演算)
算術代入演算子は、指定した演算を行うと同時に、結果の値を代入します。
(ビット演算の結果を代入するものについては、ビット演算子の欄で説明します)
演算子 | 概要 | 処理の内容 |
+= | 加算代入 | 演算子の左側のオペランドに、左側のオペランドの値と右側のオペランドの値を加算した値(和)を代入する。 |
-= | 減算代入 | 演算子の左側のオペランドに、左側のオペランドの値から右側のオペランドの値を減算した値(差)を代入する。 |
*= | 乗算代入 | 演算子の左側のオペランドに、左側のオペランドの値と右側のオペランドの値を乗算した値(積)を代入する。 |
/= | 除算代入 | 演算子の左側のオペランドに、左側のオペランドの値を右側のオペランドの値で除算した値(商)を代入する。 |
%= | 剰余代入 | 演算子の左側のオペランドに、右側のオペランドの値を減算した値を代入する。 |
算術代入演算子を使用することで、プログラムコードをシンプルに記述することができます。
以下の2つの処理(変数jの値に3加算する)は同じ結果となりますが、算術代入演算子を利用したコードの方が簡潔になっています。
// 代入演算子と算術演算子を利用する場合
j = j + 3;
// 算術代入演算子を利用する場合
j += 3;
実際に各算術代入演算子を使用した場合の動作を以下に示します。
・加算代入(+=)
int j1 = 10;
j1 += 3;
System.out.println(j1); // 13 が出力される(10 + 3)
・減算代入(-=)
int j2 = 10;
j2 -= 3;
System.out.println(j2); // 7 が出力される(10 - 3)
・乗算代入(*=)
int j3 = 10;
j3 *= 3;
System.out.println(j3); // 30 が出力される(10 * 3)
・除算代入(/=)
int j4 = 10;
j4 /= 3;
System.out.println(j4); // 3 が出力される(10 / 3)
・剰余代入(%=)
int j5 = 10;
j5 %= 3;
System.out.println(j5); // 1 が出力される(10 % 3)
比較演算子と比較の内容
比較演算子は、演算子の左右のオペランドを比較するための演算子です。
比較演算子
比較演算子では、指定された条件に合致しているかどうかを真偽値(boolean)で返却します。
演算子の左右のオペランドどちらにも変数以外を記述することもできます。
演算子 | 概要 | 処理の内容 |
== | 等しい | 演算子の左右のオペランドが等しいかどうかを判定し、等しい場合はtrue、等しくない場合はfalseを返却する。 ・プリミティブ型の場合は値が等しいかどうかを判定する。 ・参照型の場合は参照先(インスタンス)が同じかどうかを判定する。 ・整数型のラッパークラス(Integer、Long等)同士の比較に利用する場合は注意が必要。 |
!= | 等しくない | 演算子の左右のオペランドが等しくないかどうかを判定し、等しい場合はfalse、等しくない場合はtrueを返却する。 ・型による比較内容は「==」と同様だが、結果が逆になる。 |
> | より大きい | 演算子の左側の値が、右側の値より大きいかどうかを判定し、大きい場合はtrue、それ以外の場合はfalseを返却する。 ・原則、数値型(およびラッパークラス)のみ比較が可能。 |
>= | 以上 | 演算子の左側の値が、右側の値以上かどうかを判定し、右側の値以上の場合はtrue、それ以外の場合はfalseを返却する。 ・原則、数値型(およびラッパークラス)のみ比較が可能。 |
< | 未満 | 演算子の左側の値が、右側の値未満かどうかを判定し、右側の値未満の場合はtrue、それ以外の場合はfalseを返却する。 ・原則、数値型(およびラッパークラス)のみ比較が可能。 |
<= | 以下 | 演算子の左側の値が、右側の値以下かどうかを判定し、右側の値以下の場合はtrue、それ以外の場合はfalseを返却する。 ・原則、数値型(およびラッパークラス)のみ比較が可能。 |
整数、または小数点以下の値を持たない浮動小数点数同士の場合は、型が違っても比較が可能です。
下記の例の場合は、全て「true」が出力されます。
byte b1 = 1;
int i1 = 1;
float f1 = 1;
double d1 = 1;
System.out.println(b1 == i1); // true
System.out.println(f1 == d1); // true
System.out.println(b1 == d1); // true
System.out.println(i1 == f1); // true
型が違う浮動小数点数で、小数点以下の値を持つ値同士を比較した場合は、想定と異なる結果となる場合があるので注意してください。
試しに、float型の変数とdouble型の変数を比較してみます。
float f2 = 0.12345f;
double d2 = 0.12345d;
double d3 = 0.1234d + 0.00005d; // 0.12345d と同じ値になることを想定
floatの値(f2)とdoubleの値(d2)を、各比較演算子で比較した結果は、以下のようになります。
System.out.println(f2 == d2); // false が出力される
System.out.println(f2 != d2); // true が出力される
System.out.println(f2 > d2); // true が出力される
System.out.println(f2 >= d2); // true が出力される
System.out.println(f2 < d2); // false が出力される
System.out.println(f2 <= d2); // false が出力される
double同士の値を加算した値(d3)と、doubleの値(d2)を比較した場合も、想定と異なる結果が返ります。
System.out.println(d3 == d2); // false が出力される
System.out.println(d3 != d2); // true が出力される
System.out.println(d3 > d2); // false が出力される
System.out.println(d3 >= d2); // false が出力される
System.out.println(d3 < d2); // true が出力される
System.out.println(d3 <= d2); // true が出力される
加算の演算子(+)同様、char型を比較演算子で比較する場合は、コードポイントの値で比較されることに注意してください。
char c1 = '1';
short s1 = 1;
// 以下では、c1は文字'1'のコードポイント値(0x0031 = 49)で比較される
System.out.println(c1 == s1); // false が出力される
System.out.println(c1 > s1); // true が出力される
参照型変数の比較と特殊な例について
参照型変数の比較(==)
参照型の変数同士を比較する場合は、互いの参照が同じかどうか(参照しているインスタンスが「同じインスタンス」であるかどうか)を判断します。
以下の例では、BigDecimal型の変数bd1、bd2に対して各々newキーワードで新しく生成したインスタンスへの参照を代入しているため、この2つの変数を「==」で比較した結果はfalseとなっています。
BigDecimal bd1 = new BigDecimal(100);
BigDecimal bd2 = new BigDecimal(100); // bd1とは別の新しいインスタンスを生成
System.out.println(bd1 == bd2); // false
[変数bd1とbd2は異なるインスタンスを参照している]
次に以下の例では、BigDecimal型の変数bdBaseには新しいインスタンスを生成して代入していますが、変数bdSameにはbdBaseが持つ参照を代入しています。
この例では、2つの変数は同じインスタンスへの参照を保持しているため、「==」で比較した結果はtrueとなります。
BigDecimal bdBase = new BigDecimal(100);
BigDecimal bdSame = bdBase; // bdBase(が持つインスタンスへの参照)を代入
System.out.println(bdBase == bdSame); // true が出力される
[変数bdBaseとbdSameは同じインスタンスを参照している]
ただし、参照型の変数の比較であっても、後述のとおり特殊な動作となるものがあることに注意してください。
特殊な例① Stringクラス
Stringクラスの変数は参照型変数ですが、代入の処理時にStringクラス固有の動作が行われるため、比較結果が想定と異なる場合があります。
以下にStringクラスのインスタンス生成のしくみと、比較結果の例を説明します。
String str1 = "こんにちは";
String str2 = "こんにちは";
String strnew1 = new String("こんにちは");
String strnew2 = new String("こんにちは");
System.out.println(str1 == str2); // true が出力される
System.out.println(str1 == strnew1); // false が出力される
System.out.println(strnew1 == strnew2); // false が出力される
まず、上記の変数str1、str2に代入しているような「ダブルクォーテーションで囲んだ文字列」を「文字列リテラル」と呼びます。
String型の変数に対して文字列リテラルを代入した場合、JavaのStringクラスではメモリ上の「生成済の文字列リテラル」を共有している領域(Stringコンスタントプール)を検索します。
このとき、共有領域にない新しい文字列リテラルであれば、新しいインスタンスを生成して共有領域へ登録します(下図①)。同じ内容の文字列リテラルが共有領域に既にある場合は、新しいインスタンスは生成せずに、そのインスタンスへの参照を代入します(下図②)。
上図のとおり、変数str1、str2には同じインスタンスへの参照が代入されるため、str1 == str2 の比較結果はtrueとなります。
これに対し、newキーワードでStringクラスのインスタンスを生成した場合、共有領域の外に別々のインスタンスとして新しく生成される(上図③&④)ため、str1 == strnew1 や strnew1 == strnew2 の比較結果は、両方ともfalseとなります。
特殊な例② 整数型のラッパークラス
整数型のラッパークラスの変数同士を比較した場合も、特殊な動作になるため注意が必要です。
下記のサンプルコードでは、100の値の変数同士(integer01とinteger02)を「==」で比較した結果はtrue、1000の値を代入した変数同士(integer03とinteger04)の比較結果はfalseとなっています。
Integer integer01 = 100;
Integer integer02 = Integer.valueOf(100);
Integer integer03 = 1000;
Integer integer04 = Integer.valueOf(1000);
System.out.println(integer01 == integer02); // true が出力される
System.out.println(integer03 == integer04); // false が出力される
// 比較対象の片方がプリミティブ型の値の場合は想定通り
System.out.println(integer03 == 1000); // true が出力される
System.out.println(1000 == integer04); // true が出力される
// 数式にした場合も想定通り
System.out.println(integer03 + 1 == integer04 + 1); // true が出力される
System.out.println((integer01 + integer03) == (integer02 + integer04)); // true が出力される
これは、Integerクラスが準備しているインスタンスのキャッシュ(すぐに利用できるように事前に準備してあるもの)により、-128~127の範囲の値を直接指定した変数には、Integerクラスがあらかじめ準備しているインスタンスへの参照が代入されるため、「==」で比較した場合もtrueが返されています。
-128~127の範囲外の値を変数に代入した場合は、新しいIntegerクラスのインスタンスが生成されるため、変数integer03、integer04にはそれぞれ別のインスタンスへの参照が代入されています。
これらの動作は、Integer型の変数に直接値を代入した場合も、Integer.valueOfメソッドの結果を代入した場合どちらでも同様です。
Integer以外でも、ShortクラスやLongクラスといった整数値のラッパークラスのインスタンス生成時は同様の動作となり、値が -128~127の範囲内(※)であれば「==」で比較しても値での比較結果を得ることはできますが、範囲外の場合は異なる結果が返ってくることになります。
(※厳密にはIntegerクラスのみ範囲を変更する方法がありますが、ここでは説明は割愛します)
このため、数値として比較したい場合は、ラッパークラスのインスタンスをそのまま「==」で比較することは避けたほうが良いでしょう。
数値を持つ参照型の比較方法
整数型のラッパークラスやBigDecimalクラスのような、数値を持つクラスのインスタンス同士を比較する場合は、対象のクラスによっていくつかの方法があります。
整数型のラッパークラスの場合は、プリミティブ型の値同士を比較するか、compareToメソッドを利用することで、数値での比較が可能です。
compareToメソッドでは、メソッドの結果(戻り値)を0と比較することで、比較演算子での評価と同じ結果を得ることが可能です。
また、同値かどうかの比較であれば、equalsメソッドを利用することもできます。
Integer integer05 = 10000;
Integer integer06 = 10000;
// プリミティブ型の値同士で比較
System.out.println(integer05.intValue() == integer06.intValue()); // true
System.out.println(integer05.intValue() != integer06.intValue()); // false
System.out.println(integer05.intValue() > integer06.intValue()); // false
System.out.println(integer05.intValue() >= integer06.intValue()); // true
System.out.println(integer05.intValue() < integer06.intValue()); // false
System.out.println(integer05.intValue() <= integer06.intValue()); // true
// compareToメソッドを利用
System.out.println(integer05.compareTo(integer06) == 0); // true
System.out.println(integer05.compareTo(integer06) != 0); // false
System.out.println(integer05.compareTo(integer06) > 0); // false
System.out.println(integer05.compareTo(integer06) >= 0); // true
System.out.println(integer05.compareTo(integer06) < 0); // false
System.out.println(integer05.compareTo(integer06) <= 0); // true
// (参考)equals メソッドを利用した比較
System.out.println(integer05.equals(integer06)); // true
その他、BigDecimalのような数値を扱うためのクラスでは、compareToメソッドのように比較のためのメソッドが準備されていますので、それらのメソッドを利用した比較を行います。
(演算子とは異なる内容ですので、ここでは気になる方だけ、下記の「BigDecimalでの大小比較について」を開いてお読みください)
※BigDecimalの値の同一・大小の比較について
BigDecimal型の変数の値が同一かどうか、および大小の比較を行う場合は、BigDecimalクラスのcompareToメソッドが利用できます。
BigDecimalのcompareToメソッドでも、整数型のラッパークラスと同様に、実行結果の値を0と比較することで、比較演算子での判定と同じ結果を得ることができます。
また、BigDecimalではcompareToメソッドを利用することで、小数の値でも正しく比較することが可能です。
BigDecimal bd1 = new BigDecimal("123.456");
BigDecimal bd2 = new BigDecimal("123.456");
// bd1.compareTo(bd2) の実行結果と、0 を比較することで比較する
System.out.println(bd1.compareTo(bd2) == 0); // true
System.out.println(bd1.compareTo(bd2) != 0); // false
System.out.println(bd1.compareTo(bd2) > 0); // false
System.out.println(bd1.compareTo(bd2) >= 0); // true
System.out.println(bd1.compareTo(bd2) < 0); // false
System.out.println(bd1.compareTo(bd2) <= 0); // true
// BigDecimalのインスタンスの数値を確認
System.out.println(bd1); // 123.456
System.out.println(bd2); // 123.456
ただし、BigDecimalのインスタンスを生成する時点で、引数にfloatやdoubleの値を指定していた場合は、BigDecimal同士でも想定と異なる場合があることに注意してください。
これは、BigDecimalが浮動小数点数の厳密な値でインスタンス化されるため、インスタンスの生成時点で想定と異なる値となっている場合があるためです。
BigDecimal bd3 = new BigDecimal(123.456); // 小数を指定(デフォルト:double型)
BigDecimal bd4 = new BigDecimal(123.456f); // floatを指定
System.out.println(bd3.compareTo(bd4) == 0); // false
System.out.println(bd3.compareTo(bd4) != 0); // true
System.out.println(bd3.compareTo(bd4) > 0); // true
System.out.println(bd3.compareTo(bd4) >= 0); // true
System.out.println(bd3.compareTo(bd4) < 0); // false
System.out.println(bd3.compareTo(bd4) <= 0); // false
// そもそも異なる値でインスタンスが生成されている
System.out.println(bd3); //123.4560000000000030695446184836328029632568359375
System.out.println(bd4); //123.45600128173828125
この場合は、BigDecimalのインスタンスを生成する時点で、引数に指定する浮動小数点数を文字列化しておくことで回避することができる場合があります。
(数式の結果を引数に指定するなど、精度が異なる桁数の値が指定されるような場合は除きます)
float fvalue = 123.456f;
double dvalue = 123.456d;
// インスタンス生成時に引数を文字列化しておく
BigDecimal bd5 = new BigDecimal(fvalue + "");
BigDecimal bd6 = new BigDecimal(dvalue + "");
// 数値の比較と値の確認
System.out.println(bd5.compareTo(bd6) == 0); // true
System.out.println(bd5); // 123.456
System.out.println(bd6); // 123.456
// 精度が異なる数式はNG
BigDecimal bd7 = new BigDecimal((1f / 3) + "");
BigDecimal bd8 = new BigDecimal((1d / 3) + "");
// 数値の比較と値の確認
System.out.println(bd7.compareTo(bd8) == 0); // true
System.out.println(bd7); // 0.33333334
System.out.println(bd8); // 0.3333333333333333
論理演算子
論理演算子
論理演算子は、真偽値に対する評価を行うための演算子です。
評価した結果は真偽値として返却されます。
演算子 | 概要 | 処理の内容 |
&& | 論理積 (短絡) | 演算子の左右のオペランドがともに真(true)の場合はtrue、いずれかが偽(false)の場合はfalseを返却する。 ・左右のオペランドには真偽値(booleanまたはBoolean型の変数またはリテラル)、または真偽値を返す式のみ記述することが可能。 |
|| | 論理和 (短絡) | 演算子の左右のオペランドのいずれかが真(true)の場合はtrue、ともにが偽(false)の場合はfalseを返却する。 ・左右のオペランドには真偽値、または真偽値を返す式のみ記述することが可能。 |
! | 否定 | 演算子の後続のオペランドが真(true)の場合はfalse、偽(false)の場合はtrueを返却する。 ・後続のオペランドには真偽値(および真偽値を返す式)のみ記述することが可能。 |
以下の演算子は「ビット演算」の演算子として分類されますが、上記の論理演算子と同じように真偽値同士の論理演算でも利用できるため、ここでも説明しておきます。
演算子 | 概要 | 処理の内容 |
& | 論理積 | 演算子の左右のオペランドがともに真(true)の場合はtrue、いずれかが偽(false)の場合はfalseを返却する。 ・左右のオペランドには真偽値、または真偽値を返す式を記述した場合。 ※左右のオペランドに整数値を記述した場合はビット論理積となる。 |
| | 論理和 | 演算子の左右のオペランドがともに真(true)の場合はtrue、いずれかが偽(false)の場合はfalseを返却する。 ・左右のオペランドには真偽値、または真偽値を返す式を記述した場合。 ※左右のオペランドに整数値を記述した場合はビット論理和となる。 |
^ | 排他的論理和 | 演算子の左右のオペランドのどちらか1つが真(true)の場合はtrue、ともに真(true)またはともに偽(false)の場合はfalseを返却する。 ※左右のオペランドに整数値を記述した場合はビット排他的論理和となる。 |
その他の演算子
これら以外にも、ビット演算子、ビット演算の代入演算子、instanceof演算子、三項演算子といった演算子があります。
当記事(Java入門)では、今後の記事でもビット演算子やinstanceof演算子はほとんど利用しませんので、これらの説明は読み飛ばしても問題ありませんが、こういった演算子があることは覚えておいてください。
※三項演算子は今後も利用しますので、ここで使い方を覚えておいてください。
ビット演算子
演算子 | 概要 | 処理の内容 |
& | ビット論理積 | 演算子の左右のオペランド(整数値)のビット論理積(整数値)を返却する。 ・左右のオペランドにlong型を含む場合は戻り値はlong値、含まない場合はint値が返される。 |
| | ビット論理和 | 演算子の左右のオペランド(整数値)のビット論理和(整数値)を返却する。 ・左右のオペランドにlong型を含む場合は戻り値はlong値、含まない場合はint値が返される。 |
^ | ビット排他的論理和 | 演算子の左右のオペランド(整数値)のビット排他的論理和(整数値)を返却する。 ・左右のオペランドにlong型を含む場合は戻り値はlong値、含まない場合はint値が返される。 |
~ | ビット反転 | 演算子の後続のオペランド(整数値)をビット反転した値を返却する。 ・後続のオペランドがlong型の場合は戻り値はlong値、それ以外の場合はint値が返される。 |
<< | 左シフト | 演算子の左側のオペランド(整数値)に対し、右側のオペランド(整数値)の値だけビットを左シフトした値を返却する。 ・左シフト時、下位ビットは0で埋められる。 ・左側のオペランドがlong型の場合は戻り値はlong値、それ以外の場合はint値が返される。 |
>> | 右シフト (符号あり) | 演算子の左側のオペランド(整数値)に対し、右側のオペランド(整数値)の値だけビットを右シフトした値を返却する。 ・右シフト時、上位ビットは最上位のビット値で埋められる。 ・左側のオペランドがlong型の場合は戻り値はlong値、それ以外の場合はint値が返される。 |
>>> | 右シフト (符号なし) | 演算子の左側のオペランド(整数値)に対し、右側のオペランド(整数値)の値だけビットを右シフトした値を返却する。 ・右シフト時、上位ビットは0で埋められる。 ・左側のオペランドがlong型の場合は戻り値はlong値、それ以外の場合はint値が返される。 |
算術代入演算子(ビット演算)
演算子 | 概要 | 処理の内容 |
&= | 論理積代入 | 演算子の左側のオペランドに、左右のオペランドの論理積を代入する。 ・左右のオペランドが真偽値の場合は、真偽値の論理積を代入する。 ・左右のオペランドが整数値の場合は、整数値のビット論理積を代入する。 |
|= | 論理和代入 | 演算子の左側のオペランドに、左右のオペランドの論理和を代入する。 ・左右のオペランドが真偽値の場合は、真偽値の論理和を代入する。 ・左右のオペランドが整数値の場合は、整数値のビット論理和を代入する。 |
^= | 排他的論理和代入 | 演算子の左側のオペランドに、左右のオペランドの論理和を代入する。 ・左右のオペランドが真偽値の場合は、真偽値の論理和を代入する。 ・左右のオペランドが整数値の場合は、整数値のビット論理和を代入する |
<<= | 左シフト代入 | 演算子の左側のオペランド(整数値)に、右のオペランド(整数値)の値だけ左シフトした値を代入する。 |
>>= | 右シフト代入 (符号あり) | 演算子の左側のオペランド(整数値)に、右のオペランド(整数値)の値だけ右シフトした値を代入する。 ・右シフト時、上位ビットは最上位のビット値で埋められる。 |
>>>= | 右シフト代入 (符号なし) | 演算子の左側のオペランド(整数値)に、右のオペランド(整数値)の値だけ右シフトした値を代入する。 ・右シフト時、上位ビットは0で埋められる。 |
instanceof演算子
instanceof 演算子は、参照型の変数が指定したクラス(または、その継承先クラス)であるかどうかを判定するための演算子です。
演算子 | 概要 | 処理の内容 |
instanceof | クラス一致 | 演算子の左側のオペランド(参照型変数)が、右側のオペランド(型)のインスタンスを参照しているかどうかを判定した結果を返却する。 ・左側の変数の参照先が、右側で指定したクラスのインスタンスである場合はtrueを返す。 ・左側の変数の参照先が、右側で指定したクラスを継承したクラスのインスタンスである場合もtrueを返す。 ・上記以外の場合はfalseを返す。 |
以下では3つのクラスを準備し、それぞれのインスタンス変数に対してinstanceof演算子での判定を行ってみます。
/** 比較対象の基本のクラス */
public class ClassBase { }
/** 異なるもう1つのクラス */
public class ClassOther { }
/** 基本のクラスを継承したクラス */
public class ClassExt extends ClassBase { }
ClassBaseとClassExtは継承(親子)関係のクラス、ClassOtherはこれらのクラスとの継承関係のないクラスとして定義しています。
Javaのクラスは全てObjectクラスを継承します。
もちろん上記のいずれのクラスも、Objectクラスを継承したクラスです。このため以下の例のように、Object型の変数にそれぞれのクラスのインスタンスを代入することができてしまいます。
Object objBase = new ClassBase();
Object objOhter = new ClassOther();
Object objExt = new ClassExt();
この例のように記述した場合は、コード上では全てObjectクラスとみなされますので、どの変数が処理に必要なクラスのインスタンスなのか判別できなくなる場合があります。
ここでは、特定のクラス(ClassBase)のインスタンスを、instanceof演算子で判別してみます。
System.out.println(objBase instanceof ClassBase); // true
System.out.println(objOhter instanceof ClassBase); // false
// 子クラス(ClassExt)は親クラス(ClassBase)でもあるので真となる
System.out.println(objExt instanceof ClassBase); // true
// 逆は成り立たない
System.out.println(objBase instanceof ClassExt); // false
instanceof演算子を利用する際、コンパイラが明らかに成立しない比較であると判断できる形でコードが記述されている場合は、コンパイルエラーが発生します。
下記のコードでは、変数clsOtherを「ClassOtherクラス」の変数として宣言したことにより、比較が成立しない(ClassOtherはClassBaseと継承関係にない)とコンパイラが判断することが可能なため、コンパイルエラーとなります。
ClassOther clsOhter = new ClassOther();
// 以下のコードはコンパイルエラーになる(コンパイラが非互換条件オペランド型と判定)
System.out.println(clsOhter instanceof ClassBase);
三項演算子
三項演算子は、「条件判定」と「式の選択」を同時に行う演算子です。
演算子 | 概要 | 処理の内容 |
? : | 三項演算子 | 「判定式 ? 式1: 式2」の形式で使用し、判定式の結果により式1または式2のどちらかを返します。 ・判定式の評価結果がtrueの場合は、式1を返します。 ・判定式の評価結果がfalseの場合は、式2を返します。 ・式1、式2には、変数や値を指定することも可能です。 |
以下の例では、条件判定( a > b )の判定結果により、変数に代入する式(および変数、値)を選択しています。
int a = 1;
int b = 2;
// boolean型の変数bool にaがbより大きい(a > b)かどうかを判断した結果を代入
boolean bool = a > b ? true : false;
// int型の変数x にaとbの大きいほうの値を代入
int x = a > b ? a : b;
// int型の変数y には、aがbより大きい時は「aとbの差」を、大きくない場合は0を代入
int y = a > b ? a - b : 0 ;