Java じゃんけんゲームを作ってみる ~基本文法をマスターする~

じゃんけんゲーム

Javaプログラミングの基本文法を理解するためにも、実際にアプリケーションを作ってみるのが手っ取り早い方法です。

教科書などを眺めても、実践に勝る学習はありません。つまりは。。。

経験に勝る知識なし!

ということです。

じゃんけんゲームの処理内容

本来は、自分で考えて仕様を考えるべきですが、初めの一歩ということで使用を提示します。

作成するクラスは「JankenPon」クラスにします。

<じゃんけんゲームの仕様>

  1. 標準入力での、0:グー、1:チョキ、2:パーと定義する
  2. ユーザーの手(入力)とCPUの手(乱数)を表示する
  3. 勝敗判定を行い、「YOU_WIN」か「YOU_LOSE」「DRAW」を表示する

この様に使用を決めたらそれぞれの項目(要件)を満たすようにプログラムを作ります。

0:グー、1:チョキ、2:パーと定義する

標準入力を受け取りグー~パーを判定します。
どのように実装したらよいでしょうか?

今回は、試しに以下のような実装をしてみましょう。

if文をマスターする

マスターするといっても、普通に使うだけですが。。。

Scanner scan = new Scanner(System.in);
int input = Integer.parseInt(scan.nextLine());
String jankenTe = null;
if (input == 0) {
    jankenTe = "グー";
} else if (input == 1) {
    jankenTe = "チョキ";
} else if (input == 2) {
    jankenTe = "パー";
} else {
    System.out.println("想定外の値です。" + input);
}

じゃんけんの手をString型の変数JankenTeに設定(代入)します。
0, 1, 2以外の値が入力されたときは想定外の値です。

ユーザーの手(入力)とCPUの手(乱数)を表示する

CPUの手を乱数を使って表示します。これはもう説明する必要はないと思います。

// 0-2の乱数を生成する
cpuTe = String.valueOf(new Random().nextInt(2));

if (cpuTe.equals("0")) {
    jankenCpu = "グー";
} else if (cpuTe.equals("1")) {
    jankenCpu = "チョキ";
} else if (cpuTe.equals("2")) {
    jankenCpu = "パー";
}

これも、if文で実装することができます。もちろん、より良いアイディアがあればそちらの実装を行うのが正しい判断です。検証するのを忘れないようにしてください。

勝敗判定を行い、「YOU_WIN」か「YOU_LOSE」「DRAW」を表示する

勝敗判定は、ちょっと良いアイディアが出ず。。。そのまま判定処理を作りました。
はっきり言ってダメダメなコードです。

String hantei = input + cpuTe;
String result = null;
if (hantei.equals("01")) {
    result = "YOU_WIN";
} else if (hantei.equals("12")) {
    result = "YOU_WIN";
} else if (hantei.equals("20")) {
    result = "YOU_WIN";
} else if (hantei.equals("00")) {
    result = "DRAW";
} else if (hantei.equals("11")) {
    result = "DRAW";
} else if (hantei.equals("22")) {
    result = "DRAW";
} else if (hantei.equals("02")) {
    result = "YOU_LOSE";
} else if (hantei.equals("10")) {
    result = "YOU_LOSE";
} else if (hantei.equals("21")) {
    result = "YOU_LOSE";
} else {
    System.out.println("想定外の値です。" + hantei);
}

何とかじゃんけんゲームができました。しかし、このようなプログラムは美しくありません。

別に「アーティスチックでないからダメ」といっているわけではなく、見ずらいしわかりずらい。

人にやさしくないプログラムだということです。

人にやさしく

ズバリ、読みやすく、理解しやすいコードが良いブログラムです。もちろん、余計なメモリを使わないとかいろいろありますが。。。

ちなみに、上のようなコードで作成したじゃんけんゲームは以下のようなコードになりました。

public static void main(String[] args) {
    // 1.初めの処理
    System.out.println("じゃんけん ...");
    Scanner scan = new Scanner(System.in);

    // 2.標準入力受付
    String input = scan.nextLine();
    String jankenTe = null;

    // 3.ユーザーの手を判定する
    if (input.equals("0")) {
        jankenTe = "グー";
    } else if (input.equals("1")) {
        jankenTe = "チョキ";
    } else if (input.equals("2")) {
        jankenTe = "パー";
    } else {
        System.out.println("想定外の値です。" + input);
    }

    String cpuTe = null;
    String jankenCpu = null;
    if (jankenTe == null) {
        // 強制終了
        System.exit(-1);
    } else {
        // 4.CPUの手を判定する
        cpuTe = String.valueOf(new Random().nextInt(2));

        if (cpuTe.equals("0")) {
            jankenCpu = "グー";
        } else if (cpuTe.equals("1")) {
            jankenCpu = "チョキ";
        } else if (cpuTe.equals("2")) {
            jankenCpu = "パー";
        }
    }
    System.out.println("ポン");
    System.out.println("あなた: " + jankenTe + " CPU; " + jankenCpu);

    // 5.勝敗判定を行う
    String hantei = input + cpuTe;
    String result = null;
    if (hantei.equals("01")) {
        result = "YOU_WIN";
    } else if (hantei.equals("12")) {
        result = "YOU_WIN";
    } else if (hantei.equals("20")) {
        result = "YOU_WIN";
    } else if (hantei.equals("00")) {
        result = "DRAW";
    } else if (hantei.equals("11")) {
        result = "DRAW";
    } else if (hantei.equals("22")) {
        result = "DRAW";
    } else if (hantei.equals("02")) {
        result = "YOU_LOSE";
    } else if (hantei.equals("10")) {
        result = "YOU_LOSE";
    } else if (hantei.equals("21")) {
        result = "YOU_LOSE";
    } else {
        System.out.println("想定外の値です。" + hantei);
    }
    // 6. 結果の表示
    System.out.println(hantei);
    System.out.println(result);
}

しかし、やはりだめなコード(個人的にそのように思う)なので、これをまともなコードに直します。

この様な行為のことをリファクタリングといいます。

リファクタリング

まずは、読みずらいところを洗い出します。
以下の部分が読みずらいと思いました。

1.if文のネスト(階層化しているところ)が無駄なネストになっている

String cpuTe = null;
String jankenCpu = null;
if (jankenTe == null) {
    // 強制終了
    System.exit(-1);
} else {
    // 4.CPUの手を判定する
    cpuTe = String.valueOf(new Random().nextInt(2));

    if (cpuTe.equals("0")) {
        jankenCpu = "グー";
    } else if (cpuTe.equals("1")) {
        jankenCpu = "チョキ";
    } else if (cpuTe.equals("2")) {
        jankenCpu = "パー";
    }
}

どこが、無駄かというとelse~の部分です。もしjannkenTeがnullになっているのならば、プログラムを強制終了するので、if-elseでわける意味がありません。無駄なコードになっているのです。

ではどのようになおすか?ズバリ下のように直します。elseが丸まる必要ないのです。

String cpuTe = null;
String jankenCpu = null;
if (jankenTe == null) {
    // 強制終了
    System.exit(-1);
}

// 4.CPUの手を判定する
cpuTe = String.valueOf(new Random().nextInt(2));

if (cpuTe.equals("0")) {
    jankenCpu = "グー";
} else if (cpuTe.equals("1")) {
    jankenCpu = "チョキ";
} else if (cpuTe.equals("2")) {
    jankenCpu = "パー";
}

処理の内容を考えてみれば、不要ですよね?なぜなら

System.exit(-1);

でプログラムは強制終了(引数に「-1」を与えているので『異常終了』)するからです。

つまり、if文の中の処理を行うとき=jankenTeがnullの時は「CPUの手を判定」より後の処理が行われません。

メソッドを利用する

その他にも、行けていないところがあります。それは、似たような処理がたくさんあるというところです。
特にif文の処理が同じような処理を行っています。

なので、メソッドを作成して同じコードを書かないようにします。

今までに、ちょこっと書いたりしました。改めて理解しましょう。

具体的には、以下のif文です。2か所、同じコードがあります。

String jankenTe = null;
if (input.equals("0")) {
    jankenTe = "グー";
} else if (input.equals("1")) {
    jankenTe = "チョキ";
} else if (input.equals("2")) {
    jankenTe = "パー";
} else {
    System.out.println("想定外の値です。" + input);
}

これをメソッドとして切り出します。具体的には下のように切り出します。staticがついているのはメインメソッドから呼び出すためです。

public static String jankenHantei(String input) {
    String jankenTe = null;
    if (input.equals("0")) {
        jankenTe = "グー";
    } else if (input.equals("1")) {
        jankenTe = "チョキ";
    } else if (input.equals("2")) {
        jankenTe = "パー";
    } else {
        System.out.println("想定外の値です。" + input);
    }
    return jankenTe;
}

そして、このコードと同じ部分を書き換えます。下のようなコードになりました。

public class JankenPon {
    public static void main(String[] args) {
        // 1.初めの処理
        System.out.println("じゃんけん ...");
        Scanner scan = new Scanner(System.in);

        // 2.標準入力受付
        String input = scan.nextLine();
        // 3.ユーザーの手を判定する
        String jankenTe = jankenHantei(input);

        String cpuTe = null;
        String jankenCpu = null;
        if (jankenTe == null) {
            // 強制終了
            System.exit(-1);
        }
        // 4.CPUの手を判定する
        cpuTe = String.valueOf(new Random().nextInt(2));
        jankenCpu = jankenHantei(cpuTe);

        System.out.println("ポン");
        System.out.println("あなた: " + jankenTe + " CPU; " + jankenCpu);

        // 5.勝敗判定を行う
        String hantei = input + cpuTe;
        String result = null;
        if (hantei.equals("01")) {
            result = "YOU_WIN";
        } else if (hantei.equals("12")) {
            result = "YOU_WIN";
        } else if (hantei.equals("20")) {
            result = "YOU_WIN";
        } else if (hantei.equals("00")) {
            result = "DRAW";
        } else if (hantei.equals("11")) {
            result = "DRAW";
        } else if (hantei.equals("22")) {
            result = "DRAW";
        } else if (hantei.equals("02")) {
            result = "YOU_LOSE";
        } else if (hantei.equals("10")) {
            result = "YOU_LOSE";
        } else if (hantei.equals("21")) {
            result = "YOU_LOSE";
        } else {
            System.out.println("想定外の値です。" + hantei);
        }
        // 6. 結果の表示
        System.out.println(hantei);
        System.out.println(result);
    }

    public static String jankenHantei(String input) {
        String jankenTe = null;
        if (input.equals("0")) {
            jankenTe = "グー";
        } else if (input.equals("1")) {
            jankenTe = "チョキ";
        } else if (input.equals("2")) {
            jankenTe = "パー";
        } else {
            System.out.println("想定外の値です。" + input);
        }
        return jankenTe;
    }
}

これで、多少はよくなりました。しかし、まだです。

Mapインターフェースを使用する

じゃんけんの判定方法ですが、すごく頭の悪いやり方です。しかし、これから見せるコードも頭の良いやり方ではありません。なぜかというと、何の工夫もないからです。

<頭の良いやり方ではない方法>
まずは下のような、フィールド変数(定数)とメソッドを作成します。

/** フィールド変数(定数) */
public static final String YOU_WIN = "YOU_WIN";
public static final String YOU_LOSE = "YOU_LOSE";
public static final String DRAW = "DRAW";

