Javaに置ける&,&&,|,||,a++,++aの違いについて

f:id:hira98:20190515125543p:plain

【はじめに】

後述のJavaソースを実行すると、タイトル通りの実行結果になります。

この説明を聞いて「当然だぜ😤」と言う方はこの記事を読む必要はありません。

「可読性が悪い💩コードだなー」と思った方は過去の私と同じです。

私たち初心者にとっては、💩コードに見えるかもしれません。

しかし、ベテランエンジニアからすると「これくらい知っとけよ!!それでもプロかよ!!」と、お叱りを受ける可能性があります。

お叱りを受けないために、この記事を読んで脱💩コードしましょう。

ソースを分解する

上記ソースを見た初心者が、💩コードと思ってしまう要因は、6から25行目のswitch文です。

ここがなければ、単純なループなので読み解くのは簡単です。

//6から25行目のswitchをコメントアウトした時の実行結果
 パターン1 a:10 b:20
 パターン2 a:10 b:20
 パターン3 a:10 b:20
 パターン4 a:10 b:20
 パターン5 a:10 b:20
 パターン6 a:10 b:20

初心者が💩コードを読み解くには、次の3つの違いを理解する必要があります。

  • &&&の違い

  • |||の違い

  • 変数int aに対するa++++aの違い

この違いについて、以降で説明していきます。

&&&の違い

&&&はどちらもAND演算子です。

AND演算子は2つの条件を比較し、両方ともtrueの時だけtrueを返す演算子です。

主にif文で複数条件を判定したい時に使用されます。

真理値表(条件1、2のパターンとそれに対する結果を網羅した表)に表すと、次のようになります。

条件1 条件2 結果
true true true
true false false
false false false
false false false

ここで注目すべきは、条件1がfalseの時の結果は必ずfalseになっているということです。

「条件1だけで結果が分かるなら、条件2の判定をする必要なくない🤔」

「ただ、条件1で結果が分かっても、条件2も判定して欲しい人もいるよな🤔」

と考えた言語開発者が用意した実装方法。それが&&&を使い分ける方法です。

判定処理の詳細は次の通りです。

/*
"&"を使った場合の判定処理
1)条件1の判定を行う
2)条件2の判定を行う
3)条件1と条件2がtrueの時だけ"OK"と出力する。
*/
if(条件1 & 条件2) {
  //OK出力処理
}

/*
"&&"を使った場合の判定処理
1)条件1の判定を行う。
2)条件1がfalseの時は、条件2の判定を行わずに処理終了。
3)条件1がtrueの時は、条件2を判定しtrueだったら、OKと出力する。
*/
if(条件1 && 条件2) {
  //OK出力処理
}

|||の違い

「|」と「||」はどちらもOR演算子です。

OR演算子とは2つの条件を比較し、どちらかが条件を満たす時だけtrueを返します。

真理値表に表すと次のようになります。

条件1 条件2 結果
true true true
true false true
false false true
false false false

ここで注目すべきは、条件1がtrueの時の結果は必ずtrueになっているということです。

AND演算子同様に

「条件1だけで結果が分かるなら、条件2の判定をする必要なくない🤔」

「ただ、条件1で結果が分かっても、条件2も判定して欲しい人もいるよな🤔」

と考えた言語開発者が用意した実装方法。それが|||を使い分ける方法です。

判定処理の詳細は次の通りです。

/*
"|"を使った場合の判定処理
1)条件1の判定を行う
2)条件2の判定を行う
3)条件1と条件2のどちらかがtrueの時は"OK"と出力する。
*/
if(条件1 | 条件2) {
  //OK出力処理
}

/*
"||"を使った場合の判定処理
1)条件1の判定を行う
2)条件1がtrueの時は、条件2の判定を行わずに"OK"と出力する。
3)条件1がfalseの時は、条件2を判定しtrueだったら、"OK"と出力する。
*/
if(条件1 && 条件2) {
  //OK出力処理
}

変数int aに対するa++++aの違い

まずはa++++aの共通の部分について説明します。

次のソースでは変数a、b、c、dに対して同じ処理をしています。

int a=0, b=0, c=0, d=0; 
a = a + 1;
b += 1;
c++;
++d

// 変数a,b,c,dを出力
System.out.printf("%d %d %d %d\n", a, b, c, d);

/*
実行結果
1 1 1 1
*/

ここから分かる通り、a++++aは変数aに対して1を足しています。

では両者の違いは何かというと、「変数aの値を読みだした後に1を足すか、1を足してから変数aの値を読みだすか?」の違いです。ソースで表すと次のようになります。

int a=0, b=0;
// a++の確認
System.out.printf("a1:%d\n", a++); // 変数aを出力
System.out.printf("a2:%d\n", a); // 変数aを出力

// ++bの確認
System.out.printf("b1:%d\n", ++b); // 変数bを出力
System.out.printf("b2:%d\n", b);   // 変数bを出力

/*
実行結果
a1:0
a2:1
b1:1
b2:1
*/

「a1:」出力時のa++はaに格納された値を出力した後にaに1を足しているため、「a2:」のaでは1が出力されます。

「b1:」出力時の++bはbに1を足した後に、bに格納された値を出力しています。よって、「b1:」「b2:」で出力されるbの値は同じになります。

因みに、足し算があるなら当然のように引き算を行うための書き方もあります。

int a = 1;
a = a - 1;
a -= 1;
a--;
--a;

// 変数a,b,c,dを出力
System.out.printf("%d %d %d %d\n", a, b, c, d);

/*
実行結果
0 0 0 0
*/

因みに、a----aの違いは「変数aの値を読みだした後に1を引くか、1を引いてから変数aの値を読みだすか?」になります。

最後に

脱💩コードは出来たでしょうか。

「よし、これで私も脱初心者だ🎉」

と思った方は甘いです💩

Java SE8 Silver」は、初心者が💩コードと思うようなソースのバーゲンセール状態なんです🤮