4.1 演算子（算術演算子、代入演算子、比較演算子、論理演算子、ビット演算子など）～Java Basic編

### はじめに

#### 自己紹介

皆さん、こんにちは、Udemy講師の斉藤賢哉です。私はこれまで、25年以上に渡って企業システムの開発に携わってきました。特にアーキテクトとして、ミッションクリティカルなシステムの技術設計や、Javaフレームワーク開発などの豊富な経験を有しています。
様々なセミナーでの登壇や雑誌への技術記事寄稿の実績があり、また以下のような書籍も執筆しています。
* [「マスタリング Java EE 5」（2007年）](https://amzn.asia/d/j0txqK5)
* [「アプリケーションアーキテクチャ設計パターン」（2017年）](https://amzn.asia/d/9avaCyF)

いずれも**Java EE**（**Jakarta EE**）を中心にした企業システム開発のための書籍です。中でも [「アプリケーションアーキテクチャ設計パターン」](https://amzn.asia/d/9avaCyF)は、（Javaに限定されない）比較的普遍的なテーマを扱っており、内容的にはまだまだ陳腐化していないため、興味のある方は是非手に取っていただけると幸いです（中級者向け）。

#### Udemy講座のご紹介

この記事の内容は、私が講師を務めるUdemy講座『**Java Basic編**』の一部の範囲をカバーしたものです。『**Java Basic編**』はこちらの[**リンク**](https://www.udemy.com/course/learn-java-se-basic/?referralCode=594C958456356851C97C)から購入できます（セールス対象外のためいつも同じ価格）。また**定価の約30%OFFで購入可能なクーポン**をQiita内で定期的に発行していますので、興味のある方は、ぜひ私の他の記事をチェックしてみてください。

この講座は、以下のような皆様にお薦めします。
* Javaの言語仕様や文法を正しく理解すると同時に、現場での実践的なスキル習得を目指している方
* 新卒でIT企業に入社、またはIT部門に配属になった、新米システムエンジニアの方
* 長年IT部門で活躍されてきた中堅層の方で、学び直し（リスキル）に挑戦しようとしている方
* 今後、フリーランスエンジニアとしてのキャリアを検討している方
* 「**Chat GPT**」のエンジニアリングへの活用に興味のある方
* 「**Oracle認定Javaプログラマ**」の資格取得を目指している方
* IT企業やIT部門の教育研修部門において、新人研修やリスキルのためのオンライン教材をお探しの方

#### この記事を含むシリーズ全体像

この記事はJava SEの一部の機能・仕様を取り上げたものですが、一連のシリーズになっており、**シリーズ全体でJava SEを網羅**しています。また認定資格である「**Oracle認定Javaプログラマ**」（Silver、Gold）の範囲もカバーしています。シリーズの全体像および「Oracle認定Javaプログラマ」の範囲との対応関係については、以下を参照ください。

https://qiita.com/KenyaSaitoh/items/4711a078a851510bc4da

## 4.1 演算子

チャプターの概要

このチャプターでは、変数やリテラルに対して様々な処理を行うための演算子について学びます。

### 4.1.1 演算子の概要

#### 演算子とオペランド

演算子とは、変数やリテラルに対して、あらかじめ決められた処理を行うための記号です。
これまでのレッスンで登場した`=`や`+`は、代表的な演算子です。演算子はオペレーターとも呼ばれますが、本コースでは演算子で統一します。
また演算子によって処理される変数やリテラルを、オペランドと呼びます。オペランドは、被演算子とも呼ばれますが、本コースでは「用語としての対称性」よりも分かりやすさを重視してオペランドで統一します。
式は、オペランドと演算子によって構成されます。例えば以下の式では、変数x、yやリテラル10がオペランドに、`=`や`+`が演算子に、それぞれ相当します。

```java:snippet_1 (Main_4_1)
int x = 30;
int y = x + 10;
```

【図4-1-1】演算子とオペランド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/113be691-d535-b3d6-1ae5-deabbef78b1f.png)

なおオペランドに対して演算子による処理を行い、その結果を得ることを「式を評価する」と言います。
演算子には、算術演算子、代入演算子、比較演算子、論理演算子、ビット演算子、という種類があります。これらについて、次のレッスンから順番に見ていきましょう。

#### 演算子の優先順位

Javaの演算子には、数学の演算子と同じように、優先順位が決められています。
以下に代表的な演算子の優先順位を示します。

【表4-1-1】演算子の優先順位
|優先度|記号|
|--|--|
|高い|++（後置記法）, --（後置記法）|
||++（前置記法）, --（前置記法）, !|
||*, /, %|
||+, -|
||<<, >>, >>>|
||<, >, <=, >=, instanceof|
||==, !=|
||&|
||^|
||&#124;|
||&&|
||&#124;&#124;|
||?:|
|低い|=, +=, -=, *=, /=, %=, &=, &#124;=, ^=, <<=, >>=, >>>=|

### 4.1.2 算術演算子

#### 算術演算子の種類

算術演算子は文字通り、四則演算など何らかの算術を行うための演算子です。
算術演算子には、以下のような種類があります。

【表4-1-2】算術演算子の種類
|算術演算子|説明|具体例|
|--|--|--|
|+|加算|30 + 10 ⇒ 40|
|-|減算|30 - 10 ⇒ 20|
|*|乗算|15 * 3 ⇒ 45|
|/|除算|15 / 3 ⇒ 5|
|%|剰余（除算の余り）|20 % 9 ⇒ 2|
|++|インクリメント演算子|int i = 10; int x = ++i ⇒ xは11、iは11<br>int i = 10; int x = i++ ⇒ xは10、iは11|
|--|デクリメント演算子|int i = 10; int x = --i ⇒ xは9、iは9<br>int i = 10; int x = i-- ⇒ xは10、iは9|

#### 算術演算子による四則演算

数値型データに対する算術演算子による四則演算は、一般的な数学と同じです。演算子同士には優先順位があり、＊（乗算）、／（除算）、％（剰余）が、＋（加算）、ー（減算）よりも優先順位は高くなります。乗算、除算、剰余よりも加算、減算を優先させたい場合は、その部分を`( )`で囲みます。
また％は、Javaに限らず多くのプログラミング言語において、剰余を表す記号として用いられています。例えば`20 % 9`の演算結果は、2になります。

演算子による四則演算は、直感的に理解できるケースが大半ですが、オペランドのデータ型によって挙動が変わります。まず整数型と整数型の演算では、結果は整数型になります。特に除算の場合は、小数点以下は切り捨てられるため、注意が必要です。次に整数型と浮動小数点型との演算は、結果は浮動小数点型になります。また浮動小数点型と浮動小数点型の演算は、結果は浮動小数点型になります。
なお整数型において「ゼロ除算」を行うと、java.lang.ArithmeticExceptionという例外が発生します（例外についてはチャプター19.1参照）。

#### 整数型と浮動小数点型との演算

前述したように整数型と浮動小数点型の演算では、結果は浮動小数点型になります。例えば以下のコードでは、`10 * 0.03`の乗算により、浮動小数点型である0.3という結果が得られるため、その結果をdouble型の変数yに代入しています。

```java:snippet_2 (Main_4_1)
int x = 10;
double y = x * 0.03;
```

次に、以下のコードはどうなるでしょうか。

```java:snippet_3 (Main_4_1)
int x = 100;
double y = x * 0.1;
```

このコードでは`100 * 0.1`の結果は10のため、一見するとこの値は整数型ではないか思われます。ところが実際にはこの値は浮動小数点型の10.0であり、double型などの型で扱う必要があるため、注意が必要です。

#### 整数型データの除算

前述したように整数型同士の除算では結果は整数になるため、小数点以下は切り捨てられます。この動きをもう少し詳しく見ていきましょう。まず以下のコードを見てください。

```java:snippet_4 (Main_4_1)
int x = 5 / 2;
```

`5 / 2`の除算結果は2.5ですが、この命令文を実行すると小数点以下が切り捨てられるため、変数xの値は2となります。
では以下のコードはどうでしょうか。

```java:snippet_5 (Main_4_1)
double d = 5 / 2;
```

直感的には、変数dに除算結果である2.5が格納されそうに思われますが、この命令文を実行すると変数dの値は2.0になります。これは`5 / 2`という整数型同士の除算が行われた時点ですでに結果は整数の2となっており、その値が変数dに代入されたためです。
そのため以下のコードようにdouble型変数に代入してから除算すれば、意図したとおりに計算結果は2.5になります。

```java:snippet_6 (Main_4_1)
double d1 = 5;
double d2 = 2;
double val = d1 / d2;
```

他の方法としては、`double val = (double) 5 / (double) 2`といった具合に、整数5と2をdouble型にキャストしてから除算しても、同じ結果（2.5）が得られます。

また浮動小数点型と整数型とが混在する除算は、結果は浮動小数点型になるため、以下のコードでは変数val1～val3の値はいずれも2.5になります。

```java:snippet_7 (Main_4_1)
double val1 = 5.0 / 2.0;
double val2 = 5.0 / 2;
double val3 = 5 / 2.0;
```

#### 算術演算とキャスト（縮小変換）

算術演算の結果をキャスト演算子によって縮小変換する場合は、キャスト対象となる範囲を意識する必要があります。
例えば以下のコードを見てください。

```java:snippet_8 (Main_4_1)
int x = 100;
int y = (int) x * 0.1; // コンパイルエラー
```

これは、コンパイルエラーになります。`x * 0.1`という式は、整数と浮動小数点数の演算なので、前述したように結果は浮動小数点数になります。このコードではxが100なので、`x * 0.1`という式の結果は浮動小数点数10.0です。このコードは一見すると、`x * 0.1`の結果である浮動小数点数10.0を、キャスト演算子`(int)`によってint型に縮小変換しているため、問題がないように見えるかもしれません。ところが実際には、キャスト演算子`(int)`の範囲は、直後に登場する変数xのみと見なされてしまいます。つまりキャストをしたところで、浮動小数点数10.0を直接int型変数に代入しようとしていることに変わりはないため、コンパイルエラーになるのです。
このような場合は、以下のようにキャストの範囲を`()`によって明示するようにしてください。

```java:snippet_9 (Main_4_1)
int y = (int) (x * 0.1);
```

このようにすれば、`x * 0.1`の結果である浮動小数点数10.0がint型に縮小変換され、変数yには整数10が格納されます。

#### インクリメント演算子・デクリメント演算子

`++`はオペランド（変数）に対して1を加算するための演算子で、インクリメント演算子とも呼ばれます。また`--`はオペランド（変数）に対して1を減算するための演算子で、デクリメント演算子とも呼ばれます。
例えばインクリメント演算子を変数iに用いる場合は、`++i`と記述します。これは`i = i + 1`と同義です。同様に`--i`は`i = i - 1`と同義です。
プログラムのロジックにおいて、変数に1を加算したり減算したりする処理は、高い頻度で登場します。そのような場合は、これらのインクリメント演算子やデクリメント演算子を用いるのが一般的です。

#### インクリメント演算子・デクリメント演算子の記法の違い

インクリメント演算子・デクリメント演算子は、`++i`といった具合に変数の前に演算子を記述しますが、`i++`といった具合に変数の後ろに記述することもできます。`++i`のような記法を前置記法、`i++`のような記法を後置記法と呼びます。
`++i`と`i++`は、オペランド（変数）に対して1を加算する、という点は同じです。両者の違いは、値を参照するタイミングと、加算するタイミングの前後関係にあります。
`int x = ++i`と記述する（前置記法）と、まず変数iに1を加算し、その後、変数iの値をxに代入します。一方`int x = i++`と記述する（後置記法）と、まず変数iの値をxに代入し、その後、変数iに1を加算します。

【図4-1-2】インクリメント演算子の前置記法と後置記法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/f04b8717-a839-c09c-52fd-b017159ab65a.png)

具体的な挙動は、以下のコードを見てください。

```java:snippet_10 (Main_4_1)
int i = 10;
int x = i++;
```

このコードを実行した時点で、変数x、i、それぞれの値はどうなっているでしょうか。ここでは後置記法が使われているため、まず変数iの値がxに代入され、その後iに1が加算されます。従って結果的には、xの値は10、iの値は11になります。

:::note warn
インクリメント演算子・デクリメント演算子は、非常に利用頻度の高い演算子です。ただし演算結果を直接参照する処理（変数への代入など）は、前置記法と後置記法による挙動の違いをしっかりと理解する必要があるため、特に注意が必要です。
:::

#### 文字列に対する＋演算子

`+`演算子は、数値型データの加算だけではなく、文字列型データの連結にも利用することができます。例えば以下のコードでは、文字列"Hello, "と"World!"が連結されるため、変数strには"Hello, World!"が格納されます。

```java:snippet_11 (Main_4_1)
String str = "Hello, " + "World!";
```

また文字列と文字列型以外のデータを`+`演算子によって連結する場合は、文字列以外のデータが自動的に文字列変換されます。
それでは以下のコードを見てください。

```java:snippet_12 (Main_4_1)
String str1 = "abc" + 100;
String str2 = 100 + "abc";
```

このようにすると、変数str1には"abc100"が、str2には"100abc"が、それぞれ格納されます。

なお`+`演算子を用いると、文字列と参照型変数を連結することもできます。このとき、参照型変数のtoString()メソッドが自動的に呼び出されます（チャプター13.1参照）。

### 4.1.3 代入演算子と比較演算子

#### 代入演算子の種類

代入演算子とは、右辺で指定した変数およびリテラルやそれらの演算結果を、左辺で指定した変数に代入するための演算子です。
代入演算子には、以下のような種類があります。

【表4-1-3】代入演算子の種類
|代入演算子|説明|具体例|
|--|--|--|
|=|代入|x = 30|
|+=|左辺と右辺を加算した結果を代入|x = 30; x += 10 ⇒ xは40|
|-=|左辺から右辺を減算した結果を代入|x = 30; x -= 10 ⇒ xは20|
|*=|左辺と右辺を乗算した結果を代入|x = 15; x *= 3 ⇒ xは45|
|/=|左辺から右辺を除算した結果を代入|x = 15; x /= 3 ⇒ xは5|
|%=|左辺から右辺を除算した余りを代入|x = 20; x %= 9 ⇒ xは2|
|&=|論理積の結果を代入|レッスン4.1.4参照|
|&#124;=|論理和の結果を代入|レッスン4.1.4参照|
|^=|排他的論理和の結果を代入|レッスン4.1.4参照|
|<<=|ビット演算（左シフト）の結果を代入|レッスン4.1.5参照|
|>>=|ビット演算（符号なし右シフト）の結果を代入|レッスン4.1.5参照|
|>>>=|ビット演算（符号あり右シフト）の結果を代入|レッスン4.1.5参照|

これまで何度も登場した`=`は、代表的な代入演算子の1つです。
また`+=`は、左辺と右辺を加算した結果を代入するためのものです。以下に具体例を示します。

```java:snippet_13 (Main_4_1)
int x = 30;
x += 10;
```

変数xにはもともと30が格納されていますが、このようにすると30に対して10が加算され、加算後の40が代入されます。

#### 比較演算子の種類

比較演算子とは、左辺と右辺の値を比較し、その判定結果を論理値（trueまたはfalse）として返すための演算子です。比較演算子は、条件分岐やループといった制御構文（チャプター6.1～6.3参照）において、条件式を表すために使用します。
比較演算子には、以下のような種類があります。

【表4-1-4】比較演算子の種類
|比較演算子|説明|
|--|--|
|==|左辺と右辺の同一性を判定する（同一の場合にtrue）|
|!=|左辺と右辺の同一性を判定する（同一でない場合にtrue）|
|<|左辺と右辺の大小を判定する（左辺が右辺より小さい場合にtrue）|
|>|左辺と右辺の大小を判定する（左辺が右辺より大きい場合にtrue）|
|<=|左辺と右辺の大小を判定する（左辺が右辺以下の場合にtrue）|
|>=|左辺と右辺の大小を判定する（左辺が右辺以上の場合にtrue）|
|?:|三項演算子（レッスン6.2.5参照）|

#### 同一性判定を行う比較演算子

この中でまず`==`や`!=`は、左辺と右辺の値の同一性を判定するために使用します。`==`は左辺と右辺が同一の場合にtrueが、同一ではない場合にfalseが返ります。一方`!=`は左辺と右辺が同一ではない場合にtrueが、同一の場合にfalseが返ります。
それではコードで確認してみましょう。

```java:snippet_14 (Main_4_1)
int x = 10, y = 15;
boolean flag1 = y == x + 5; // trueが返る
boolean flag2 = x == y; // falseが返る
boolean flag3 = x != y; // trueが返る
```

このように比較演算子の`==`や`!=`は、左辺と右辺の値の同一性を判定するために使用します。
なお上の例のように、プリミティブ型変数同士の場合は、「同じ値であるかどうか」が判定されます。一方で参照型変数に対して`==`や`!=`を使う場合は、「同じインスタンスを参照しているか」という意味になるので注意が必要です。

:::note info
参照型変数には同一性と等価性という概念があり、両者の違いを正しく理解する必要がありますが、詳細はチャプター13.1で説明します。
:::

#### 文字列の値が同じであることの判定

ここでは「文字列の値が同じであること」を判定するための方法を説明します。このテーマについては、前述した「参照型変数における同一性と等価性の違い」を踏まえた説明が必要ですが、ここではコース構成上の都合により、事前に簡単な説明をしておきます。
「文字列の値が同じであること」を判定するためには、`==`演算子ではなく、Stringクラスのequals()メソッドを使用します。String型変数strの値が"foo"であるかどうかを判定する場合、`if (str == "foo")`と実装してもコンパイルエラーにはなりませんが、正しい判定ができない可能性があります。ここでの目的に応じた判定をするためには、`if (str.equals("foo"))`と記述する必要があります。

#### 大小判定を行う比較演算子

次に大小判定を行うための演算子です。`< `、 `<= `、 `> `、 `>= `は、左辺と右辺の大小関係を比較するために使用します。
それではコードで確認してみましょう。

```java:snippet_15 (Main_4_1)
int x = 10, y = 15;
boolean flag1 = x < y; // trueが返る
```

#### 三項演算子

三項演算子とは `条件式 ? 式1 : 式2 `という、3つのオペランドを取る特殊な演算子です。この演算子は、条件判定によって変数に代入する値を切り替えたい場合に使用しますが、if文の簡略的な記法と見なすこともできます。
三項演算子についてはチャプター6.2にて取り上げますので、ここでは割愛します。

### 4.1.4 論理演算子

#### 論理演算子の種類

論理演算子とは、複数の条件式や論理値に対して様々な論理演算を行い、その結果を論理値（trueまたはfalse）として返すための演算子です。論理演算子は、条件分岐や繰り返しといった制御構文において、比較演算子と組み合わされて、分岐や繰り返しを判定するために使用します。
論理演算子には、以下のような種類があります。

【表4-1-5】論理演算子の種類
|論理演算子|説明|
|--|--|
|&&|論理積（左辺と右辺がともにtrueの場合にtrue）|
|&|論理積（左辺と右辺がともにtrueの場合にtrue）|
|&#124;&#124;|論理和（左辺と右辺のいずれかがtrueの場合にtrue）|
|&#124;|論理和（左辺と右辺がいずれかがtrueの場合にtrue）|
|!|否定（式がtrueの場合はfalse、falseの場合はtrue）|
|^|排他的論理和（左辺と右辺が「trueとfalse」の組み合わせになった場合にtrue）|

論理積、論理和、排他的論理和をベン図で表すと、以下のようになります。

【図4-1-3】論理演算子とベン図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/dbd4a49c-23ce-b28b-2e1e-4723962cf8f1.png)

論理積は「AND条件」とも言われますが、2つの命題がともに真だったときにはじめて真になる、という論理演算です。また論理和は「OR条件」とも言われますが、2つの命題のうちどちらか片方でも真であれば演算結果も真になる、という論理演算です。最後に排他的論理和とは、2つの命題が異なる場合、つまり「真と偽の組み合わせ」のときに真になる、という論理演算です。

#### 論理積

論理演算子を順番に見ていきましょう。
まず`&&`および`&`は、論理積を表します。つまり左辺と右辺の条件式がともにtrueだった場合に、trueを返します。具体的には以下のコードを見てください。

```java:snippet_16 (Main_4_1)
int x = 10;
boolean flag = (x <= 15) && (x % 2 == 0); // trueが返る
```

`&&`の左辺、右辺がともにtrueになるため、この論理演算の結果はtrueになります。なおこのコードでは、`&&`の左右の条件式を分かりやすいように`( )`で囲っていますが、`( )`がなくても同様の結果になります。

#### 論理和

次に`||`および`|`は、論理和を表します。
つまり左辺と右辺の条件式のいずれかがtrueだった場合に、trueを返します。具体的には以下のコードを見てください。

```java:snippet_17 (Main_4_1)
int x = 20;
boolean flag = (x <= 15) || (x % 2 == 0); // trueが返る
```

`||`の左辺はfalseですが、右辺がtrueのため、この論理演算の結果はtrueになります。

#### 否定

次に`!`（エクスクラメーションマーク）は、直後の条件式に対する否定を表します。つまり条件式がfalseの場合はtrueを、条件式がtrueの場合はfalseを返します。
コードで見ていきましょう。

```java:snippet_18 (Main_4_1)
int x = 10;
boolean flag = ! (x == 20);
```

このコードでは、`x == 20`はfalseになりますが、それが否定されるため、変数flagにはtrueが格納されます。なお`!`の直後が単一のboolean変数の場合は`( )`は不要ですが、このコードのように式を記述する場合は、否定の範囲を`( )`で示す必要があります。

#### 否定とド・モルガンの法則

否定は、論理積や論理和と組み合わせて使用するケースが多々あります。このとき論理和、論理積、否定の間に成り立つ規則性を、ド・モルガンの法則と言います。
例えば2つの旗、旗1と旗2があるものとします。
まず「旗1が赤、かつ、旗2も赤」という状態の否定は、論理積と否定を組み合わせて`! (旗1 == 赤 && 旗2 == 赤)`という条件式になります。これは論理和と否定を組み合わせた`(! 旗1 == 赤) || (! 旗2 == 赤)`という条件式と、同義になります。
また「旗1が赤、または、旗2が赤」という状態の否定は、論理和と否定を組み合わせて`! (旗1 == 赤 || 旗2 == 赤)`という条件式になります。これは論理積と否定を組み合わせた`(! 旗1 == 赤) && (! 旗2 == 赤)`という条件式と、同義です。

#### 排他的論理和

最後に`^`（キャレット）は排他的論理和を表します。すなわち左辺と右辺が「trueとfalse」の組み合わせになった場合に、trueを返します。それではコードで確認してみましょう。

```java:snippet_19 (Main_4_1)
int x = 20;
boolean flag = x <= 15 ^ x % 2 == 0;
```

このコードでは「x = 20」ですが、その場合`^`の左辺はfalseになり、逆に右辺はtrueになるため、この論理演算の結果はtrueになります。また仮に「x = 10」だとすると、`^`の左辺も右辺もtrueになるため、この論理演算の結果はfalseになります。

#### 論理演算子の短絡評価

論理演算子の短絡評価とは、左辺の式のみを評価するだけで、論理演算が確定する場合は右辺の評価は行わない、という処理を指します。すでに登場した演算子のうち、`&&`と`||`が短絡評価を行う演算子です。
まず論理積の短絡評価をコードで確認してみましょう。

```java:snippet_20 (Main_4_1)
int x = 20;
boolean flag = (x <= 15) && (x % 2 == 0); // falseが返る
```

このコードでは、論理演算子`&&`の左辺の式を評価するとfalseになり、この時点でこの論理演算の結果はfalseであることが確定するため、右辺の評価は行われません。

次に論理和の短絡評価です。以下のコードを見てください。

```java:snippet_21 (Main_4_1)
int x = 10;
boolean flag = (x <= 15) || (x % 2 == 0); // trueが返る
```

この例では論理演算子`||`の左辺の式を評価するとtrueになり、この時点でこの論理演算の結果はtrueであることが確定するため、右辺の評価は行われません。
論理演算子を使用する場合は、特別な理由がない限りは、短絡評価（`&`ではなく`&&`、`|`ではなく`||`）を選択して問題ないでしょう。

### 4.1.5 ビット演算子

#### ビット演算子の種類

ビット演算子とは文字通り、ビット演算を行うための演算子です。ビット演算とは、演算対象となる数値データをビット列、すなわち2進数の0と1の列とみなして、ビット単位の論理演算やシフト演算を行うことです。
ビット演算子には、以下のような種類があります。

【表4-1-6】ビット演算子の種類
|ビット演算子|説明|具体例|
|--|--|--|
|&|論理積|12 & 5 ⇒ 4|
|&#124;|論理和|12 &#124; 5 ⇒ 13|
|^|排他的論理和|12 ^ 5 ⇒ 9|
|~|否定|~4 ⇒ -5|
|<<|左シフト|13 >> 2 ⇒ 3|
|>>|符号なしの右シフト|13 >>> 2 ⇒ 3|
|>>>|符号ありの右シフト|-77 >>> 2 ⇒ -20|

ただし通常のJavaによるアプリケーション開発では、ビット演算を使用するケースは極めて限定的なため、本コースでは代表的な機能の紹介に留めます。

#### ビット論理演算

ビット論理演算には、論理積、論理和、否定などがありますが、ここでは論理積と論理和を取り上げます。
まず`&`は、論理積を求めるための演算子です。ビットの論理積とは桁ごとに2つのビットを評価し、「ともに1だった場合に1、それ以外は0」という演算です。
例えば`12 & 5`という論理演算では、12を表すビット列1100と、5を表すビット列0101の論理積が求められ、演算結果は0100、すなわち4になります。
次に`|`は、論理和を求めるための演算子です。ビットの論理和とは桁ごとに2つのビットを評価し、「どちらか一つでも1だった場合に1、それ以外は0」という演算です。
例えば`12 | 5`という論理演算では、ビット列1100と0101の論理和が求められ、演算結果は1101、すなわち13になります。

#### ビットシフト演算

ビットシフト演算には左シフトと右シフトがあり、さらに右シフトは、符号なしと符号ありの2つに分類されます。
ここでは2種類の右シフトを取り上げます。
まず`>>`は、符号なしの右シフトです。例えば`13 >> 2`という論理演算は、「13を表すビット列00001101のビットを右に2つシフトさせる」という意味になります。このときシフトによって左側に生じた空きビットは、0で埋められます。従ってこの演算結果は00000011、すなわち3になります。

【図4-1-4】符号なしの右シフト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/b726ed71-eaeb-46d8-3422-05df7de8ceda.png)