そして、次のメソッドを追加します。

   public static String jankenHantei(String input) {
        String jankenTe = null;
        if (input.equals("0")) {
            jankenTe = "グー";
        } else if (input.equals("1")) {
            jankenTe = "チョキ";
        } else if (input.equals("2")) {
            jankenTe = "パー";
        } else {
            System.out.println("想定外の値です。" + input);
        }
        return jankenTe;
    }

作成したメソッドを使用して、メインメソッドを書き直します。

そうすると下のようになりました。

public class Chap0 {
    public static final String YOU_WIN = "YOU_WIN";
    public static final String YOU_LOSE = "YOU_LOSE";
    public static final String DRAW = "DRAW";

    public static void main(String[] args) {
        // 1.初めの処理
        Map<String, String> hanteiMap = createMap();
        System.out.println("じゃんけん ...");
        Scanner scan = new Scanner(System.in);

        // 2.標準入力受付
        String input = scan.nextLine();
        // 3.ユーザーの手を判定する
        String jankenTe = jankenHantei(input);

        String cpuTe = null;
        String jankenCpu = null;
        if (jankenTe == null) {
            // 強制終了
            System.exit(-1);
        }
        // 4.CPUの手を判定する
        cpuTe = String.valueOf(new Random().nextInt(2));
        jankenCpu = jankenHantei(cpuTe);

        System.out.println("ポン");
        System.out.println("あなた: " + jankenTe + " CPU: " + jankenCpu);

        // 5.勝敗判定を行う
        String hantei = input + cpuTe;
        String result = hanteiMap.get(hantei);
        // 6. 結果の表示
        System.out.println(hantei);
        System.out.println(result);
    }

    public static String jankenHantei(String input) {
        String jankenTe = null;
        if (input.equals("0")) {
            jankenTe = "グー";
        } else if (input.equals("1")) {
            jankenTe = "チョキ";
        } else if (input.equals("2")) {
            jankenTe = "パー";
        } else {
            System.out.println("想定外の値です。" + input);
        }
        return jankenTe;
    }

    public static Map<String, String> createMap() {
        Map<String, String> hanteiMap = new HashMap<String, String>();
        hanteiMap.put("01", YOU_WIN);
        hanteiMap.put("12", YOU_WIN);
        hanteiMap.put("20", YOU_WIN);
        hanteiMap.put("00", DRAW);
        hanteiMap.put("11", DRAW);
        hanteiMap.put("22", DRAW);
        hanteiMap.put("02", YOU_LOSE);
        hanteiMap.put("10", YOU_LOSE);
        hanteiMap.put("21", YOU_LOSE);

        return hanteiMap;
    }
}

実行結果は下のような形で出力されました。

じゃんけん ...
1
ポン
あなた: チョキ CPU; チョキ
11
DRAW

如何でしょうか?だいぶすっきりしたように見えると思います。プログラムの処理内容が理解できていれば、無図解ことではありません。「このような方法もある」というのを知っておくと後々にカッコよいコードが書けるようになります。※自分も努力いたします。。。

でわでわ。。。

Java Basic 実践学習編 〜ハローワールドから変数の宣言・初期化〜

Javaの実践学習

今までに、色々と学習してきましたが、効率と理解度を考慮に入れるとズバリ下のような学習方法が一番だと思いました。

  1. コードを書く
  2. コードを動かす
  3. コードを書き換えて動かしてみる
    4.コードを理解する

この順序でいろんな書き方、プログラムの組み方を理解していくのが最もわかり易く、実践で使えると思いました。

この手順を使用してJavaの基本をやり直したいと思います。

初めてのJava

以前書いた記事はこちらです。

Lv1.ハローワールド

初めtのプログラムとして有名なものですが、これはJava言語に限ったことではありません。C言語、Python, C#, java script etc ...でも同じことです。
プログラムを起動して、「Hello World」と表示するだけのプログラムです。

このプログラムは、大きなアプリケーションに新たに取り組む、もしくはフレームワークを使用するなどの時に「プログラムが動くよね?」という確認のために使用することが多いです。

そして、自分はJava屋なので、Java言語で実装を行います。

下のコードは、「Hello クラス」を作成し、そこにメインメソッドを作成しました。

<Code.01>

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

Eclipse(開発ツール(IDE))での実行した時の動画は以下になります。

シンプルに、コンソール(標準出力)への文字列出力になります。

ポイント1

プログラムが動くことを確認するというところです。

Lv2.適当な文字の出力

上のコードを書き換えて、出力内容を変更します。

<Code.02>

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("I an Takunoji. It's verry hard.");
    }
}

出力した文言の言っていることは、意味がわかりませんが、とりあえずは、出力内容が変わります。

コードの実行確認は、読者の皆さんが行ってください。
※コピペしないほうが、理解も早いです。

ポイント2

"(ダブルクォーテーション)で囲った部分が文字列としてJVM(Javaを起動する機会、java.exeのこと)に、認識されます。
まとめると下のようなイメージになります。

System.out.println(「文字列」);

この「文字列」の部分を引数と呼びます。<Code.02>のコードを説明すると
「printlnメソッドの引数に文字列「I an Takunoji. It's verry hard.」を渡している」と説明できます。

よくあるミス

下のコードはエラーになります。

<Code.03>

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("I an Takunoji. It's verry hard.);
    }
}

すぐに気がつく人は気がつくのですが、気がつかない人はなかなか気がつきません。
自分がそうです。苦労しました、今でも、汚いコードとかにある、このような「小さなミス」を見つけるのに一苦労します。

コードは綺麗に書きましょう

一言で言うと自分があとで苦労します。。。

余談:綺麗なコードとは

単純に、以下の部分がポイントです。

  1. インデントが揃っている
  2. 余計な変数宣言がない
  3. 同じ名前の変数を別の用途に使いまわさない
  4. 処理が整理されていて、どの処理がどこにあるのかわかるようになっている

大まかに上のようなコードです。詳細に関しては、今後理解して行けば良いと思います。

Lv3.計算をしてみる

単純な足し算と引き算をコンソールに出力します。

<Code.04>

public class HelloWorld {
    public static void main(String[] args) {
        // 足し算
        System.out.println("1 + 1 = " + (1 + 1));
        // ひき算
        System.out.println("1 - 1 = " + (1 - 1));
    }
}

上のコードは、文字列「1 + 1 = 」に「1 + 1」の計算結果を文字列として連結して、出力しています。
次の行では、同様に、文字列「1 - 1 = 」に「1 - 1」の計算結果を文字列として連結して、出力しています。

ポイント3

ポイント2でも説明しましたが、

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

"1 + 1 = " + (1 + 1)

の部分が引数になります。
この引数は

"1 + 1 = "

が文字列を示し、

(1 + 1)

が計算処理でその結果は2になります。
最後に、

"1 + 1 = " + (1 + 1)

にある真ん中の「+」が文字列の連結処理を行っているところです。

文字列の隣に来る「+」は文字連結を示します。

では、次のコードを見て見ましょう、掛け算と割り算です。

<Code.05>

public class HelloWorld {
    public static void main(String[] args) {
        // かけ算
        System.out.println("2 * 2 = " + 2 * 2);
        // わり算
        System.out.println("2 / 2 = " + 2 / 2);
    }
}

ポイント4

このコードは、掛け算と割り算を行なっています。しかし、<Code.04>と比べてみるとかっこが足りません。
具体的に

"1 + 1 = " + (1 + 1)

"2  2 = " + 2  2

の部分です。

この部分は暗黙的なルールがあり、中学生くらいだと思いますが、「足し算と掛け算」があったら「掛け算」の方を先に計算すると言うルールがあったと思います。

プログラムでも同じなんです。

つまるところは以下のような理由で、上のような違いがあります。

<足し算と引き算の場合>

public static void main(String[] args) {
    // 足し算
    System.out.println("1 + 1 = " + (1 + 1));
    // ひき算
    System.out.println("1 - 1 = " + (1 - 1));
}

足し算と引き算の場合は、()かっこが必要です。それは「文字を連結する」と言う処理と、「計算をする」と言う処理にしようする演算子(「+」のこと)が同じなため

"1 + 1 = " + 1 + 1

のように書くと文字連結か、計算するかJavaコンパイラが判別できないためエラーになります。

<掛け算と割り算の場合>

public static void main(String[] args) {
    // かけ算
    System.out.println("2 * 2 = " + 2 * 2);
    // わり算
    System.out.println("2 / 2 = " + 2 / 2);
}

見た目にも、「+」と「*」で演算子が違うので「文字列の連結」と「計算」の区別がつきます。なのでかっこがなくてもビルドエラーになりません。

ついでにもう1つサンプルコード
<Code.06>

public class HelloWorld {
    public static void main(String[] args) {
        // かけ算と割り算
        System.out.println("2 * 2 = " + 2 * 2 / 2);
    }
}

この場合はどうのような処理結果が出るでしょうか?それは実行して見てからのお楽しみ。

変数を使う

プログラミングを行なっていると「変数」と言う言葉が出てきます。
プログラミングは、中学校くらいに習った(習う)数学と似たところがあります。

演算子 意味 サンプルコード
+ 足し算、文字列の連結 1 + 1, "文字" + "1"
- 引き算 1 - 1
* かけ算 1 * 1
/ わり算 1 / 1
% 剰余算 1 % 1
剰余算について

<Code.07>

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
        System.out.println("3 % 2 = " + 3 % 2);
    }
}

上のように割った後の余りを算出します。「3 / 2 = 1 あまり1」と言うふうになります。なので「3 % 2」の計算結果は「1」になります。

実際に使用するときは「変数Xが偶数か奇数か?」と調べるときに、下のような形で使用します。

<Code.08>

public class HelloWorld {
    public static void main(String[] args) {
        int X = 32;
        boolean isKisu =  X % 2 == 1;
    }
}

このときに変数Xを2で割った時の余りが1になる数は「奇数」です。逆に「0」になるものは偶数です。

このような「法則のようなもの?」を見つけてそれをプログラムに落とし込むと言うところもプログラミングの面白いところです。

変数を学ぶ

プリミティブ型の変数としては以下のようなものがあります。

[プリミティブ型]と呼ばれるデータ型の種類

データ型          読み      用途
byte            バイト        8ビットの整数(-127から127) を示すが実際はファイル入出力時にこのデータ型で扱うことが多い
int               イント        整数として使用する(四則計算など)、整数の計算で使用する事が多い
long              ロング      intよりも大きい数値を使用する時に使用する、日付計算などで使用する事が多い。
double          ダブル        小数点をつける数値として使用する
float            フロート    あまり使わない
char           キャラ          一文字を示す、またintでも扱うことができる 'a'(シングルクォーテーション使用)
boolean        ブーリアン 真(true)か偽(false)を示す、intではtrue=1, false=0

これは全てではないですが、大まかに変数の一覧になっています。

そして、よく使用するのが、以下の4つです。

  1. int型: 整数用の変数
  2. double型: 少数用の変数
  3. boolean型: 真偽値
  4. String型:文字列として使用する

今までにも使用しているコードですが、改めて眺めて見ましょう

<Code.09>

public class HelloWorld {
    public static void main(String[] args) {
        // 変数の宣言
        int seisu;
        // 変数の初期化
        double shosu = 0.0;
        // 変数の初期化
        String moji = "文字列";
    }
}

変数の宣言は値を代入しません。

int seisu;

、そして、初期化は値を代入します

int double shosu = 0.0;

上記ひと通りの内容を説明した動画が、以下になります。

四則計算の実装

