Javaではさまざまな演算子が使用できます。
しかし、初心者にとっては「演算子の使い方がよくわからない」「種類が多すぎてどんなときに何の演算子を使うのかわからない」
などの悩みを抱えている方も多いのではないでしょうか?
そこで、この記事では演算子について、
・算術演算子
・比較演算子
・代入演算子とインクリメント・デクリメント演算子
・条件演算子
・三項演算子
・シフト演算子
・演算子の優先順位
という基本的な内容から
・Javaでの演算子のオーバーロードについて
など応用的な内容についても解説していきます。
今回は演算子について、使い方をわかりやすく解説します!
なお、Javaの記事については、こちらにまとめています。
演算子の一覧表
Javaの演算子には種類があります。その種類を見てみましょう。
演算子の種類 | 記号 |
---|---|
算術演算子 | +, -, *, /, % |
比較演算子 | >, >=, <, <=, ==, != |
代入演算子 | =, +=, -=, *=, /=, %= |
インクリメント・デクリメント演算子 | ++, –- |
条件演算子 | &, |, ^, !, ||, && |
シフト演算子 | <<, >> |
演算子ひとつとってもこれだけの種類があります。
では早速、それぞれの演算子について説明していきます!
算術演算子(+, -, *, /, %)
代入演算子について下記の表にまとめました。
記号 | 説明 |
---|---|
+ | 加算 |
- | 減算 |
* | 乗算 |
/ | 除算 |
% | 余り |
それではサンプルコードで確認していきましょう。
public class Main { public static void main(String[] args) { int a = 5; int b = 3; int c; // 加算 c = a + b; System.out.println("加算 c : " + c); // 減算 c = a - b; System.out.println("減算 c : " + c); a = 3; b = 4; // 乗算 c = a * b; System.out.println("乗算 c : " + c); a = 6; b = 2; // 除算 c = a / b; System.out.println("除算 c : " + c); a = 6; b = 2; // 剰余 c = a % b; System.out.println("剰余 c : " + c); /* Java.lang.ArithmeticException: / by zero a = 3; b = 0; // 除算 c = a / b; System.out.println("除算 c : " + c); */ } }
実行結果:
加算 c : 8 減算 c : 2 乗算 c : 12 除算 c : 3 剰余 c : 0
このサンプルコードでは、加算、減算、乗算、除算、剰余を行っています。
また、サンプルコードの最後はコメントアウトしています。
コメントアウト内では3を0で割っていますが、これはJavaの「java.lang.ArithmeticExeption: / by zero」が発生します。
この例外が発生することで、プログラムは停止してしまう可能性がありますので注意しましょう!
比較演算子とinstanceof演算子
比較演算子(>, >=, <, <=, ==, !=)
よく使う基本的な演算子について見てみましょう。
演算子 | 読み | 書き方 | 説明 |
---|---|---|---|
> | 大なり | a > b | aはbより大きい |
>= | 大なりイコール | a >= b | aはb以上 |
< | 小なり | a < b | aはbよりも小さい |
<= | 小なりイコール | a <= b | aはb以下 |
== | イコール | a == b | aとbは同じ |
!= | ノットイコール | a != b | aとbは同じでない |
比較演算子の詳しい使い方についてはこちらで解説しているので参考にしてくださいね。
instanceof演算子
Javaにはinstanceof演算子というものがあります。
instanceof演算子はオブジェクトの型を判定する演算子です。
instanceof演算子は左辺側に比較元となるオブジェクトを指定し右辺側に比較するオブジェクト型を指定します。
instanceof演算子の詳しい使い方についてはこちらで解説しているので参考にしてくださいね。
代入演算子とインクリメント・デクリメント演算子
代入演算子(=, +=, -=, *=, /=, %=)
代入演算子は変数に値を代入する際に用います。
代入演算子について下記の表にまとめました。
記号 | 説明 |
---|---|
= | 代入 |
+= | 加算して代入 |
-= | 減算して代入 |
*= | 乗算して代入 |
/= | 除算して代入 |
%= | 剰余して代入 |
それではサンプルコードで確認していきましょう。
public class Main { public static void main(String[] args) { int foo = 0; // 代入 foo = 5; // 代入 // foo = foo + 3; と同じ意味 foo += 3; System.out.println("foo : " + foo); } }
実行結果:
foo : 8
このサンプルコードでは、最初のfooを定義した段階で変数の値を初期化するために「=」が使われています。
この「=」が代入演算子になります。
その後に変数fooに対して5を代入しています。
また、足し算をして代入する場合により短く書ける「+=」を使っています。
インクリメント・デクリメント演算子(++, –-, 前置, 後置)
インクリメント演算子は数値型の変数にプラスを2個続けて書くことで1を加算することができる演算子です。
インクリメントには前置インクリメントと後置インクリメントとがあります。
前置と後置ではそれぞれ若干意味が違ってくるため使う場合に応じて変更が必要です。
前置インクリメントの場合は1を足した後に変数に代入を行ないますが、後置インクリメントの場合は値を先に変数に代入してから値を1足します。
また、デクリメント演算子は1を減算する演算子になります。
デクリメント演算子についてもインクリメント演算子同様、前置・後置の使い方ができます。
それではサンプルコードで確認していきましょう。
public class Main { public static void main(String[] args) { int foo = 0; int bar = 0; // 後置インクリメントの場合 bar = foo++; System.out.println("foo : " + foo); System.out.println("bar = " + bar); foo = 0; bar = 0; // 前置インクリメントの場合 bar = ++foo; System.out.println("foo : " + foo); System.out.println("bar = " + bar); foo = 1; // デクリメントの場合 foo--; System.out.println("foo : " + foo); } }
実行結果:
foo : 1 bar = 0 foo : 1 bar = 1 foo : 0
このサンプルコードでは、1番目に後置インクリメントの場合について記述しています。
後置インクリメントの場合は変数fooの値を先に変数barに代入してからfooの値を1足しています。
2番目に前置インクリメントの場合について記述しています。
前置インクリメントの場合は変数fooに1を足した後に変数barに代入を行なっています。
このように前置インクリメントの場合と後置インクリメントの場合では、結果に差が生じることになります。
使う際には前置で書くべきか後置で書くべきかを考える必要があります。
3番目に後置デクリメントの場合について記述しています。
条件演算子
論理演算子(&, |, ^)
論理演算子には3種類あります。
記号 | 名前 | 説明 |
---|---|---|
& | ビット論理積 | ANDを返す |
| | ビット論理和 | ORを返す |
^ | ビット排他的論理和 | XORを返す |
それではサンプルコードで確認していきましょう。
public class Main { public static void main(String[] args) { int foo = 1; int bar = 3; int result = 0; // 論理和(OR) result = foo | bar; System.out.println("result = " + result); // 論理積(AND) result = foo & bar; System.out.println("result = " + result); // 排他的論理和(XOR) result = foo ^ bar; System.out.println("result = " + result); } }
実行結果:
result = 3 result = 1 result = 2
このサンプルコードでは、まず1番目に変数fooと変数barの論理和の結果は3となるため変数resultは3が入ります。
次に2番目は論理積になるので結果は1となり変数resultには1が入ります。
3番目は変数fooと変数barの1ビット目が両方1であるため排他的論理和の場合は0になります。
その結果、変数resultには2が入ることになります。
短絡演算子(!, ||, &&)
短絡演算子には3種類あります。
記号 | 名前 | 説明 |
---|---|---|
|| | 論理和 | どちらかの条件が成立すれば真 |
&& | 論理積 | 条件が両方成立すれば真 |
! | 否定 | 真のとき偽。偽のとき真。 |
それではサンプルコードで確認していきましょう。
public class Main { public static void main(String[] args) { int foo = 1; int bar = 2; if(foo == 1 || bar == 1) { System.out.println("TEST1:TRUE"); } if(foo == 1 && bar == 1) { System.out.println("TEST2:TRUE"); } boolean baz = true; if(!baz) { System.out.println("TEST3:TRUE"); } } }
実行結果:
TEST1:TRUE
このサンプルコードでは、まず1番目に変数fooの中身が1もしくは変数barの中身が1である場合は真となりブロック内({})にあるprintfを実行しています。
次に2番目は偽(false)となりTRUEという文字は表示されません。
左辺の式と右辺の式の条件を両方共満たす必要がありどちらか一方の条件が満たされていない場合は、もう片方が条件を満たしていたとしても偽となりブロック内({})に入ることはありません。
3番目はbazがfooがtrueであればTRUEと表示されるはずですが今回はif文中の変数fooの前に「!」がついています。
bazがtrueである場合は偽(false)となりますので、TRUEという文字は表示されません。
三項演算子
三項演算子は条件をみたす場合と満たさない場合で結果を分岐させることのできる演算子です。
考え方としてはif文に近いものがあります。
ではさっそくサンプルコードを見てみましょう。
public class Main { public static void main(String[] args) { int foo = 1; int bar = 0; bar = foo == 1 ? 10 : 20; System.out.println("bar = " + bar); } }
実行結果:
bar = 10
このサンプルコードでは、fooの値が1かどうかをチェックし真である場合(1である場合)に10を変数barに代入しています。
偽(1出ない場合)は変数barには20が入る仕組みになっています。
なお、この三項演算子については議論がありif文を三項演算子にして扱ったりあらゆる所で三項演算子に使う事は可読性が落ちるとも言われ避けられる場合もあります。
シフト演算子
シフト演算はビット演算に用いられる演算子です。
左シフト(<<)
変数の値を2ビット左にシフトさせたい場合は「<<」を使って下記のように書きます。
左シフトの記述例:
int foo = 1; foo = foo << 2; // 基本的な書き方 foo <<= 2; // 代入演算子とくっつけても書けます
1つ目の左シフトで2ビット左に動かしています。この際動かした右側には0で埋められるというルールがあるため2ビット動かした場合は変数fooの値は4になります。
2つ目の左シフトではさらに2ビット左に移動させているため変数fooの値は16になります。
右シフト(>>)
先程解説した左シフトの反対方向に値をシフトさせることができるのがこの右シフト「>>」です。
なお、この右シフトには二種類あります。
まず「>>」は右側にシフトさせる効果がありますが移動後の左側には最上位ビットで埋められるというルールがあります。
0010 0000
これを2ビット右シフトした場合は
0000 1000
になります。
次に最上位のビットが1の場合を見てみましょう。
1000 0000
この状況で2ビットシフトした場合は次のようになります。
1110 0000
となります。
では左シフトと同じ様に強制的に0で埋めたい場合は「>>」ではなく「>>>」を使いましょう。
演算子の優先順位
演算子には優先順位という考え方があります。
まず、プログラムが処理を行う場合は原則的に左から右という流れがありますが、代入演算子を用いた式を評価(処理)する場合は右辺が優先されます。
そして、算数と同じく「+」や「-」よりも「*」や「/」の方が優先順が高いため先に計算される仕組みになっています。
優先順位について下記の表にまとめました。
優先順位 | 演算子 | 名前 |
---|---|---|
1 | ++, -- | 後置インクリメント, 後置デクリメント |
2 | !, ++, -- | 論理否定, 前置インクリメント, 前置デクリメント |
3 | *, /, % | 乗算, 除算, 剰余 |
4 | +, - | 加算, 減算 |
5 | <<, >> | 左シフト, 右シフト |
6 | >, >=, <, <=, instanceof | より大きい, 以上, より小さい, 以下, 型比較 |
7 | ==, != | 等価, 非等価 |
8 | & | ビット論理積 |
9 | ^ | ビット排他的論理和 |
10 | | | ビット論理和 |
11 | && | 論理積 |
12 | || | 論理和 |
それではサンプルコードで確認していきましょう。
public class Main { public static void main(String[] args) { int foo = 0; foo += 5 + 2 * 4 / 3; System.out.println("foo = " + foo); } }
実行結果:
foo = 7
このサンプルコードの場合、2*4が先に行われます。
次にその結果である8と3の除算が行われたあとに5を加算しその合計値をfooに加算するといった計算式になります。
このあたりの優先順位についてはとても細かく決められているため複雑な計算式を作る際は注意が必要です。
ちなみに、極力複雑な計算式を作る様な状況は避けるべきですが・・・
Javaでの演算子のオーバーロードについて
Javaでは演算子の挙動を変更する演算子のオーバーロードやオーバーライドができません。
C++ではoperatorキーワードを使うことで[]や=、+などといった演算子の挙動を決めることができます。
しかしJavaではそのような機能が備わっていません。
オーバーロードとオーバーライドについては次の記事で詳しく解説しているので、ぜひ確認してください。
まとめ
ここでは、演算子について解説してきましたがいかがだったでしょうか?
よく使う演算子からあまり使わない演算子まで一通り解説をしてきました。
ちょっと長い記事になりましたが忘れてしまったときには、この記事を思い出して頂ければすぐに復習できるかと思います!