次に`>>>`ですが、これは符号ありの右シフトです。`>>>`の`>>`との違いは「シフトさせたときに最上位のビットを符号として維持するかどうか」という点にあるため、正の数値を演算する場合は両者に違いは生じません。一方、負の数値の場合は両者に違いが生じます。整数型ではチャプター3.1で触れたように、負の値は「2の補数」によって表されます。例えばbyte型変数の場合、-77のビット列は10110011なので、`-77 >>> 2`という論理演算は「ビット列10110011に対してビットを右に2つシフトさせ、そのとき最上位の符号ビットを使って空きビットを埋める」という意味です。従ってこの演算結果のビット列は11101100になり、これはbyte型変数では-20になります。

【図4-1-5】符号ありの右シフト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/47b3f3d2-8909-3bd3-4748-7ebd163324b0.png)

### このチャプターで学んだこと

このチャプターでは、以下のことを学びました。

1. 式は、演算子とオペランドによって構成されること。
1. 演算子には、算術演算子、代入演算子、比較演算子、論理演算子、ビット演算子、という種類があること。
1. 演算子には、優先順位が決められていること。
1. 算術演算では、整数型と浮動小数点型との演算や、整数型の除算において、特に注意が必要であること。
1. インクリメント演算子・デクリメント演算子の機能と、前置記法・後置記法の違いについて。
1. 代入演算子と比較演算子の種類や特徴について。
1. 論理演算子の特徴や、ド・モルガンの法則、短絡評価の意味について。
1. ビット演算子の種類や特徴、ビットシフト演算の処理について。