【Java入門】演算子について（算術演算子、複合代入演算子、関係演算子、論理演算子）

#目的

Java言語を含めたプログラミングの学習を始めたばかりの方、既学習者の方は復習用に、
今回は**演算子**について学ぶために書いています。

[【Java入門目次】](https://qiita.com/morioheisei/items/6c7fc063c26e63d890ac)
・[変数と型](https://qiita.com/morioheisei/items/3d27e82d6cd88068dded)
・[型変換](https://qiita.com/morioheisei/items/28ab5fd69570e01cd317) 
・[変数のスコープ](https://qiita.com/morioheisei/items/c56ab32b68ce92d32206)
・[文字列の操作](https://qiita.com/morioheisei/items/e58adadd8535971b69be)
・[配列の操作](https://qiita.com/morioheisei/items/b6acbb1b0c07b40e7f56)
・演算子（準備中） ←今ここ
・[条件分岐](https://qiita.com/morioheisei/items/194cdc73a29bddade0a4)
・[繰り返し処理](https://qiita.com/morioheisei/items/e686e33b60c6a60e87f0)
・クラスについて（準備中）
・抽象クラス（準備中）
・インターフェース（準備中）
・カプセル化（準備中）
・モジュールについて（準備中）
・[例外処理について](https://qiita.com/morioheisei/items/d25d2b67e7530c1aab9d)
・[ラムダ式について](https://qiita.com/morioheisei/items/2bfcc3d8d8440b00e6a9)
・[Stream APIについて](https://qiita.com/morioheisei/items/3a7be38b4d3ef712ccb2)

#演算子とは

ソースコード内で値に対して**加算**や**減算**などの四則演算を行ったり、**値の比較**を行う場合に演算子を使います。
多くの演算子がありますが、いくつか見ていきましょう。


#算術演算子

加減乗除を行う演算子です。
演算対象となる変数やリテラルの事を**オペランド**とも呼びます。

以下は算術演算子の演算子と記述例です。

| 演算子     |記述例  |説明   |
|:-----------------|:------------------|:------------------|
| + | a + b | aとbを加算する |
| - | a - b | aからbを減算する |
| * | a * b | aとbを乗算する |
| / | a / b | aをbで除算する |
| % | a % b | aをbで除算した余りをだす |


実際に整数と整数で演算を行った結果は以下になります。

```java:算術演算子の例
int a = 100;
int b = 50;

System.out.println(a + b); // 150
System.out.println(a - b); // 50
System.out.println(a * b); // 500
System.out.println(a / b); // 2
System.out.println(a % b); // 0
```

###違う型同士で演算を行った時

整数と整数で演算を行った結果は整数になります。
しかし、**整数と浮動小数点数で演算を行った結果**は**浮動小数点数になります。**

Javaによって演算時に型変換が行われるためです。([型変換についての記事はこちら](https://qiita.com/morioheisei/items/28ab5fd69570e01cd317#%E3%83%97%E3%83%AD%E3%83%A2%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E6%98%87%E6%A0%BC))

```java:整数と浮動小数点数で演算をした例
int a = 3;
double b = 5.0;
System.out.println(a + b); // 8.0
```

###0で除算を行った時

整数や浮動小数点数に0で除算を行うとエラーが発生したり、非数、無限大が出力されるので気をつけましょう。

```java:0除算の例
int a = 8;
System.out.println(a / 0); // java.lang.ArithmeticException: / by zero エラー
System.out.println(a % 0); // java.lang.ArithmeticException: / by zero エラー

double b = 8.0;
System.out.println(b / 0); // Infinity
System.out.println(b % 0); // NaN
```



##優先度

演算子には**優先度**があり、1行の式の中に複数演算子があった場合に優先度の高いものから処理がなされます。

`*、 /、　%`は`+、 -`に比べて優先度は高いです。
決められた優先度より先に演算したい場合は、`()`で囲む事で優先的に演算をさせる事が出来ます。

```java:優先度の例
// 乗算が先に行われる
int num = 2 * 5 + 1;
System.out.println(num); // 11

// +(加算) を先に行いたい場合
int num2 = 2 * (5 + 1);
System.out.println(num2); // 12
```

##結合規則

また、優先度が同じ場合には**結合規則**でどの演算子から計算するか決められます。
**右結合**は、`右から左へ計算していきます。`
→単項演算子、三項演算子、代入演算子が該当します。

**左結合**は、`左から右へ計算していきます。`
→算術演算子や論理演算子が該当します。

```java:結合規則の例
String str = "Hello";
int a = 50, b = 50;

// 文字列+数字で文字列結合が行われ、「Hello50」となり、+50の処理が行われる。
System.out.println(str + a + b); // Hello5050

// a+bの足し算が行われ、「100」となり、+Helloの処理が行われる。
System.out.println(a + b + str); // 100Hello
```

**優先度**や**結合規則**を意識して扱わなければいけませんね。

#単項演算子

**++(インクリメント)**、**--(デクリメント)**と言います。
1つの値または変数の加算、減算を行う演算子です。


| 演算子     |記述例  |説明   |
|:-----------------|:------------------|:------------------|
| ++ | ++a、 a++ | aに1を加算する |
| -- | --a、 a-- | aに1を減算する |


##前置/後置の違い

`演算子`を**変数の前に配置**するのか、**後ろに配置する**のかで実行結果が変わってきます。

まずは、前置の場合。

```java:前置の場合
int a = 10;
int b = ++a;
System.out.println(a); // 11
System.out.println(b); // 11
```

a、b共に11になっています。
**前置の場合**、`他の処理よりも前にインクリメントが行われ`、bに代入されるため両方とも11になります。

次に後置の場合。

```java:後置の場合
int a = 10;
int b = a++;
System.out.println(a); // 11
System.out.println(b); // 10
```

aは11ですが、bは10になっています。
**後置の場合**、`他の処理が済んでからインクリメントが行われるため`、10をbに代入した後にaが11になります。

前置、後置の挙動の違いには注意しなければいけませんね。

#代入演算子と複合代入演算子

代入演算子は`=`を用いて右辺の値を左辺に代入する演算子です。
`a = b (aにbを代入する)`


また、複合代入演算子は、代入演算子と`+`や`-`などの演算子を組み合わせた演算子です。


|演算子     |記述例 |演算子    |算術演算子の場合 |
|:-----------------|:---------------------|:------------------|:------------------|
| += | a+=b | aにbを加えた値をaに代入する | a = a + b |
| -= | a-=b | aからbを引いた値をaに代入する | a = a - b |
| *= | a*=b | aにbを乗じた値をaに代入する | a = a * b |
| /= | a/=b | aをbで割った値をaに代入する | a = a % b |
| %= | a%=b | aをbで割った余りをaに代入する | a = a % b |


複合代入演算子を用いた結果は以下になります。

```java:複合演算子の例
int a = 10, b = 3;

a += b;
System.out.println(a); // 13

a -= b;
System.out.println(a); // 10

a *= b;
System.out.println(a); // 30

a /= b;
System.out.println(a); // 10

a %= b;
System.out.println(a) // 1
```

#関係演算子

**2つの値を比較する**際に使用する演算子です。
関係演算子を使用した結果は、**boolean値**である**true**または**false**が返ってきます。

| 演算子 | 記述例 | 説明 |
|:--|:--|:--|
| == | a==b | aとbの値が等しければtrue、異なればfalse |
| != | a!=b | aとbの値が異なればtrue、等しければfalse |
| > | a>b | aの値がbの値より大きければtrue、以下ならばfalse |
| >= | a>=b | aの値がbの値以上であればtrue、小さければfalse |
| < | a<b | aのbの値より小さければtrue、以上ならばfalse |
| <= | a<=b | aの値がbの値以下であればtrue、大きければfalse |


関係演算子を用いた例は以下になります。

```java:関係演算子の例
int a = 50, b = 30, c = 50;

System.out.println(a == b); // false
System.out.println(a == c); // true

System.out.println(a != b); // true
System.out.println(a != c); // false

System.out.println(a < b); // false
System.out.println(a <= c); // true

System.out.println(a > b); // true
System.out.println(a >= c); // true
```

#論理演算子

２つ以上の条件を元に評価を行う際に使用する演算子です。
論理演算子を使用した結果は、**boolean値**である**true**または**false**が返ってきます。


| 演算子 | 記述例 | 説明 |
|:--|:--|:--|
| & | a&b | aとbが共にtrueの時にtrue、そうでなければfalse<br>aがfalseであったとしてもbは評価される |
| && | a&&b | aとbの共にtrueの時にtrue、そうでなければfalse<br>aがfalseならbは評価されず結果がfalseとなり、aがtrueならbも評価され結果を返す |
| &#124; | a&#124;b | aとbいずれかがtrueならtrue、そうでなければfalse<br>aがtrueであったとしてもbは評価される|
| &#124;&#124; | a&#124;&#124;b | aとbいずれかがtrueならtrue、そうでなければfalse<br>aがtrueならbは評価されず結果がtrueとなり、<br>aがfalseならbも評価され結果を返す |
| ^ | a^b | aとbの値が異なる時true、そうでなければfalse |
| ! | !a | aの値がtrueの時false、falseの時true |


##&、&#124;を用いた例

and条件(&&)とor条件(&#124;&#124;)は、今までの演算子に比べてやや複雑ですので1つずつ深掘りしていきます。
(ビット演算の例は今回割愛します)


###&&の例

```java:&&の例
boolean result = c++ > 50 && ++d > 50;
System.out.println(result); // false
System.out.println("c: " + c + ", d: " + d); // c: 51, d: 50
```

1つ目の条件は後置インクリメントなので、50 > 50 で比較が行われ、結果はfalseが返ります。その後、cはインクリメントされます。


**&&の場合**、`1つ目の条件がfalseであった場合、2つ目の条件が評価されません。`そのためdのインクリメントの処理は実行されません。
1つ目の条件が**false**であったため、`resultにはfalseが代入`され、**cは51、dは50**となります。


###&#124;&#124;の例

```java:||の例
int c = 50, d = 50;
    
boolean result = ++c > 50 || ++d > 50;
System.out.println(result); // true
System.out.println("c: " + c + ", d: " + d); // c: 51, d: 50
```

1つ目の条件は前置インクリメントなので、**51 > 50**で比較が行われ、結果は**true**が返ります。


**||の場合**、`1つ目の条件がtrueであった場合、2つ目の条件が評価されません。`そのためdのインクリメントの処理は実行されません。
1つ目の条件が**true**であったため、`resultにはtrueが代入`され、**cは51、dは50**となります。


上記の通り、それぞれの動作の違いを把握して注意しなければいけませんね。


#終わりに

演算子の一部を紹介してみました。演算子は使用頻度が高いためしっかりと理解しておきたいですね。
今回紹介出来なかったものについては別記事で紹介出来たらと思います。


#参考サイト

**[算術演算子とは](https://www.javadrive.jp/start/ope/index1.html#section1)**
**[【超基本】Javaの論理演算子の使い方](https://eng-entrance.com/java-cal-logical)**