次は、四則計算をプログラムで行います。上記の計算でも行いましたが、今回は変数を使用して実行します。

九九(2の段)を算出、表示する

サンプルコードは以下になります。

ポイント5

<Code.10>

public static void main(String[] args) {
    int a = 2;
    int x = 1;
    System.out.println("2 x 1 = " + a * x);
    x++;
    System.out.println("2 x 2 = " + a * x);
    x++;
    System.out.println("2 x 3 = " + a * x);
    x++;
    System.out.println("2 x 4 = " + a * x);
    x++;
    System.out.println("2 x 5 = " + a * x);
    x++;
    System.out.println("2 x 6 = " + a * x);
    x++;
    System.out.println("2 x 7 = " + a * x);
    x++;
    System.out.println("2 x 8 = " + a * x);
    x++;
    System.out.println("2 x 9 = " + a * x);
}

表示結果は以下になります。

ポイント

変数「a」と「x」を初期化して、掛け算した結果を表示しています。そして表示処理(

System.out.println("XXXX");

)の間にある

x++;

の処理は「インクリメント」と言って変数の値に「プラス1」します。
なので、これは2の段を表示できているのです。

今回は、ここまでです。次は、変数を使用して、簡単なプログラムを作成します。

2:Java式と演算子 〜とある本の学習+アルファ〜

2章 式と演算子

ここから先は、次のような形で学習していきます。

  1. コードを書き写す(写経する)※コピペ禁止
  2. プログラムを動かす
  3. 動かしたプログラムの内容を理解する

コードを書き写すのは、実際にコードを書くとコードの意味を理解しやすいからです。

コピーしてしまうと、塊でしか理解できないので、プログラムを読めるようになりません。当然自分でプログラムを書けるようにもなりません。

目的としては、プログラムを自在に組むことができるようになることなので、はじめのうちは写経するようにしましょう(笑)

計算の文

写経するコード

public class Main {
    public static void main(String[] args) {
        int a;
        int b;
        a = 20;
        b = a + 5;
        System.out.println(a);
        System.out.println(b);
    }
}

実行結果は自分で確認してください。

そして、次の単語を覚えます。

  1. リテラル、変数のこと = 「オペランド
  2. 「+」「*」「=」など = 「演算子

リテラルに関して

変数の型に関しては、理解できたと思いますが、変数を宣言したときの右側部分

// 変数の宣言
int number;// 数値
String moji;// 文字列

// 変数の初期化
double shosu = 0.0; // 数値
boolean isTrue = true;// 真偽値
String moji2 = "mojimoji";// 文字列
String moji3 = "1";// 文字列
String moji4 = "0.0";// 文字列

リテラルは文字列、整数型などの変数に値を設定する前。
つまりは、「=」の右側のことです。
「String a = "文字リテラル";」とか「int i = 10」などのような初期化をした時に出てくる右側部分です。つまりは、 「"文字リテラル"」と「10」がそれにあたります。

String moji = "文字リテラル";
int seisu = 10;

上のコードの場合は、文字リテラルが「"文字リテラル"」で整数リテラルが「10」になります。

細かい説明などはこちらの動画にしてありますので、よかったらどうぞ。※コードの実行も行なっております。

エスケープシーケンス

プログラムを書いている時に下のような処理を行いたいとします。

コンソール(標準出力)に「"(ダブルクォーテーション)」を表示する

この場合、「文字列を表すリテラルで『"(ダブルクォーテーション)』を使用しているので、エスケープしないとビルドエラーになります。

System.out.println("文字列の表示は"(ダブルクォーテーション)を使います”);

このような時に「”」をエスケープします、その方法が「バックスラッシュ(¥)」になります。

System.out.println("文字列の表示は¥"(ダブルクォーテーション)を使います”);

細かいことが書いてありますが、バックスラッシュでエスケープします。
バックスラッシュをエスケープする時は次のように書きます。「¥¥」

System.out.println("データの保存はC:¥¥fldに保存してください");

四則演算を行う

Javaプログラムで四則演算を、通常の計算を行います。

写経するコード

public class Main {
    public static void main(String[] args) {
        int a = 0;
        int b = 1;
        int c = 2;
        System.out.println(a + " + " + b + " = " + (a + b));
    }
}

上のコードを写経して実行してみてください。表示結果は省略します。

この時、

a + " + " + b + " = "

の部分は、数値が文字列に変換されます(暗黙的にキャストします)。このため

+ (a + b)

の部分も文字列の追加として扱うか、数値の計算として処理するべきかJVMがわから無くなってしまうので

(a + b)

のように、カッコをつけます。

これは、式の評価をする順番を意図的に変えています。

カッコをつけない場合

System.out.println(a + " + " + b + " = " + a + b);

式の評価は、全部が「+」演算子なので左から順に評価されていきます。

しかし、次のように、プログラムを修正した場合

public class Main {
    public static void main(String[] args) {
        int a = 0;
        int b = 1;
        int c = 2;
        System.out.println(a + " * " + b + " = " + a * b);
    }
}

数学で習ったように、掛け算の処理が先に行われます(評価されます)。なのでカッコがなくてもビルドエラーになりません。

キャスト

プログラムを実行している時に、「文字列を数値に変換したい」、「数値を文字列に変換したい」。というようなことが起きます。

例えば、占いプログラムを作るとします。

占いプログラムでは、ユーザーの生年月日を入力しますが、これは文字列です。

占いの判定をするのに、西暦部分と誕生月部分を足し算して、これを合計する必要があります。

このような時には、下のようにキャストしてやります。

String born = "1999/02/22";
int seireki = (int) "1999"; // ビルドエラー

// doubleとintは同じ数値なのでキャストできる
double d = (double) 12;

// 文字列は下のように変換する
int nen = Integer.parseInt("1999");

写経するコード2

public class Main {
    int r = new java.util.Random().nextInt(90);
    System.out.println("乱数の生成結果: " + r);
}

写経するコード3

public class Main {
    System.out.println("あなたの名前を入力してください。");
    String name = new java.util.Scanner(System.in).nextLine();
    System.out.println("あなたの年齢を入力してください。");
     int age = new java.util.Scanner(System.in).nextInt();
    System.out.println("ようこそ" + age + "歳の" + name + "さん");
}

このコードは、遊べるコードなので、たくさん遊んでみてください。

(例)

入力した値を判定して、数字かどうか区別する
IN: ABC
OUT: 数字ではありません
IN: 123
OUT: 数字です

上のような出力を行うプログラムを作成する。

他にもできることはたくさんあります。

三角形の辺の長さを入力してください。
1: ※入力値
2: ※入力値
3: ※入力値
三角形の面積=

Java java.nio.Files 使い方~古いけどニューIO(アイオー)でCSV読み書き~

Java Filesを使う

java.nioが使用できるようになって久しいですが、改めてファイル読み込みの処理を行おうと思います。

今回やろうとしているのは、Csvファイルの読み込みです。主にデータのやり取りを行う時に、Csvファイルを読み込み、DBに登録する。。。

など用途は様々です。最近の流行りだとビックデータを取得して、データ解析などありますが、データを読み取ると言う部分の基本的な手段になります。

CSVファイルの読み込み

CSVファイルはカンマ区切りのデータを保存するのに使用されます。よくMySQLやPoestgreなどのDBでも「CSV出力」とか「CSV読み込み」などを行います。

具体的には下の様なテキストファイルです。一行目は、ヘッダーになっていて項目名を並べる事が多いです。

当然の様に、ヘッダーなしのものも、あります。

id, name, age, tall

1, taro, 16, 180

2, yuki, 20, 160

3, umi, 24, 190

身近な例として、政府の統計調査結果などをCSVでダウンロードできたりします。

CSV読み込み実装

CSVファイルを開いて、その中身を1行ずつ読み込みます。単純に読み込んで、コンソール(標準出力)に出力するだけの処理です。

なので、下のようなテストケースを実装しました。

  1. 実装するメソッドはreadCsv()です。
  2. readCsv()はstaticメソッドです。
  3. 「D:\csv\c01.csv」というファイルを読み込見ます。
  4. ファイルは文字コードが「SJIS」だったので文字コードを「SJIS」に指定します。

<テストコード>

@Test
public void testReadCsv() {

    List<String[]> res = CsvUtils.readCsv("D:\\csv\\c01.csv", "SJIS");
    res.forEach(arr -> {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + ", ");
        }
        System.out.println();
    });
}

Assertは入れていない状態です。これから仕様を決めようというところです。

