Print Friendly, PDF & Email

新人エンジニアが最初に知っておきたい演算子の使い方

なぜ、演算子が重要なのか、その理由。

この記事では、弊社の新人エンジニア研修の参考にJava8を解説します。

前回は変数とデータ型について解説しました。

今回は演算子を解説します。

Javaには様々な演算子がありますが、ここではその中でも

・算術演算子
・キャスト演算子

を解説します。

・関係演算子
・条件演算子
・三項演算子

については、次回の4.条件分岐と判定条件でお話しします。

1.算術演算子

四則演算(+-×÷)などをする演算子を算術演算子といいます。

一例として、Javaで足し算をする場合を見てみましょう。

package chap03;

public class Example01 {

    public static void main(String[] args) {
        System.out.println(1 + 2);
    }
}

このプログラムを実行すると標準出力には「3」と出力されます。

この時の、「+」記号を演算子(オペレータ)と呼び、2や3のことをオペランドと呼びます。

また、「1 + 2」 は3という値を持つため式と呼ばれます。

さらに、 System.out.println(1 + 2);のように;(セミコロン)までを文というのでしたね。

演算子自体はいろいろな種類がありますが、この場合の「+記号」は足し算を意味するので特に算術演算子といいます。

ここで、Javaの算術演算子をまとめましょう。

算術演算子演算内容式の例結果(値)
+足し算1 + 23
-引き算1 - 2-1
*掛け算2 * 36
/割り算5 / 2
%剰余(余りを求める)5 % 21

ここで、5 / 2 = 2.5 ではなく、2となることに注目してください。

整数同士の演算では結果も整数になるからです。

小数点以下は切り捨てられるわけです。

また、数学でも掛け算と割り算(そして剰余)は、足し算と引き算より優先され先に計算されました。Javaでも同じです。

そのため

System.out.println(1 + 5 % 2);

の結果は、2になります。

()を使って以下のように優先順位を変更してみましょう。

System.out.println((1 + 5) % 2);

上記の結果は、0になります。

2.変数を含む式

式には変数を含めることもできます。

以下のプログラムは2から順に5まで1つづ増やした数を表示します。

package chap03;

public class Example02 {

    public static void main(String[] args) {
        int i = 1;
        int j = i + 1;
        System.out.println(j);

        j = j + 1;
        System.out.println(j);

        System.out.println(j += 1); //短縮表記の例1

        System.out.println(++j); //短縮表記の例2

        System.out.println(j++); //短縮表記の例2

        System.out.println(j);
    }
}

<結果を表示>

2
3
4
5
5
6


間違えやすいので繰り返しですが、上記の

int j = i + 1;

という式は数学の左辺と右辺が等しいという意味ではありません。

は変数jにi+1という式の値を代入するという意味です。

=は代入を意味するということは新人エンジニアのみなさんが間違えやすいところなので気をつけましょう。

ちなみに等しいは「==」で表すということをこのあとすぐ学びます。

また、上記のように変数を使った式は短縮表記も可能です。

j += 1

複合代入演算子といいます。

複合代入演算の作り方は以下の通りです。

複合代入演算子の書き方
複合代入演算子の書き方

以下に加算以外の例を示します。

number -= 2; 
number *= 2; 
number /= 2; 
number %= 2; 

変数名が長くなれば短縮効果が効いてくる書き方です。

少し練習してみましょう。

通常の書き方複合代入演算子を使った書き方値(numberは2で初期化されているものとする)
number = number - 3;number -= 3; -1
number = number * 3;number *= 3; 6
number = number / 3;number /= 3; 0
number = number % 3;number %= 3; 2

※答えは隠し文字です。空欄をドラッグして下さい。

また、短縮表記の例2のような書き方で1増やす処理をインクリメントといいます。

さらに、1減らすデクリメントというものもあります。

(例:--j)

インクリメント、デクリメントにはオペランドに対してどこに書かれるかによって前置と後置があります。

前置は、式の中でオペランドの値は増やされたり減らされたりした“後”の値が用いられます。

後置は、式の中でオペランドの値は増やされたり減らされたりする“前”の値が用いられます。

例えば、上記の短縮表記の例2において

System.out.println(j++); //表示結果は5のまま
System.out.println(j); //1インクリメントされた6が表示される

ということになります。

なお、

i++;
++i;

のように単独で使った場合は前置、後置は同じ結果になります。

3.変数の型と代入の制限

前回、変数には型があって入れられる数値の範囲が違うということを学びました。

では、例えばdouble型の変数にint型の整数を入れるとどうなるでしょうか?

また、その逆はどうでしょうか?

やってみましょう。

package chap03;

public class Example03 {

    public static void main(String[] args) {
        double d = 1;
        System.out.println(d);
    }
}

<結果を表示>

1.0

エラーにはなりませんでした。

これを暗黙的な型変換といいます。

「大は小を兼ねる」ということで、より大きな型への代入は暗黙の型変換がされます

しかし、以下のようなプログラムはエラーになります。

package chap03;

public class Example04 {

    public static void main(String[] args) {
        int i = 3.14;
        System.out.println(i);
    }
}

<結果を表示>

(中略)- 不適合な型: 精度が失われる可能性があるdoubleからintへの変換

このように精度が失われる可能性のある代入はできません。

しかし、もし、プログラマーが精度が失われても構わないと考えた場合にも代入できないとすると不都合です。

それを可能にするのがキャスト(cast)演算子です。

4.キャスト演算

より小さな型への代入を可能にするキャスト演算は()「丸カッコ」を使います

package chap03;

public class Example05 {

    public static void main(String[] args) {
        int i = (int) 3.14;
        System.out.println(i);
    }
}

今回は3と表示されました。

このような演算をキャスト演算または型変換と呼びます。