次は、実装するメソッドです。

  1. 引数はファイルパスと文字コードの文字列です。
  2. データを格納するListインターフェースに実体クラスのArrayListを代入します。
  3. ファイルパスから、文字コードを指定して読み取ります。
  4. 取得した1行のデータにあるかもしれない「ダブルクォーテーション(\")」を空文字に置き換えます。(削除します)
  5. 取得したデータ1行分をカンマ(,)で分解し文字列の配列に変換します。
  6. 1行分のデータ(配列)をListに設定して返却します。
    <実装コードCsvUtil>
  7. /**
  8. * CSVファイルを読み込みListで返却する。
  9. *
  10. * @param filePath 読み込むファイルのパス(完全パス)
  11. * @param encordName UTF-0, SJISなどのエンコード名
  12. * @return String配列のList
  13. */
  14. public static List<String[]> readCsv(String filePath, String encordName) {
  15. List<String[]> dataList = new ArrayList<>();
  16. try {
  17.     BufferedReader buf = Files.newBufferedReader(Paths.get(filePath), Charset.forName(encordName));
  18.     String line = null;
  19. 
    
  20.     while((line = buf.readLine()) != null) {
  21.         dataList.add(line.replaceAll("\" ", "").split(","));
  22.     }
  23. } catch (IOException e) {
  24.     e.printStackTrace();
  25. }
  26. return dataList;
  27. }

とりあえずは、読み込みの処理ができました。
しかし、開いたファイルを閉じる処理が実装されていないので、あとでbuf.close()を追加実装しました。

書き込み処理

上の読み込み処理の後に、返却されるList<String[]>`を引数にして`exportPathにファイルを出力する処理です。

  1. まずは、リソース読み込み用のtry~catchを使用してファイルを書き込みで開きます。
  2. リストから文字列の配列を取り出し、書き込みます。
  3. 書き込みじは文字コードを「SJIS」に設定します。
  4. 1行書き込んだら、次の行なのでnewLine()で次の行に進みます。

<書き込みの処理>

後日記載致します。

以上で、読み込みと書き込みの処理ができました。

でわでわ。。。

1:Javaプログラムの書き方 〜とある本の学習+アルファ〜

1章:ようこそJavaの世界へ

1.1 Javaによる開発の基礎知識

1.1.1 開発の流れ

①ソースコードの作成。

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

②コンパイル
javaファイルをclassファイルに変換することです。下のコマンドを使用します。

javac FirstCls.java

③実行
作成したクラスファイルを実行します。下のコマンドを使用します。

java FirstCls

1.1.2 開発環境の整備

※Eclipseはインストール済みの想定。
インストール方法

外観を変更する

  1. ウィンドウ→設定→一般→外観→色とテーマの順にクリック
  2. ここで好きなテーマを選択する
    ※大半の人がデフォルトで使用している

文字コードの変更(確認)

  1. ウィンドウ→設定→一般→ワークスペースの順にクリック
  2. 「テキスト・ファイル・エンコード」がUTF-8になっていることを確認

JDKの確認

  1. ウィンドウ→設定→一般→Java→インストール済みのJREの順にクリック
  2. JDKを指定して、使用するJREを決定する

1.2 Javaプログラムの基本構造

1.2.1 プログラムの骨格

Javaは「クラス」を基準にしてプログラムを起動します。
Javaを起動する時に、必要になるJDKには、JVM(=java.exe)があるので、JVMが下のように動きます。

  1. プログラムを起動するのに必要なライブラリなどの読み込み
  2. メインメソッドを持っているクラス探す
  3. メインメソッドを持っているクラスのメインメソッドを実行する

ルール:クラス名とファイル名は同じ名前にする
「クラスの中にメソッドがある」

/** クラスの説明 */
public class クラス名 {
  /** メソッドの説明 */
  public static void main(String[] args) {
    // 何かしらの処理
  }
}
  • 中かっこ(「{」「}」)のことを「スコープ」と呼びます。スコープで囲っている部分を「ブロック」などと呼んだりします。

  • このスコープ(=「ブロック」)を開いたら(開始したら)、必ず閉じる(終了する)ことを意識する

  • 中かっこ(「{」「}」)で囲っている部分がそれぞれクラスの範囲、メソッドの範囲を決めている

上のサンプルコードでは「クラス名」クラスの中に「メインメソッド」がある

ちなみに、インデント(スペースやタブで位置をずらすこと)を入れないと、とても見にくい

何が見にくいというと、クラスの範囲と、メソッドの範囲を区別しずらいのです。

<インデントなし>

/** クラスの説明 */
public class クラス名 {
/** メソッドの説明 */
public static void main(String[] args) {
// 何かしらの処理
}
}

1.2.2 プログラムの書き方

Java言語(C言語も)の場合は、メインメソッドが起動しますので、クラスの中にメインメソッドを作成する

Javaはメインメソッドが動く

  1. どのようなプログラムを作りたいかを考えます。

  2. プログラムの名前を決めます。

  3. 「クラス名.java」という名前でファイルを作ります。

  4. 下のような、ソースコードの外側を記述します。

    /** クラスのJavaDocコメント */
    public class クラス名 {
    /** メインメソッドのJavaDocコメント */
    public static void main(String[] args) {
    // 処理の中身:通常のコメント
    /*
     * これも通常のコメント、あまり使われない。
     */
    }
    }
  5. ソースコードの中身を描きます。

    System.out.println("Hello World!");

     1.2.5 mainメソッドの中身

  • 上の骨格の「何かしらの処理」の部分に処理を描く。
  • 処理は上から下へ進み、1行の中では左から右へ進む
  • セミコロン「;」で1行が終わる
  • ドット「.」は参照呼出し
public static void main(String[] args) {
  System.out.println("Hello World");
}

上のコードは、Systemクラスから変数「out」を呼び出し、メソッド「println()」を呼び出している

練習:SecondProgram

写してください。以下のコードを書いて動かしてください。

public class SecondCls {
  public static void main(String[] args) {
    System.out.println("*** Second Program ***");
    System.out.println("日記ソフト");
    System.out.println("終了します。");
  }
}

実行方法は以下の通り

  1. SecondCls.javaファイルを作成する

  2. 「ウィンドウズボタン+R」を押下してコマンドプロンプトを開く

  3. javacコマンドでクラスファイルを作成する

    javac SecondCls.java
  4. javaコマンドで作成したクラスファイルを事項する

    java SecondCls

1.3 変数宣言の文

1.3.1 変数宣言の文とは?

ズバリ下のように書きます。

  1. 変数の宣言
    // 「宣言」:データ型 変数名;
    int hensuMei;
  2. 変数の初期化
    // 「初期化」データ型 変数名 = 代入するデータ
    int dataGata = 0;

1と2の違いは、宣言と同時に値を代入するかしないかです。

==変数の宣言と初期化==

public static void main(String[] args) {
  // 変数の宣言
  int num;
  // 変数の代入
  num = 0;
  // 変数の初期化
  int age = 12;
  // 命令実行の文=メソッドの呼び出し
  System.out.println("対象年齢は" + num + "~" + age + "です。");
}
  • 「変数に値を代入するとき」は「=」を使用する。
  • 「命令の文」は「メソッド呼び出し」を行う

1.3.2 変数の名前(識別子)

==英語では==

変数=Valiable

名前つけのルール

予約語は使用しない(予約後の一覧)

abstract assert boolean break byte
case catch char class const
continue default do double else
enum extends final finally float
for goto if implements import
instanceof int interface long native
new package private protected public
return short static strictfp super
switch synchrnized this throw throws
transient try void volatile while

宣言(初期化)済みの変数名は使用できない

大文字・小文字は区別される

変数名・メソッド名はキャメルケースを使用する

// 変数名のキャメルケース(頭を小文字にする)
int myAge;
// メソッド名のキャメルケース(頭を小文字にする)
public void methodName();

クラス名はアッパーキャメルケース

/** クラス名は頭を大文字にする */
public class ClassName {
}

演算子で使用している文字、予約語は変数名(クラス名)として使用できない

==計算処理==

public static void main(String[] args) {
  // 足し算
  int tashizan = 1 + 1;
  // 引き算
  int hikizan = 1-1;
  // 掛け算
  int kakezan = 1 * 1;
  // 割り算
  int warizan = 1 / 1;
}

1.3.3 データ型

※あくまでも使用例として紹介しています。
==プリミティブ型データの変数型==

  • byte ファイル・ネットワーク通信時に使用
  • int 整数データを格納するのに使用
  • long 大きな整数値を格納するのに使用
  • float 画像処理、3Dモデル描画時に使用
  • double 少数データを格納するのに使用
  • char 1文字分のデータ、シングルクォーテーション「`」で囲む

==参照型データの変数型==

  • String 文字列
  • そのほかJavaAPIや自作のクラス名
    List list; // List型の変数「list」

1.3.5 定数の利用

変数には値を何度でも代入できるので、定数を使用して値を変更できないようにする。

final データ型 変数名 = 代入するデータ

ルール:定数は大文字の変数名にする

final int OVER_TEN = 0; // 値が10以上を示すフラグ
final int UNDER_TEN = 1; // 値が10以下を示すフラグ

定数の使用例:フラグに使う

public static void main(String[] args) {
    final int OVER_TEN = 0; // 値が10以上を示すフラグ
    final int UNDER_TEN = 1; // 値が10以下を示すフラグ
}

1.5 練習問題+α

コマンドプロンプト上に下のような図を表示するプログラムを作成してください。
※ 「=」の数が、上下ともに20あります。
<出力する図>

      *
    *   *
  *   *   *
      *
      *
  *   *   *
    *   *
      *

====================

Java オブジェクト指向 ~設計図と実装のイメージをつなげる~

イントロダクション

下のようなツイートをしてみたところ。。。

複数の「いいね」をもらったので、自分の知っていることを記載します。

1. 設計と実装のつながり
2. 設計(クラス図)について
3. オブジェクト指向

結論から言うと「設計図(クラス図)は実装を示している」という認識です。
しかし、「オブジェクト指向で躓く人が多い」というウワサから想像するに、この部分は多くの人がつまずく部分だと思われます。

「躓いた数なら日本一」の自信がある自分としては、以下のものが不明瞭な認識のままではなかろうかと思います。
1. 設計と実装のつながり
2. クラス同士の関係
3. クラスのインスタンス化
4. 処理の追いかけ方

サンプルとして下のようなコンソールアプリを作成しました。
※ 以前作成したのものがありました。。。

これのクラス図も作成しました。

これらを材料にして設計(クラス図)と実装のつながりを見ていこうと思います。

# 1. 設計と実装のつながり
実装をしてない状態では、上記のイメージ(クラス図)のように、詳細な処理が書かれていない状態です。
この部分は「自分で考える」必要があります。

具体的には、**単純に疑問点を明確にしていく作業**があるということです。クラス図の内容を箇条書きにすると下のようになります。

1. MainBankクラスはCalculationクラスを持っている(属性を持っている)
2. MainBankクラスはメインメソッドを持っている(操作を持っている)
3. MainBankクラスはatm()を持っている(操作を持っている)
4. Calcurationクラスはyokingaku()を持っている(属性を持っている)
5. CalcurationクラスはgetYokingaku()を持っている(操作を持っている)
6. CalcurationクラスはsetYokingaku()を持っている(操作を持っている)
6. Calcurationクラスはnyukin()を持っている(操作を持っている)
7. Calcurationクラスはvalidate()を持っている(操作を持っている)
8. Calcurationクラスはcalcurate()を持っている(操作を持っている)
9. InputCheckerクラスはvalidNyukinHikidashi()をもっている(操作を持っている)

上のような内容だと**処理の内容が**わかりません。それもそのはず、コーダー(実装者)が行うべき仕事だからです。

早い話が、自分で考えましょうということです。

上のわかっていることで**確定しているところは「属性」**です。なので属性はそのまま実装していしまいます。

#### ポイントその1
フィールド変数に関しては明確になっている、一例ですが下のような部分です。
> 1. MainBankクラスはCalculationクラスを持っている(属性を持っている)

というのは、フィールド変数にCalculationクラスをもっていて、クラス図にある「-」はアクセス修飾子が「private」ということです。

<[MainBank.java](https://github.com/ZenryokuService/PracticeJava1/blob/master/PracticeJava1/src/jp/zenryoku/apps/atm/MainBank.java)>

public class MainBank {
    /** 金銭管理クラス */
    private Calcuration cal;
}

<[Calcuration.java](https://github.com/ZenryokuService/PracticeJava1/blob/master/PracticeJava1/src/jp/zenryoku/apps/atm/Calcuration.java)>

public class Calcuration {
    /** 預金額 */
    private int yokingaku;


<[InputChecker.java](https://github.com/ZenryokuService/PracticeJava1/blob/master/PracticeJava1/src/jp/zenryoku/apps/atm/check/InputChecker.java)>

public class InputChecker {
}

## 2.設計(クラス図)について
設計(クラス図)について考えていきます。

#### 不明点のポイント
どのように実装したらよいか?というところに焦点を当てます。
不明点の残る「操作」に関してはとりあえずメソッドだけ作ってしまいます。
上のクラス図には詳細な返却値などの指定がないので、この部分も不明点 -> 自由に実装してよいところ、となるわけです。

メインメソッドは最後にします、それはこれから作成する「操作」をそろえてから、「不足する操作(メソッド)」を作ってから考えるべきだからです。※不足分を後で追加すると面倒なのです。。。

料理に例えると、先に作成する料理の、材料をそろえるようなイメージです。

まずは、不明点の洗い出しを行います。操作の内容が不明な状態なのでメソッドの一覧を作成することになります。

1. MainBank#main()に関してはメインメソッドなので最後にします。
2. MainBank#atm()は、名前からしてコーダー銀行アプリを起動するメソッドにします。
2. Calcuration#getYokingaku()は名前からしてフィールドの値を取得するメソッドにします。
3. Calcuration#setYokingaku()も名前からしてフィールドの値を設定するメソッドにします。
4. Calcuration#nyukin()メソッドは、名前からしてお金を入金するときのメソッドにします。
5. Calcuration#validate()メソッドは、名前からして入力チェックのメソッドにします。
6. Calcuration#calcurate()メソッドは、名前からして計算処理を行うメソッドにします。

ここまで作成したら、処理のイメージが湧いてくるかと思います。

大まかに、Calcurationクラスで、入金(出金)を行い、預金金額の管理も行う。というところです。

そのためには「入金(出金)(nyukin())」メソッドを用意して、計算処理のメソッド(calcurate())を用意して。。。

というような実装イメージがわくと思います。

具体的にメソッドの枠を作ってみましょう、具体的にはメソッドを空実装(中身の実装をしない)をしてみます。

### 実際の業務として実装するときは
「この部分に関しては「このように実装します。よろしいでしょうか?」などのように上長に確認しましょう。

### 操作の実装
早速、実装していきます。まずは入力(IN)と出力(OUT)を明確にします。この部分は設計の工程になります。
業務としては、この詳細な設計部分は設計書に記載されていることがほとんどですが、たまに「よろしく!」といわれることがあるので、そのときは、自分で考えます。

「このように実装します」という報告は忘れないようにしましょう。

まずは、設計図(クラス図)でもメソッドの量が多いので、CalcurationクラスのI/O(INとOUTのこと)を決定します。「空実装」を行うという意味です。しかし、ゲッターとセッターに関しては処理が決まっているので実装してしまいます。

ここまでの実装は以下になります。

public class Calcuration {
    /** 預金額 */
    private int yokingaku;

    /** コンストラクタ */
    public Calcuration() {
    }

    /** 
     * 預金金額のゲッター
     * @return the yokingaku
     */
    public int getYokingaku() {
        return yokingaku;
    }

    /**
     * 預金金額のセッター
     * @param yokingaku the yokingaku to set
     */
    public void setYokingaku(int yokingaku) {
        this.yokingaku = yokingaku;
    }

    /** 
     * 入金処理 or 引出し
     * @param input 標準入力
     * @param isNyukin
     */
    public void nyukin(Scanner input, boolean isNyukin) {
    }

    /**
     * 入力チェック処理
     * @param in
     * @return true: 入力エラー false: 入力OK!
     */
    private boolean validate(String in) {
        return false;
    }

    /**
     * 
     * @param in 数字文字
     * @param isNyukin ture: 入金処理 false: 引出し処理
     */
    private boolean calcurate(String in, boolean isNyukin) {
        return true;
    }
}

### クラス同士の関係
上のクラス図にあるクラスは以下の3つです。
1. MainBank
2. Calcuration
3. InputChecker

これらの関係性を考えると、下のような役割を持たせてやるとよい関係が築けそうです。
1. MainBank => メインメソッドを実行する
2. Calcuration => 預金金額の計算、管理を行う。
3. InputChecker => 入力チェック処理を管理する。チェック処理はここに書くということです。

この部分(クラスの関係)は、アイディアの良し悪しが入ってくる部分です、そして、プログラミングの面白いところでもあります。上記のような関係よりも良い関係があればそのように実装するべきです。

そして、それぞれのクラスの役割が決まってきたら次は、空になっているメソッドの実装を行います。

補足として、クラス関係を作るときにどう考えたら良いかわからない場合には、とりあえず1と2のクラス関係を作りプログラムを動かしてみて下さい。

書いて動かして見れば、理解出来ます。案ずるより生むが易しと言ったところです。

## 3.オブジェクト指向
ここで、頭の中を設計レベルに戻します。

具体的には、どのような処理を行うか?を考えるというところです。

以下のような、手順で考えるとよいと思います。

1. メインメソッドにコメントで処理の順番を記述する

public static void main(String[] args) {
    // 1.MainBankクラスのインスタンス化
    // 2.MainBank#atm()メソッドを呼び出す 
}


2. MainBank#atm()メソッドにコメントで処理の順番を記述する

public void atm() {
    // 1. コーダー銀行の受け付け開始文言を出力
    // 2. 無限ループを開始
    // 3. 初期画面の文言を出力
    // 4. 標準入力を受け付ける
    // 5. "bye"と入力があった場合は処理を終了する
    // 6. 入力チェックをする
    // 7. "in"と入力があった場合は入金処理を行う
    // 8. "out"と入力があった場合は出金処理を行う
}

ここで、"in" もしくは "out" が入力されたときは入金処理を呼び出します。入金時と、出金時を区別するための引数も付けます。

3. 各部品クラス(Calcuration, InputChecker)に実装コメントを書く

この様にすると、不明点を明確にすることができるのではないでしょうか?

あくまでも自分の考えた「設計」なので、もっと良い「設計」があるかもしれません。

この様に、下のクラス(オブジェクト)に役割を持たせ、必要な処理(メソッド)を実装します。処理はなるべく周りに影響が出ないように、実装しているクラスのみに影響範囲が収まるように実装します。

具体的には、実装したメソッドの中でほかのクラスの処理を呼び出すとか、用途が限定されるなどのような実装にならないようにするということです。

具体的には、計算をするメソッドを実装するのに、引数を定義せず、返り値だけ定義してしまうと、決まった計算しかできなくなります。なので、メソッドに対する汎用的な使用方法を考えた実装をしましょう。という事です。

そして、他のクラスの処理を**必ず呼び出さない**というのも不適切な判断なので、この部分はフレキシブルに実装するべきです。

つまりは、ひとつのクラスのみを使用する形で実現すると、例えば足し算をするメソッドを複数クラスに実装しなくてはなりませんが、初めから、計算クラスを作っておいて、足し算メソッドを定義しておけば、足し算処理は「計算クラスの足し算メソッド」を利用すれば、同じ処理を実装する必要がなくなります。

オブジェクト指向プログラミングでは、資源の再利用を可能にする事で無駄な作業を減らし、より良いプログラミング・ライフを楽しんで行ける様に考えます。

実装の経験(自分で実装してみるなどの経験)により、より良い方法を身に着け、より良いプログラムがかける様になります。

この様なところが**「知識」ではなく「技術」**なのです。

### クラスのインスタンス化
上記で出てきたクラスについて、考えます。
> 1. MainBank => メインメソッドを実行する
2. Calcuration => 預金金額の計算、管理を行う。
3. InputChecker => 入力チェック処理を管理する。チェック処理はここに書くということです。

ここで、特殊なのは「メインメソッド」です。これは**static**修飾子がついているので、MainBankクラスの中にあっても、定義したメソッド(メンバ・メソッド)を実行するためには、インスタンス化が必要です。
つまり「new」する必要があるということです。

インスタンス化するというのは、**PCのメモリ上に「クラス」で定義したオブジェクトを作成する**ということです。この部分は、とても抽象的なので理解に苦しみました。

自分の場合は、絵にするとわかりやすかったので絵にすると上記のようなクラス図と似たものになりました。
![](http://zenryokuservice.com/wp/wp-content/uploads/2020/11/import1-5.png)

今回の実装では、インスタンス化するクラスは1つなので、複数ある場合を顧慮しなくてよいですが、ただ一つインスタンス化していないクラスつまり、「new」していないクラスがあります。

InputCheckerクラスです。このクラスのメソッドはstatic修飾子がついていて、インスタンス化しなくてよいのです。

staticはクラスの「インスタンスに依存しない」ということなので、起動するあっぷりケーションには必ず1つです。

具体的にはメインメソッドが必ず一つです。そして、staticをつけたXXXメソッドはクラスに一つです。

例えば、上記のCalcurationクラスを複数作成した場合、預金額はCalcurationクラスのインスタンスの数だけ存在します。

public stataic void main(String[] args) {
    Calcuration calA = new Calcuration();
    Calcuration calB = new Calcuration();

    calA.nyukin(); // ここで、入金処理
    calB.nyukin(); // ここで、入金処理

    System.out.println(calA.getYokingaku());
    System.out.println(calB.getYokingaku());
 }

のように実装した場合は、calAとcalBで保持している預金金額の値が**別々に**計算されます。

逆に、預金金額の修飾子にstaticがついていた場合は、calAとcalBで保持している預金金額の値が**同じに**なります。

### 処理の追いかけ方
これは、そのまま読むしかないのですが、まずは決まっているところから記載します。
**まずはメインメソッド**から、処理が始まります。これは絶対です。
なので、メインメソッドの処理を追いかければそのまま処理を追いかけることになります。

詳細に関しては、すでに記載しているので割愛します。

以上で、設計図と実装のつながりが理解できたと思います。

如何でしょうか?

でわでわ。。。

Java オブジェクト指向基礎 ~オブジェクト指向コンセプト~

イントロダクション

オブジェクト指向という言葉は皆さん聞いたことがあると思います、これについてちゃんと理解しようと思います。

オブジェクト指向コンセプト

1.なぜオブジェクト指向か

システム開発における課題」 -> 開発期間の短縮
顧客の要求やサービスは、早いサイクルで変化します。そのためシステム開発に多くの時間を
かける余裕がありません。それどころか、開発が進んでいる最中に、要求やサービスの内容が
変わっても期間内の対応が求められます。

つまり、仕様変更があっても開発期間が変わらないので、多くの開発者が会社にお泊りすることが
多々ありました。

システムの仕様変更に伴うコストの削減

前述の通り、開発途中で顧客の要求する内容が変わることもありますが、そのたびに初めから
作成していては、期間が延びるだけでなく、費用がかさみます。顧客は最小コストで最大限の
成果を期待します。

この様な問題点に対応するためには、システム開発において、次のことを実現するべきです。

1.1.3実現するべきこと

  1. 以前に作成したプログラムを再利用する
  2. 大勢のエンジニアで共同開発を行う
  3. プログラムの変更箇所をいち早く特定し対応する
  4. あるプログラムの変更がほかのプログラムに影響しないようにする

もし、巨大な1本のプログラムとして構築したら、これらを実現するのは、困難です。しかし、システムを管理しやすい単位で分割し、それらを組み合わせる形式で構築すれば、これらを実現することができます。

この分割の単位をオブジェクトとするのが、オブジェクト指向による開発です。

2. オブジェクトとは

それでは、システム分割単位である「オブジェクト」とは、いったいどのようなものでしょうか。
ここでは、「エアコン」を制御するプログラムを例にそれを見ていきます。

下の図ではエアコンが持つ情報や機能を書きだしたものです。「電源」は電源の情報(状態)、「設定温度」や「運転モード」は使う人が操作した情報(状態)を示すものです。
一方、「電源をON(あるいはOFF)にする」「運転モードを切り替える」「設定温度を変更する」などは、エアコンを操作するための機能です。

エアコンを例にすると。。。

<エアコンの場合>

表1<エアコンの制御プログラム>

係(役目) 情報(状態) 機能
電源係 電源 電源をON、OFFにする
温度係  設定温度 設定温度の変更
温度係  現在の室温 現在の室温を測る
運転係  運転モード 運転モードを切り替える
運転係  運転モード 温度差によって動作を変える

エアコンを制御するプログラムは、こうした情報(状態)を保持し、参照しつつ使う人の操作に応じてエアコンをどうさせます。

<ポイント>

情報(状態)と機能は密接にむずびついて1つの係・役割を担い、それ以外の情報(状態), 機能から互いに独立しているということです。
そして、エアコンが操作されるとそれぞれの係は、互いに要求を行い、連携して動作します。

運転モードの着替え時の場合

運転モードを「冷房」から「ドライ」に変更する操作が行われたら、「運転係」から「温度係」へ設定温度の変更をする「要求」が行われます。また、「運転係」は現在の室温と設定温度を確認しないと動作(冷やす、温める)を決められないので、「温度係」にそれらの情報(状態)を問い合わせます。

この場合、「係」に相当するのが、システムにおけるオブジェクトです
また、「温度係」が電源のON/OFFを切り替えたり、「運転係」が設定温度を変更したりしません。
それぞれの係は自分のすべきことが明確に分かれています(独立性)。

子の係の独立性のおかげで、オブジェクト指向による開発では、作業もオブジェクトごとに独立して進めることができます。開発を終えたオブジェクトは、他のオブジェクトから簡単に利用することができます。また、おかしな動作を押する箇所が出ても、オブジェクト単位で調査・修正するので、利用しているオブジェクトへの影響を軽減することができます。
これにより上記の実現するべき点をかなえることが得できます。

オブジェクト指向言語の機能

属性と操作

Java言語を使用した場合、オブジェクトをどのように表現するのか見ていきましょう。ここでもエアコンの制御プログラムを例に確認します。

先ほどの表(下の図)を見ながら読み進めてください。


表1<エアコンの制御プログラム>

係(役目) 情報(状態) 機能
電源係 電源 電源をON、OFFにする
温度係  設定温度 設定温度の変更
温度係  現在の室温 現在の室温を測る
運転係  運転モード 運転モードを切り替える
運転係  運転モード 温度差によって動作を変える

前節では、係がオブジェクトに相当することを説明しました。さらにオブジェクト指向では、上の図
にある情報(状態)のことを属性と呼び機能のことを操作と呼びます。
例えば、電源系(電源オブジェクト)は「電源」という属性と「電源をONにする」「電源をOFFにする」
という操作が一つのセットにな手出来ています。
温度係(温度オブジェクト)も運転係(運転オブジェクト)も同様です。

つまり、オブジェクトは属性と操作を一体化することで表現されます。

属性と操作

属性と操作について詳しく見ていきましょう。属性は変数として、表現され、名前と値を持ちます。

  • 属性「室内温度」⇒値「30度」
  • 属性「設定温度」⇒値「27度」

属性をプログラムで表現する場合の例

/** 温度係 */
public class Temparature {
  /** 室内温度 */
  int roomTemparature;
  /** 設定温度 */
  int settingTemparature;

 /** コンストラクタ */
  public Temparature() {
    // 例なのでコンストラクタで値を設定する
    roomTemparature = 30;
    settingTemparature = 27;
  }  
}

操作は、他のオブジェクトや自分自身(自オブジェクト)から呼び出されることにより動作し、
そのオブジェクトの状態を変えたり、さらにそこからほかのオブジェクトの操作を呼び出したり
できます。下の図Aでは、温度オブジェクトに「設定温度を変更する」という操作(メソッド)
が定義されています。エアコンの設定温度を変更したい場合には、属性へ直接悪背うするのではなく
この操作を呼び出します。
図A

属性と操作をプログラムで表現する場合の例

/** 温度係 */
public class Temparature {
  /** 室内温度 */
  int roomTemparature;
  /** 設定温度 */
  int settingTemparature;

 /** コンストラクタ */
  public Temparature() {
    // 例なのでコンストラクタで値を設定する
    roomTemparature = 30;
    settingTemparature = 27;
  }

  /** 設定温度を変更する */
  public void setSettingTemparature(int setTamparature) {
    this.setTamparature = setTamparature;
  }
}

カプセル化とデータ隠蔽

オブジェクト指向では、そのオブジェクトが持つ属性と操作を一体化して表現すると説明しましたが、
これをカプセル化と呼びます。

カプセル化には次のようなメリットがあります。

  1. オブジェクトの内部構造を知る必要がない
  2. 属性値の変更は、操作経由に制限できる
  3. 操作名が同じなら、内部構造が変わっても利用する側にそれを意識させない
  4. 属性に不整合な値が入らないよう、操作でチェックできる

エアコンの温度オブジェクトで、カプセル化のメリットを見ていきましょう。

エアコンの設定温度を変更する場合、リモコンなどから、エアコンの「設定温度を変更する」機能
を呼び出します。この時、エアコンの内部構造や制御プログラムなどを知る必要はありません(1)。

そして、それらに直接触れることもありません。ただリモコンで操作するだけです(2)。

もし、後継機種などで「設定温度を変更する」機能の仕組みが変わっても、操作方法が同じなら
そのことで困ることはないでしょう(3)。

さらに温度設定を100度にしたり、零下40度したりはできません。「設定温度を変更する」が、
そのような設定を受け入れないからです(4)。

また、2, 4により、属性を外部から保護することをデータの隠蔽と呼びます。

図B

クラスと継承

クラス

今度は、電源オブジェクトについてみていきます。
前述では、伝げのぶじぇくとの情報(状態)として「電源」、機能として「電源をONにする」と
「電源をOFFにする」を取り上げました。しかし、エアコンの種類によっては、電源をつけると
電気代を表示する機能や、フィルタの汚れ具合を確認し掃除ランプを表示する機能がついている
ものもあります。
これらすべてを電源オブジェクトとして表現したとき、「共通している属性や機能」と
「独自に持っている属性や機能」とに分けられます。

まず、この共通している部分に着目し、土台となるひな型を作成します。
この作業を抽象化と呼びます。また抽象化した結果、オブジェクトを作成するための土台となる

ひな型をクラスと呼びます。

下の図は電源オブジェクト(電気代), 電源オブジェクト(フィルタ)の属性と機能をそれぞれ洗い出した
結果、共通項目が見つかった様子を表しています。

図C

こうしたオブジェクトの共通項目を集め、定義した門が一般的な「電源」クラスとなります。

インスタンス化

クラスは、オブジェクトを作詞得するためのひな型です。つまり設計図にすぎません。
「電源」の設計図ができても、私たちが使える「モノ」ではないのです。
子の設計図であるクラスをもとにして、実際に使うことができる「モノ」にするにすることを
インスタンス化と呼びます。

例えば、下の図Dのようにエアコンを表現するためには、電源クラス、温度クラス、運転クラスが
必要です。それらをまとめるクラスとして、エアコンクラスが必要です。各クラスをもとにインスタンス化することで、それぞれオブジェクト(実際に使うことができる「モノ」)が作成され、実際のエアコンを表現することができます。

また、クラスをもとに複数のインスタンス化を行えば、複数のオブジェクトを作成することができます。
ふたつのエアコンオブジェクトが作成されれば、エアコンオブジェクトを二つ動かすことができます。

これらのオブジェクトは同じクラスから作成されているため、同じ属性・操作を持ちます、しかしエアコンオブジェクトは別々に動きます。

具体的には、上のエアコンオブジェクト二つをエアコンAとエアコンBとしたとき、Aの電源をONにしてBの電源をOFF似しておくこともできます。もちろんエアコンAは設定温度20度、エアコンBは設定温度30度として二つとも動かすことができます。

継承

先ほど説明した電源オブジェクトは、電気代を計算したり、ランプを表示する機能がついていません。
そして、この二つの機能を付けた電源オブジェクトを作成するときに定義する電源クラスを作成する
ためには、新たに電源クラスを作成しなくてもよいのです。

つまり、一度作成した電源クラスを拡張して新しいクラスを定義することができます。
これを継承と呼びます。

オブジェ駆使項では、継承の元となるクラスをスーパークラス(親クラス)と呼び、
拡張したクラスのことをサブクラス(子クラス)と呼びます

継承により定義されたサブクラスは、スーパークラスの属性、操作を受け継ぎます。
そのため、サブクラスでは独自に持つ属性、操作のみを定義するだけで済みます。
サブクラスをインスタンス化すれば、スーパークラスの属性・操作を引き継いだオブジェクトを
が生成されます。

下の図Cのように、共通項目を洗い出し、新たに拡張したクラスを作成する手段として継承
あります。

図C

具体的には下のように実装します。

<電源クラス>

/** 電源クラス */
public class PowerSupply {
  /** 電源 */
  private boolean power;

  /** 電源ON */
  public void switchOn() {
    this.power = true;
  }  

  /** 電源OFF */
  public void switchOn() {
    this.power = false;
  }    
}

<電源クラス(電気代)>

/** 電源クラス(電気代) */
public class ElectricBillPowerSupply {
  /** 電気代 */
  private int electricBill;

  /** 電気代計算 */
  public void calcBill() {
    // 電気代計算の処理
  }
  /** 電気代表示 */
  public void calcBill() {
    // 電気代表示の処理
  }
}

インターフェースとポリモフィズム

私たちは日常でも、たくさんのオブジェクト(モノ)を利用しています。
それらの中には、全く物は別だが、同じ操作方法で利用できるものがあります。

例えば携帯電話はメーカー各社からたくさんの製品が開発・発売されていますが、「電話をかける」
や「電話を切る」という操作はマニュアルを見なくてもできるのではないでしょうか。
また、MDコンポ、CDコンポ、MP3プレーヤーはそれぞれ内部構造も再生する媒体も異なる機械
ですが、「再生」「停止」などの操作に迷わないと思います。

この様に、オブジェクトを利用する側に公開すべき操作をまとめたクラスの仕様のことを
インターフェースと呼びます。

また、共通のインターフェースを持つ操作でも、実際にはオブジェクトごとに振る舞いや動作が異なる
ことをポリモフィズム(多様性・多相性)といいます。

同じ再生ボタンでも、MDコンポ、CDコンポ、MP3プレーヤーの内部で行われることはそれぞれ違います。
もし、MDコンポ、CDコンポ、MP3プレーヤーでインターフェースを統一させていないとしたらどうでしょう。

使用者は、音楽を聴くためのオブジェクトを変える度に違う操作をしなくてはいけません。
これでは面倒で使いづらいでしょう。

プログラムの作成でも同じことが言えます。処理内容は異なるが目的は同じという機能であれば、
オブジェクトに対して、共通のインターフェースを定義し、ポリモフィズムを実現することで、
操作方法が統一され、利便性を高めることができます。ほかのプログラムを再利用することも容易です。

また、後でプログラムを手直ししてでも、機能を呼び出す方法が変わらなければ、
それを呼び出すプログラムには、なにも影響しません。これもインターフェースのメリットの一つです。

でわでわ。。。

関連ページ一覧

Eclipse セットアップ(Mac版)

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜
  5. Java StepUpPrograming〜JavaFXで画面切り替え2ボタン作成〜
  6. Java StepUpPrograming〜JavaFXで画面切り替え3アクション〜
  7. Java StepUpPrograming〜JavaFXで画面切り替え4Pane切り替え〜
  8. Java StepUpPrograming〜JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

  1. JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜
  2. JavaFX + ND4J〜数学への挑戦2: 行列の計算〜
  3. Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜

オブジェクト指向関連ページ

  1. オブジェクト指向の概念1〜OracleDocのチュートリアル1〜
  2. オブジェクト指向の概念2〜クラスとは〜

Java テキスト 〜はじめてのJava コンソール表示〜

はじめてのJava

はじめてJava言語を使用してプログラミングを始めようとしている方向けです。Javaというプログラミング言語はC言語から生まれた言語で、現在(2020-11-11)は多くのアプリケーションで使用されています。具体的には以下のようなものにしようされています。

  1. 証券の取引や銀行のATMなど
  2. Androidアプリ
  3. 大手企業の基幹系システム
  4. icカードなどに組み込むアプリ

挙げればきりがないので、この辺にしておきますが、日本では多くの分野で使用されています。

有名なところだと、マインクラフトでもLWJGLというフレームワーク(Java製)を使用しています。下のような感じで動かせます。

Javaを動かしてみよう

Javaは以下のように、コードの作成~コンパイル~実行と行います。

  1. Javaコードを人力で書く(人間が読めるファイルができる)
  2. コンパイルする(人間が読めないファイルができる)
  3. 作成したプログラム実行

Hello World

まずは写経から入ります。以下のコードを書き写して動かしてみてください。テキストエディタでFirst.javaというファイルを作成します。

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

実行方法は以下の通り

  1. 上のコードを映してFirstCls.javaファイルを作成する
  2. 「ウィンドウズボタン+R」を押下して「cmd」と入力、コマンドプロンプトを開く
    コマンドプロンプト
  3. javacコマンドでクラスファイルを作成する
  4. javac FirstCls.java
  5. javaコマンドで作成したクラスファイルを実行する
  6. java FirstCls

これで、実行できたと思います

サンプルアプリの実行

  1. 以下のZIPファイルをダウンロード
  2. 展開後に/xylophone/src/xylophone/Xylophone.javaをEclipseプロジェクトにコピー、実行できるようにする
  3. Eclipseプロジェクト/resporces/の下に/xylophone/src/xylophone/audioをコピー
  4. 実行 ※エラーが出たら以下の部分を直してみる
    Xylophone.java:67行目にエラーが出たとき
  5. new AudioClip(Xylophone.class.getResource("audio/Note1.wav").toString());
  6. の「audio/Note1.wav」を「/audio/Note1.wav」に修正してみる

1章:ようこそJavaの世界へ

1.1 Javaによる開発の基礎知識

1.1.1 開発の流れ

①ソースコードの作成。

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

②コンパイル
javaファイルをclassファイルに変換することです。下のコマンドを使用します。

javac FirstCls.java

③実行
作成したクラスファイルを実行します。下のコマンドを使用します。

java FirstCls

1.1.2 開発環境の整備

※Eclipseはインストール済みの想定。

外観を変更する

  1. ウィンドウ→設定→一般→外観→色とテーマの順にクリック
  2. ここで好きなテーマを選択する
    ※大半の人がデフォルトで使用している
    色・テーマの設定

文字コードの変更(確認)

  1. ウィンドウ→設定→一般→ワークスペースの順にクリック
  2. 「テキスト・ファイル・エンコード」がUTF-8になっていることを確認

JDKの確認

  1. ウィンドウ→設定→一般→Java→インストール済みのJREの順にクリック
  2. JDKを指定して、使用するJREを決定する
    JRE

1.2 Javaプログラムの基本構造

1.2.1 プログラムの骨格

ルール:クラス名とファイル名は同じ名前にする
「クラスの中にメソッドがある」

/** クラスの説明 */
public class クラス名 {
  /** メソッドの説明 */
  public static void main(String[] args) {
    // 何かしらの処理
  }
}
  • 中かっこ(「{」「}」)のことを「スコープ」と呼びます。スコープで囲っている部分を「ブロック」などと呼んだりします。
  • このスコープ(=「ブロック」)を開いたら(開始したら)、必ず閉じる(終了する)ことを意識する
  • 中かっこ(「{」「}」)で囲っている部分がそれぞれクラスの範囲、メソッドの範囲を決めている

上のサンプルコードでは「クラス名」クラスの中に「メインメソッド」がある

ちなみに、インデント(スペースやタブで位置をずらすこと)を入れないと、とても見にくい

何が見にくいというと、クラスの範囲と、メソッドの範囲を区別しずらいのです。

<インデントなし>

/** クラスの説明 */
public class クラス名 {
/** メソッドの説明 */
public static void main(String[] args) {
// 何かしらの処理
}
}

1.2.2 プログラムの書き方

Java言語(C言語も)の場合は、メインメソッドが起動しますので、クラスの中にメインメソッドを作成する

Javaはメインメソッドが動く

  1. どのようなプログラムを作りたいかを考えます。
  2. プログラムの名前を決めます。
  3. 「クラス名.java」という名前でファイルを作ります。
  4. 下のような、ソースコードの外側を記述します。
  5. /** クラスのJavaDocコメント */
  6. public class クラス名 {
  7. /** メインメソッドのJavaDocコメント */
  8. public static void main(String[] args) {
  9. // 処理の中身:通常のコメント
  10. /*
  11.  * これも通常のコメント、あまり使われない。
  12.  */
  13. }
  14. }
  15. ソースコードの中身を描きます。
  16. System.out.println("Hello World!");

1.2.5 mainメソッドの中身

  • 上の骨格の「何かしらの処理」の部分に処理を描く。
  • 処理は上から下へ進み、1行の中では左から右へ進む
  • セミコロン「;」で1行が終わる
  • ドット「.」は参照呼出し
public static void main(String[] args) {
  System.out.println("Hello World");
}

上のコードは、Systemクラスから変数「out」を呼び出し、メソッド「println()」を呼び出している

練習:SecondProgram

写してください。以下のコードを書いて動かしてください。

public class SecondCls {
  public static void main(String[] args) {
    System.out.println("*** Second Program ***");
    System.out.println("日記ソフト");
    System.out.println("終了します。");
  }
}

実行方法は以下の通り

  1. SecondCls.javaファイルを作成する
  2. 「ウィンドウズボタン+R」を押下してコマンドプロンプトを開く
    コマンドプロンプト
  3. javacコマンドでクラスファイルを作成する
  4. javac SecondCls.java
  5. javaコマンドで作成したクラスファイルを事項する
  6. java SecondCls

1.3 変数宣言の文

1.3.1 変数宣言の文とは?

ズバリ下のように書きます。

  1. 変数の宣言
  2. // 「宣言」:データ型 変数名;
  3. int hensuMei;
  4. 変数の初期化
  5. // 「初期化」データ型 変数名 = 代入するデータ
  6. int dataGata = 0;

1と2の違いは、宣言と同時に値を代入するかしないかです。

==変数の宣言と初期化==

public static void main(String[] args) {
  // 変数の宣言
  int num;
  // 変数の代入
  num = 0;
  // 変数の初期化
  int age = 12;
  // 命令実行の文=メソッドの呼び出し
  System.out.println("対象年齢は" + num + "~" + age + "です。");
}
  • 「変数に値を代入するとき」は「=」を使用する。
  • 「命令の文」は「メソッド呼び出し」を行う

1.3.2 変数の名前(識別子)

==英語では==
変数=Valiable

名前つけのルール

  1. 予約語は使用しない
1 2 3 4 5
abstract assert boolean break byte
case catch char class const
continue default do double else
enum extends final finally float
for goto if implements import
instanceof int interface long native
new package private protected public
return short static strictfp super
switch synchrnized this throw throws
transient try void volatile while
  1. 宣言(初期化)済みの変数名は使用できない
  2. 大文字・小文字は区別される
  3. 変数名・メソッド名はキャメルケースを使用する
  4. // 変数名のキャメルケース(頭を小文字にする)
  5. int myAge;
  6. // メソッド名のキャメルケース(頭を小文字にする)
  7. public void methodName();
  8. クラス名はアッパーキャメルケース
  9. /** クラス名は頭を大文字にする */
  10. public class ClassName {
  11. }
  12. 演算子で使用している文字、予約語は変数名(クラス名)として使用できない

==計算処理==

public static void main(String[] args) {
  // 足し算
  int tashizan = 1 + 1;
  // 引き算
  int hikizan = 1-1;
  // 掛け算
  int kakezan = 1 * 1;
  // 割り算
  int warizan = 1 / 1;
}

1.3.3 データ型

※あくまでも使用例として紹介しています。
==プリミティブ型データの変数型==

  • byte ファイル・ネットワーク通信時に使用
  • int 整数データを格納するのに使用
  • long 大きな整数値を格納するのに使用
  • float 画像処理、3Dモデル描画時に使用
  • double 少数データを格納するのに使用
  • char 1文字分のデータ、シングルクォーテーション「`」で囲む

==参照型データの変数型==

  • String 文字列
  • そのほかJavaAPIや自作のクラス名
  • List<String> list; // List型の変数「list」

1.3.5 定数の利用

変数には値を何度でも代入できるので、定数を使用して値を変更できないようにする。

final データ型 変数名 = 代入するデータ

ルール:定数は大文字の変数名にする

final int OVER_TEN = 0; // 値が10以上を示すフラグ
final int UNDER_TEN = 1; // 値が10以下を示すフラグ


定数の使用例:フラグに使う

public static void main(String[] args) {

}

1.5 練習問題+α

コマンドプロンプト上に下のような図を表示するプログラムを作成してください。
※ 「=」の数が、上下ともに20あります。

<出力する図>

      *
    *   *
  *   *   *
      *
      *
  *   *   *
    *   *
      *

式と演算子

演算子

番号 演算子 意味
1 .(ドット) メソッド、フィールドの呼び出し
2 new クラスのインスタンスを作成するときに使用する
3 == 左右の数値が等しいか判定する(TRUE / FALSEを返す)
4 != 左右の数値が等しくないか判定する(TRUE / FALSEを返す)
5 & ビット演算 AND =「~かつ~」のときTRUE、それ以外はFALSE」
6 | ビット演算 OR =「~または~」のときTRUE、両方ともFALSEの場合はFALSE
7 ? XX : YY 三項演算子 =「論理演算 ? TRUEの時の値 : FALSEの時の値」:

例 String res = 1 == 1 ? "TRUEの場合": "FALSEの場合";

2.2 オペランド

2.2.1 リテラル

実際の値のこと

2.2.2 エスケープシーケンス

バックスラッシュ「\」もしくは、「¥」円記号(半角)をつけた文字のことでメタ文字を「文字」として使いたいときに使用する。

<例>

// 「"」は文字列を加工形で表示するためにエスケープシーケンスを使用する
// ※「"」を文字列として使用したいときは「エスケープ」する
String moji = "Javaのはじめの\"J\"は1文字目";

2.3 評価のしくみ

下のような式があったとします。
「1 + 5 -3」この式をプログラムで書くと次のコードになります。

public static void main(String[] args) {
  // 上の計算式
  int answer = 1 + 5 - 3;
}

このようなときに、処理の順序、「1 + 5」と「5 - 1」の評価はどのように行われるか?

左から順に評価していきます

つまり、以下の順序です。

  1. 1 + 5の計算結果を出す
  2. 上の結果に」「-1」する

==掛け算は先に処理を行う==
つまり以下のような優先順位で評価します。

  1. 「掛け算・割り算」→「足し算・引き算」の順序
  2. 左から順に評価

まとめると

  1. 「掛け算・割り算」→「足し算・引き算」の順序で評価
  2. 「=」以外の演算子は、左から順に評価
  3. 「=」は右から評価
問題+α

以下のコードの場合、どのような順序で評価されるでしょうか?

System.out.println("Hello World!");

実行順序として正しいものを、1~4の中から選びなさい

  1. Systemクラスの公開フィールド変数out(PrintStreamクラス)を取得
  2. フィールド変数out(PrintStreamクラス)のメソッドprintln()を評価(呼び出している)
  3. メソッドprintln()を取得
  1. フィールド変数out(PrintStreamクラス)のSystemを評価(呼び出している)

2.4 演算子

2.4.1 算術演算子

演算子 機能 優先順位
+ 足し算
- 引き算
* 掛け算
/ 割り算

2.5 型の変換

2.5.3 強制的な型変換(キャスト)

「int型」を「double型」に変換するというような形のキャスト
<具体例>

int num = 10;
// 強制的な型変換
double dd = (doubble) num;

// 下のやり方はエラーになる
// int num1 = (int) "10";

// 型をメソッドを使用して変換している
String tmp = String.valueOf(num);

// Stringが票差化された(左に文字列が先にある)あとであれば
// intやdoubleも文字列として評価される(自動キャスト)
System.out.println("aaaa" + 10.1);

異なる型同士の算術演算

返却値(左側の変数型)は、大きいほうの型のデータ型が優先される

2.6 命令実行の文

2.6.5 乱数を生み出して代入する命令

// 3を上限値として乱数を生成する
int r = new java.util.Random().nexInt(3);

上にあるような「java.XXX.XXX」のようなパッケージはJDKの中にあるライブラリに定義されています。
そして、それらAPI群の使い方に関してはJavaDocに書かれています。

2.7 まとめ

命令の実行はメソッド呼び出しのこと

ここまで、学習して来たら簡単な処理を作ることができると思います。そしたら、何か作ってみたいのも人情

下のリンク先に問題集を作りました。

Java 練習問題集 ~基本レベル1の問題~

でわでわ。。。

Java Basic API ~Java API Stringクラスを理解するwith JUnit~

イントロダクション

Javaでプログラミングを初めて慣れたころにJavaAPIに触れることが多くなると思います。

よくある「プログラミング練習問題」などで、文字列操作を行うことがあると思います。

この様な時に使用するのがStringクラス手に定義してあるメソッド群だと思います。しかし、説明書きしているJavaDocが難しく理解するのが難しいことが多いと思います。

この解決方法として、動かしてみるというのが手っ取り早い方法の一つだと思いますので、手っ取り早い方法を記載いたします。

JavaSEで提供しているクラスを理解

簡単にプログラムを動かす方法として、IDE(Eclipseを使用します)で動かしてみるのが手っ取り早い方法ですが、如何せんメインメソッドを使用していると毎回コードを書き直さなくてはいけないので面倒です。

なので、以下の方法を提案したく思います。

JUnitを使う

JUnitはテストツールとして使用することが多いもの(フレームワーク)です。これを使用すれば下のように簡単に、いくらでもコードを動かせます。

下のは、String#equalsメソッドをテストしたものですが、「@Test」をつけたメソッドはすべて実行されるので、どんどん作成して実行すればよいのです。
<例>

public class StringTest {

    /** String#equalsのテスト */
    @Test
    public void test01() {
        String st = "aaa";
        String s1 = "aaa";
        String s2 = "bbb";
        String s3 = "ccc";

        if (st.equals(s1)) {
            System.out.println("st == s1");
        } else {
            System.out.println("st != s1");
        }

        if (st.equals(s2)) {
            System.out.println("st != s2");
        } else {
            System.out.println("st == s2");
        }

        if (s3.equals(s1)) {
            System.out.println("s3 == s1");
        } else {
            System.out.println("s3 != s1");
        }
    }
}

実行結果

テストを増やす

StringクラスのJavaDocを見るとよく使うメソッドがあるので、それを紹介するついでに上のテストケースで実行します。
実際の作業を動画にしました。参考にどうぞ。

そして、実行するときにJUnitの設定をする必要があります。

Eclipseを使用しているならば、下のような手順ですぐに使用できます。

JUnitの設定

  1. Eclipeのプロジェクトを右クリック
  2. プロパティを選択
  3. ライブラリの追加をクリック
  4. JUnitを選択し次へ
  5. 次の画面では、完了をクリック

下のように、ライブラリが追加されているはずです。

String#substring

JavaDocでStringクラスを見るとStringクラスの中に定義されているメソッド群があります。説明がちょっと難しく理解に苦しむことがありますが、これを動かしてみれば、ドキュメントの内容がわからなくても問題ありません。逆に、ドキュメントの内容が理解できたりします。

具体的には、上の動画でも実行していますが、下のように実行します。

  1. JavaDocで試したいメソッドを見つける
  2. 対象のメソッドのテストケースを作成する
  3. テストを実行して挙動を確認する

作成したコード(テストケース)は下のような形です。

public class StringTest {

    /** String#equalsのテスト */
    @Test
    public void test01() {
        String st = "aaa";
        String s1 = "aaa";
        String s2 = "bbb";
        String s3 = "ccc";

        if (st.equals(s1)) {
            System.out.println("st == s1");
        } else {
            System.out.println("st != s1");
        }

        if (st.equals(s2)) {
            System.out.println("st != s2");
        } else {
            System.out.println("st == s2");
        }

        if (s3.equals(s1)) {
            System.out.println("s3 == s1");
        } else {
            System.out.println("s3 != s1");
        }
    }

    /**
     * JavaDocをみて、入力(引数)と出力(返却値)を確認後、実装して動かしてみる。
     * {@link String#substring(int)}のテストケース
     */
    @Test
    public void testSubstring() {
        String target = "abcdefg";
        // 2番目の文字を取得する
        String res = target.substring(1, 2);
        System.out.println("2番目の文字: ");
        // 取得結果が正しいか確認
        assertEquals("b", res);
        // 一番初めの文字を取得
        String res1 = target.substring(0, 1);
        assertEquals("a", res1);
        // 一番最後の文字
        String res2 = target.substring(target.length() -1, target.length());
        assertEquals("g", res2);
        // 初めから4文字分を切り出す
        String res3 = target.substring(0, 4);
        assertEquals("abcd", res3);
    }
}

equalsは調べなくてもわかると思いますが、substringはどうでしょうか?
ドキュメントには、下のような説明があります。

この文字列の部分文字列である文字列を返します。部分文字列は、指定されたbeginIndexから始まり、インデックスendIndex - 1にある文字までです。したがって、部分文字列の長さはendIndex-beginIndexになります。

とりあえずは、第一引数に開始、第二引数に終了のインデックス(数値)を設定します。

String res3 = target.substring(0, 4);

実行した結果がどのように取得できるか?これを確かめます。

assertEquals("abcd", res3);

実行後に、いまいちわからない場合は、値を変えてみます。上記の「0, 4」は初めから4文字を取得する場合ですが、2文字目から4文字目までを取得する場合はどうでしょうか?下のように「2, 4」と設定すれば想定通りに動くでしょうか?

String res3 = target.substring(0, 4);

それはテストしてみれば一発です。

assertEquals("取得するであろう値", 結果を格納した変数);

この様な形で、実装すればJavaAPIの理解を深めることができます。

色々なクラスを理解し、技術の幅を広げるのに役に立つと思います。

でわでわ。。。

関連ページ一覧

Eclipse セットアップ(Mac版)

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseにCDTをインストール〜
  3. Setup OpenGL with Java〜JOGLを使う準備 for Eclipse〜
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 〜GitからソースをPullしよう〜
  3. IntelliJ IDEA Git〜Gitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜

Java Basic Class Inheritance ~クラスの継承関係を作る2~

イントロダクション

前回作成したクラスを使用して実装してきます。

作成したクラスは以下のものです。

  • Parent: 親クラス
  • ChildAni: 子クラス
  • ChildOtoto: 子クラス
  • MainFamilly: メインメソッドを持っているクラス

実行するクラスは「MainFamilly」クラスのメインメソッドです。

とりあえずは実行すると下のようなイメージで動きます。

そして、抽象クラスを追加しました。クラス名は「Gosenzo(ご先祖)」です、

感の良い方は気がついているかもしれませんが、以下のような系譜ができています。

  1. ご先祖
  2. あに、弟

ただし、抽象クラスのメソッド「血継限界」に関しては実行していません。単純に実装するのを忘れていました。
ソースに関してはこちらにあるので、ご自由に動かして見てください。※カスタムして遊んでもよし。

継承関係で遊ぶ

勝手に設定を作ってみます。

ご先祖から因縁を持っている魔物、スライム討伐が稼業になっている家族の物語、細かい話はスッ飛ばして宿敵スライムと対峙する家族であった。。。

というわけで、スライムとの戦いを始めたいと思います。

現在作成済みのクラスは上記のとおり4クラスあります。
そして、ご先祖クラスには、フィールドが「秘伝のタレ」しかありません。

なので、RPGっぽく作成するため以下のプロパティ(フィールド)を追加します。本当は「プレーヤー」クラスの方が良いのですが。。。

いや、プレーヤークラスを作成しましょう。
※GetterとSetterは省略しています。GetterSetterの作成方法は下の動画を参照ください。

<プレーヤークラス>

public class Player {
    /** 名前 */
    private String name;
    /** レベル */
    private int level;
    /** 生命力 */
    private int HP;
    /** 特殊能力(技能)の使用時に消費 */
    private int MP;
    /** 攻撃力 */
    private int attack;
    /** 防御力 */
    private int diffence;
    /** 戦闘可能フラグ */
    private boolean canBattle;

    /**
     * コンストラクタ。
     * @param name
     */
    public Player() {
        this.name = "桃太郎";
        // レベル1の設定
        setLevel(1);
        setHP(20);
        setMP(10);
    }

    /**
     * コンストラクタ。
     * @param name
     */
    public Player(String name) {
        this.name = name;
        // レベル1の設定
        setLevel(1);
        setHP(20);
        setMP(10);
    }
}

このクラスをご先祖クラスの親にします。

public abstract Gosenzo extends Player { ... }

そうすると、MainFamillyのメインメソッドで、HPなどの設定ができるようになります。
<MainFamilly>

public class MainFamilly {
    public static void main(String[] args) {
        // 標準入力の受付
        Scanner scan = new Scanner(System.in);
        System.out.println("**** Game Start ****");
        // 親クラスのインスタンス
        Parent parent = new Parent();
        // HP
        parent.setHP(50);
        //戦闘可能フラグ
        parent.setCanBattle(true);
        //攻撃力
        parent.setAttack(20);
        //防御力
        parent.setDiffence(15);

        // 子クラス(あに)のインスタンス
        ChildAni ani = new ChildAni();
        // HP
        parent.setHP(40);
        //戦闘可能フラグ
        parent.setCanBattle(true);
        //攻撃力
        parent.setAttack(20);
        //防御力
        parent.setDiffence(15);
        // 子クラス(弟)のインスタンス
        ChildOtoto ototo = new ChildOtoto();
        // HP
        parent.setHP(30);
        //戦闘可能フラグ
        parent.setCanBattle(true);
        //攻撃力
        parent.setAttack(20);
        //防御力
        parent.setDiffence(15);
        while (true) {
            String input = scan.nextLine();
            if ("parent".equals(input)) {
                parent.say();
            } else if ("ani".equals(input)) {
                ani.say();
            } else if ("ototo".equals(input)) {
                ototo.say();
            } else {
                System.out.println("処理を終了します。");
                break;
            }
        }
    }
}

モンスターを作成する

モンスターといえど、HPなどはあるので、プレーヤークラスの子クラスとして作成することにします。
そして、「話をするかどうか?」のフラグを追加することにしました。
<モンスタークラス>

public class Monster extends Player {
    /** 話をするかどうか */
    private boolean isTalk;

    /**
     * @return the isTalk
     */
    public boolean isTalk() {
        return isTalk;
    }

    /**
     * @param isTalk the isTalk to set
     */
    public void setTalk(boolean isTalk) {
        this.isTalk = isTalk;
    }
}

そして、具体的なモンスタークラスを作成します。
つまり、スライムクラスを作成します。

<スライムクラス>

public class Slime extends Monster{
    public Slime() {
        this.setCanBattle(true);
        this.setHP(10);
        this.setMP(5);
        // 攻撃力
        this.setAttack(5);
        // 防御力
        this.setDiffence(5);
    }
}

ここまで作成したら、次は戦闘シーンを作成したくなると思います。

頑張って見てください。

自分が作成したものは次回、記事に記載いたします。

関連ページ一覧

Eclipse セットアップ(Mac版)

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