よく、映画などで俳優のキャスティング(casting)という言い方をします。

新人エンジニア研修でキャストを映画の例えで説明

悪役にキャスティングされた俳優は悪役としてふるまい、ヒーローにキャスティングされたらヒーローとしてふるまう。

違った型としてふるまうように指定するのがこのキャスト演算です。

あとでオブジェクトのキャストという応用のお話も出てきますので、しっかり押さえてください。

では、例えば、異なる型の変数や値が混在している演算の結果はどうなるでしょうか?

答えは、最も大きい型に統一された計算結果になります。

package chap03;

public class Example06 {

    public static void main(String[] args) {
        int i = 1;
        double d = 3.1;
        System.out.println(i + d);
    }
}

<結果を表示>

4.1

intとdoubleの算術演算はdouble型の結果になりました。

ここで新人エンジニアの皆さんが気を付けたいのは整数同士の割り算です。

System.out.println(5 / 2);

int同士の割り算の結果は「2」になりました。

もしも、2.5と表示させたいのであれば、どちらかのオペランドをdoubleにキャストする必要があります。

例えばこんな風に、

System.out.println(5 / (double)2);(中略)- 不適合な型: 精度が失われる可能性があるdoubleからintへの変換

です。

以下に暗黙の型変換といってキャストが必要ない場合とキャストが必要な場合を図にまとめています。

上の型から下の型への代入には(地球の重力に引かれるように)暗黙の型変換が働きますからキャストは不要です。

しかし、下から上の型への代入にはキャストが必要です。

暗黙の型変換のルール
暗黙の型変換のルール

なお、上記の図の横幅はビット数をイメージしています。

char型が独自の位置を占めていますね。

同じビット数のはずのchar型とshort型の間で暗黙の型変換が働かないのはなぜだか分かりますか?

char型にはマイナスが無かったこと(unsigned)を思い出してください。

なぜ、ビット数の少ないfloat型がlong型を受け入れられるのかは、float型が指数を生かした浮動小数点表現だったことを思い出してください。

5.ArithmeticException

以下のように割る数を0にしたらどうなるでしょうか?

package chap03;

public class Example07 {

    public static void main(String[] args) {
        System.out.println(5 / 0);
    }
}

<結果を表示>

ArithmeticException: / by zero

と例外(Exception)が表示されます。

0で割った結果は数学上未定義ですので、こうなります。

どうか例外を嫌いにならないで下さい。

例外表示は皆さんの味方です。

例えば、Java言語の先祖にあたるC言語では0除算の結果は文字通り未定義です。

未定義というのは、実行時のメモリの状況により異常停止したり意味不明の結果が出力されたりといった事が起こるのです。

しかし、Javaではコンパイラが実行前に教えてくれるのです。

例外は新人エンジニアの皆さんの味方です。

もちろん、意図的に0で割る計算をすることはないでしょう。

しかし、割る数が変数ですと意図せず0で割ってしまうこともあります。

そんな時は、「もしも、割る数が0だったら処理をしない」といった条件分岐や、エラーが発生しても処理を止めない例外処理といったことが必要になります。

この点は後述します。

6.文字列の結合に使用する「+」

文字列はString型の変数に代入できます。

package chap03;

public class Example08 {

    public static void main(String[] args) {
        String str = "Hello World";
        System.out.println(str);
    }
}

文字列は別の章で詳しく学びます。

また、文字列を連結するには「+」演算子を使います。

package chap03;

public class Example09 {

    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = " World";
        System.out.println(str1 + str2);
    }
}

<結果を表示>

Hello World

しかし、「+」演算子は足し算でも使いましたね。

文字列と数値が混在する場合はどうなるでしょうか?

package chap03;

public class Example10 {

    public static void main(String[] args) {
        System.out.println("1 + 2 = " + 1 + 2);
        System.out.println(1 + 2 + "は 1 + 2 の答えです");
    }
}

<結果を表示>

1 + 2 = 12
3は 1 + 2 の答えです


左から順番に結合されています。

算術演算子は左結合
算術演算子は左結合

算術演算子は左結合というルールがあります

そのため、文字列に連結された時点で全体が文字列と評価されるので上記の結果になるのです。

文字列と算術演算が混在する+演算には注意が必要です。

更に新人エンジニアの皆さんには少々応用的な知識として文字列を+で結合することはパフォーマンスが悪いことにも注意しましょう。

7.文字と文字列の扱いで詳しくお話ししますが、ここでも簡単に触れておくと文字列は1度生成すると内部の文字列を変更できません。

そのため文字列を連結する時には新しい文字列が生成されるのです。

数回の結合であれば問題になりませんが、何千何万回となると影響があります。

そのような場合にはStringBuilderクラスまたは、StringBufferクラスのappendメソッドの使用を推奨します。

今回はJavaの演算子について見てきました。

次回は、条件分岐と判定条件を学んでプログラムに様々な判断をさせてみましょう。

<まとめ:隣の人に正しく説明できたらチェックを付けましょう>

□算術演算子は+ - * / % の5種類である

□=は代入を意味する

□より大きな型への代入は暗黙の型変換がされ、より小さな型への代入にはキャストが必要である

□算術演算子は左結合というルールがあるため文字列と算術演算が混在する標準出力には注意が必要である

まとめができたら、アウトプットとして演習問題にチャレンジしましょう。

問題3.変数と演算子

以下のプログラムを作成しなさい。 コンピュータはもともと数値計算を楽にするために開発されました。そういう意味で計算は最もコンピュータが得意なことです。ここではい…

【今回の復習Youtube】
 
 

JavaSE8の解説に戻る

最後までお読みいただきありがとうございました。

新人エンジニア研修のプログラムを見てみる

当社はJava講師を募集中です(サブ講師のため未経験者可)