talosのプログラミング教室

はじめてのJava ~パッケージとインポート編~

f:id:talosta:20200331181701p:plain


今回はJavaのパッケージとインポートについて説明します。

パッケージはクラスインタフェースの集まりです。

パッケージを使うことでクラスインタフェースの管理が容易になります。

作るプログラムが大規模になるほどよく利用することになるので、しっかり学習しましょう。

パッケージの作り方

「package」を使います。

このときパッケージ名とソースコードがあるディレクトリ名は同じでなければなりません。

例えばパッケージ名を

package dir.pack;

とした場合は、このソースコードは「dir/pack」になければいけません。

以下の例ではパッケージ名が「pack」なので、packディレクトリの中にこれらのソースコードを置いています。

package pack;

public class Class1 {
    public void method1() {
        System.out.println("method1");
    }
}
package pack;

public class Class2 {
    public void method2() {
        System.out.println("method2");
    }
}
package pack;

public class Pack {
    public static void main(String args[]) {
        Class1 c1 = new Class1();
        c1.method1();
        Class2 c2 = new Class2();
        c2.method2();
    }
}

このパッケージを構築するには、packの親ディレクトリに移動し次のコマンドを実行します。

javac pack\*.java

さらに、このコマンドによって作成されるpack.classファイルは以下のコマンドで実行します。

java pack.Pack

出力は以下のようになります。

method1
method2

パッケージのインポート

「import」を使います。

import pack.*;

class ImportSample {
    public static void main(String args[]) {
        Class1 c1 = new Class1();
        c1.method1();
    }
}
// 出力
method1

「*」を使うことでpackのパッケージ全体をインポートできます。

今回はClass1しか使っていないので、

import pack.Class1

とすることもできます。

ディレクトリ構成は以下のようになっています。

root
  |--ImoprtSample.java
  |--pack
      |--Class1.java
      |--Class2.java
      |--Pack.java

本来、ImportSample.javaからはClass1クラスを認識できません。

しかし、importを使うことでそれを可能にします。

おわりに

今回はJavaのパッケージとインポートについて説明しました。

次回は例外処理について説明します。

【情報処理技術者試験】中止が決定!返金と代替試験は?

更新日 2020年5月17日

新型コロナウイルス感染症の拡大防止のため、令和2年度春期情報処理技術者試験が中止になりました。

そこで気になるのは「返金をしてもらえるのか」、「代替試験が行われるのか」ですね。

今公開されている情報と今までの非常事態時の対応からの予想を書いていきます。

情報処理技術者試験には
・情報セキュリティマネジメント試験
基本情報技術者試験
応用情報技術者試験
・プロジェクトマネージャ試験
データベーススペシャリスト試験
・エンベデッドシステムスペシャリスト試験
・システム監査技術者試験
が含まれます。ITパスポートに関してはこれらとは異なった対応となっています。

返金について

返金はしてもらえます。

返金のスケジュールとしては、
・6月下旬に返金の手続きについて郵送等で通知
・7月上旬に返金を開始
とのことです。

返金方法は以下のようになっています。

返金方法
https://www.jitec.ipa.go.jp/1_00topic/topic_20200324.htmlより


代替試験について

現時点では未定です。

東日本大震災のときは被害が日本の広域にわたったため代替試験が実施されました。

今回はさらに影響範囲が大きいため、今の状況が早期に収束すれば行われるかもしれません。

一部免除の延長について

 令和2年度春期試験において一部免除(基本情報技術者試験の午前試験免除、高度試験、情報処理安全確保支援士試験の午前Ⅰ試験免除)を受験申込み時に申請していた方につきましては、令和2年度春期試験実施の取りやめ(中止)によって不利とならないよう、一部免除申請が可能となる期間を延長いたします。

IPA 独立行政法人 情報処理推進機構:情報処理技術者試験:令和2年度春期情報処理技術者試験・情報処理安全確保支援士試験の取りやめ(中止)につい

とのことでした。

詳細はまだ決まっていませんが、今までの例を見ると、

基本情報技術者試験の午前試験免除→次回まで延長
②高度試験の午前1試験免除→1期分延長

となるでしょう。

ただし、今年は秋期も中止になる可能性があるので、そうなった場合はさらに延長になると思います。

おわりに

情報が更新されたら追記します。

はじめてのJava ~抽象クラスとインタフェース編~


今回はJava抽象クラスインタフェースについて説明します。

この2つはとても似ている機能なので、まとめて紹介します。

初心者が混同しやすいこの2つですが、使える場面が異なります。

抽象クラスとインタフェースはなぜ必要なのか

前回、継承について説明したときは、継承することによってコードを効率的に再利用できると言いました。

talosta.hatenablog.com

しかし、これが別のプロジェクトになったらどうなるでしょうか?

メソッドの名前が同じでも中身が同じとは限りません。


例を挙げて考えてみましょう。

とある企業Aは3つのプロジェクトを同時進行しています。

その3つのプロジェクトはコードの再利用が可能であることがわかりました。

優秀なプログラマBさんは、いずれでも使うと思われるClass1クラスを作っておくことにしました。

Class1クラスではとある計算をするcalc()メソッドを定義します。

しかし、詳細は未定であるためメソッドの中身までは実装できません。

そこでメソッドの中身を空にしておくことにしました。

Bさんはこのクラス継承されることを想定しています。

class Class1 {
    void calc() {
    }
}

数日後、それぞれのプロジェクトが進行し、どちらも開発フェーズに入りました。


プロジェクト1にアサインされている適当プログラマCさんはClass1 のコードを見てこう思います。

「このメソッドはなにもしないメソッドなんだ」

詳細が決定してから実装するはずであった箇所を、Cさんは勘違いして無視してしまいました。


また、プロジェクト2にアサインされている多忙プログラマDさんは設計書をよく読んだので、Class2クラスでClass1クラスを継承し、calc()メソッドをオーバーライドしなくてはいけないことを知っています。

しかし、疲れからかオーバーライドするのを忘れてしまいました。


さらにプロジェクト3にアサインされている新人プログラマEさんは、Class1クラスを以下のように使いました。

class Main1 {
    public static void main(String args[]) {
        Class1 c1 = new Class1();
        // 以下省略
    }
}

いまいち継承の使い方がわからず、インスタンスを作ってしまいました。


これらのような失敗を起こさないため、抽象クラスインタフェースを使います。

それでは、それぞれの使い方を見ていきます。

抽象クラスの使い方

abstract class Animal {
    abstract void walk();
}

classの前に「abstract」を付けます。

試しにオーバーライドをせずにコンパイルしてみましょう。

class Dog extends Animal {
    void bark() {
        System.out.println("ワン");
    }
}
// エラーメッセージ
Dog.java:1: エラー: Dogはabstractでなく、Animal内のabstractメソ 
ッドwalk()をオーバーライドしません
class Dog extends Animal {
^
エラー1個

しっかりエラーが出ました。

これでCさんとDさんの失敗は解決できたことがわかります。


次に、Animalクラスをインスタンス化してみます。

class AnimalMain {
    public static void main(String args[]) {
        Animal dog = new Animal();
    }
}
// エラーメッセージ
AnimalMain.java:3: エラー: Animalはabstractです。インスタンスを 
生成することはできません
        Animal dog = new Animal();
                     ^
エラー1個

こちらもエラーになり、Eさんの失敗は解決しました。

インタフェースの使い方

では、インタフェースはどのようなときに使うのでしょうか?

抽象クラスに対するインタフェースの特徴は多重継承できる点です。

仮にクラス多重継承ができるとしましょう。

クラスの多重継承

WolfクラスとHumanクラスを継承した狼人間はどのように動くのでしょうか?

両方から異なる動作のmove()メソッドを継承するため、不具合が起きてしまいます。

一方で、インターフェース多重継承はどうでしょうか。

インタフェースの多重継承

オーバーライドによって独自のmove()メソッドを実装することができます。

これで多重継承の問題は解決です。


それではインタフェースの使い方を見ていきましょう。

interface Wolf {
    void move();
}
interface Human {
    void move();
}
class WolfMan implements Wolf, Human {
    public void move() {
        System.out.println("walk:bipedal, run:quadruped");
    }
}
class WolfManMain {
    public static void main(String args[]) {
        WolfMan wm = new WolfMan();
        wm.move();
    }
}
// 出力
walk:bipedal, run:quadruped

インタフェースには「interface」を付け、実装側では「implements」で使用するインタフェースを明示します。

おわりに

今回はJava抽象クラスインタフェースについて説明しました。

次回はパッケージについて説明します。

はじめてのJava ~継承編~

f:id:talosta:20200328175524p:plain

今回はJava継承について説明します。

継承オブジェクト指向でとても重要な機能なのでしっかり覚えましょう。

継承とは

継承とはあるクラスの状態と動作を別のクラスが引き継ぐことです。

継承をすることによって、コードの効果的な再利用ができるようになります。

例えば消防車とトラックは両方とも車です。

したがって赤い文字の部分は共通しています。

f:id:talosta:20190612134628p:plain

そこで、車クラスを実装することで、消防車クラスとトラッククラスの実装が楽になります。

f:id:talosta:20190612135953p:plain

車クラスのような継承される側のクラスをスーパークラス、消防車クラスやトラッククラスのような継承する側のクラスをサブクラスと言います。

Javaにおける継承の方法

まず車クラスを用意しました。

class Car {
    int tire;
    int handle;
    int accelerator;
    int brake;

    void move() {
        System.out.println("The car is moving.");
    }

    void turn() {
        System.out.println("The car is turning.");
    }
}

継承は「extends」によって行います。

class FireTruck extends Car {  // 継承
    int hose;

    void sprayWater() {
        System.out.println("The fire truck is spraying the water.");
    }
}
class Main {
    public static void main(String args[]) {
        FireTruck ft = new FireTruck();

        ft.move();
        ft.turn();
        ft.sprayWater();
    }
}
// 出力
The car is moving.
The car is turning.
The fire truck is spraying the water.

MainクラスではFireTruckクラスのオブジェクトを生成していますが、スーパークラスのmove()メソッドとturn()メソッドも呼び出すことができていますね。

オーバーライド

先程はFireTruckクラスのオブジェクトを生成し、Carクラスのメソッドを呼び出しました。

しかし、出力は「The car is moving.」となっています。

これだと消防車なのかわかりません。

そこでオーバーライドをします。

オーバーライドとはスーパークラスメソッドサブクラスメソッドによって上書きすることです。

オーバーライドをすることで、スーパークラスメソッドサブクラスオブジェクトから見えなくなります。

オーバーライドのやり方を見てみましょう。

class FireTruck extends Car {
    int hose;

    void sprayWater() {
        System.out.println("The fire truck is spraying the water.");
    }

    // オーバーライド
    void move() {
        System.out.println("The fire truck is moving.");
    }

    // オーバーライド
    void turn() {
        System.out.println("The fire truck is turning.");
    }
}
// 出力
The fire truck is moving.
The fire truck is turning.
The fire truck is spraying the water.

サブクラスメソッドを再定義するだけですね。

これでCarクラスで定義したメソッドもFireTruckクラス用に修正することができました。


ちなみにオーバーライドに似た言葉でオーバーロードというものがあります。

こちらの記事で説明していますので、知らない方は読んでみてください。

talosta.hatenablog.com

おわりに

今回はJava継承について説明しました。

次回は抽象クラスインタフェースについて説明します。

はじめてのJava ~クラスとメソッド編~

f:id:talosta:20200404182056p:plain

今回はJavaクラスメソッドについて説明します。

オブジェクト指向の本質とも言えるのでしっかり学習しましょう。

クラスの定義

クラスは次のように定義します。

class Human {
    double height;
    double weight;
    int age;
}

Humanクラスを定義し、その中でheightとweight、ageというインスタンス変数を定義しました。

オブジェクトの作成

オブジェクトの作成はnew演算子によって行います。

class Yamada {
    public static void main(String args[]) {
        Human yamada = new Human();  // オブジェクト作成
        
        yamada.height = 178.5;
        yamada.weight = 71.8;
        yamada.age = 26;

        System.out.println("Yamada's height: " + yamada.height);
        System.out.println("Yamada's weight: " + yamada.weight);
        System.out.println("Yamada's age: " + yamada.age);
    }
}
// 出力
Yamada's height: 178.5
Yamada's weight: 71.8
Yamada's age: 26

インスタンス変数へのアクセスは「オブジェクト名.インスタンス変数名」でできます。

コンストラクタの追加

コンストラクタインスタンス生成時に実行されるメソッドです。

初期化などの処理を行います。

コンストラクタの名前はクラス名と同じにします。

class Human {
    double height;
    double weight;
    int age;

    // コンストラクタ
    Human(double height, double weight, int age) {
        this.height = height;
        this.weight = weight;
        this.age = age;
    }
}
class Tanaka {
    public static void main(String args[]) {
        Human tanaka = new Human(179.3, 69.0, 23);

        System.out.println("Tanaka's height: " + tanaka.height);
        System.out.println("Tanaka's weight: " + tanaka.weight);
        System.out.println("Tanaka's age: " + tanaka.age);
    }
}
// 出力
Tanaka's height: 179.3
Tanaka's weight: 69.0
Tanaka's age: 23

ちなみに「this」は実行中のオブジェクトを指します。

インスタンスメソッドの定義と呼び出し

インスタンスメソッドは次のように定義し、呼び出します。

class Human {
    double height;
    double weight;
    int age;
    int steps;

    Human(double height, double weight, int age, int steps) {
        this.height = height;
        this.weight = weight;
        this.age = age;
        this.steps = steps;
    }

    // インスタンスメソッドの定義
    void walk() {
        steps++;
    }
}
class Saito {
    public static void main(String args[]) {
        Human saito = new Human(167.9, 67.3, 30, 0);

        for(int i = 0; i < 10; i++) {
            saito.walk();  // インスタンスメソッド呼び出し
        }
        
        System.out.println("Saito's step: " + saito.steps);

    }
}
// 出力
Saito's step: 10

メソッドの定義はコンストラクタの定義に似ていますが、メソッド名の前に戻り値を書くところが異なります。

呼び出しは「オブジェクト名.メソッド名(引数)」というように行います。

オーバーロード

同じ名前で引数の違うメソッドコンストラクタを複数定義することができます。

これをオーバーロードと言います。

使い方を見てみましょう。

class Human {
    double height;
    double weight;
    int age;
    int steps;

    Human(double height, double weight, int age, int steps) {
        this.height = height;
        this.weight = weight;
        this.age = age;
        this.steps = steps;
    }

    void walk() {
        steps++;
    }

    // オーバーロード
    void walk(int stepNum) {
        steps += stepNum;
    }
}
class Saito {
    public static void main(String args[]) {
        Human saito = new Human(167.9, 67.3, 30, 0);

        for(int i = 0; i < 10; i++) {
            saito.walk(2);
        }
        
        System.out.println("Saito's step: " + saito.steps);

    }
}
// 出力
Saito's step: 20


ちなみに似たような言葉にオーバーライドという言葉があります。

こちらの記事で説明していますので、知らない方は読んでみてください。

talosta.hatenablog.com

おわりに

今回はJavaクラスメソッドについて説明しました。

次回は継承について説明します。

はじめてのJava ~制御文編~

f:id:talosta:20200331181701p:plain

今回はJava制御文を紹介します。

種類は多いですが意味のわかりやすい名前を付けられているので、簡単に覚えられると思います。

ぜひ使いながら覚えてください。

if文

条件分岐をする制御文です。

以下のように使います。

class Statement1 {
    public static void main(String args[]) {
        int a = 0;
        if(a == 0) {
            System.out.println("true");
        }
    }
}
// 出力
true

if文は( )の中がtrue(真)のときはその後の{ }の中を実行し、false(偽)のときは実行しません。

{ }がない場合は直後の1文だけが実行されます。

「a == 0」というのは「aが0に等しい」ということを表しています。

Javaの場合、「a = 0」と書くとaに0を代入するという意味なので注意しましょう。

以下は関係演算子の一覧です。


関係演算子 意味
== 左項と右項が等しい
!= 左項と右項が等しくない
> 左項が右項より大きい
< 左項が右項より小さい
>= 左項が右項以上
<= 左項が右項以下


if-else文

ifの後にelseを追加することで、if( )の中が偽の場合の処理を指定できます。

次のように使います。

class Statement2 {
    public static void main(String args[]) {
        int a = 1;
        if(a == 0) {
            System.out.println("true");
        } else {
            System.out.println("false");
        }
    }
}
// 出力
false

また、elseとifを組み合わせることで3つ以上に条件分岐させることもできます。

class Statement3 {
    public static void main(String args[]) {
        int a = 2;
        if(a == 0) {
            System.out.println("0");
        } else if(a == 1) {
            System.out.println("1");
        } else {
            System.out.println("a is neither 0 nor 1.");
        }
    }
}
// 出力
a is neither 0 nor 1.

for文

for文は繰返しを行う制御文です。

以下のように使います。

class Statement4 {
    public static void main(String args[]) {
        for(int i = 0; i < 5; i++) {
            System.out.println(i);
        }
    }
}
// 出力
0
1
2
3
4

( )の中にセミコロン区切りで3つの文を書きます。

1つ目は初期化です。

上の例ではiを0で初期化しています。

2つ目は繰返しを続ける条件です。

上の例ではiが5以上になるまで繰返しを続けるように指定しています。

5以上になったら繰返しは終わるので5は出力されていません。

3つ目は増減幅です。

上の例では繰返しが1回終わるごとに、iを+1しています。

while文

while文も繰返しを行う制御文です。

while文は以下のように使います。

class Statement5 {
    public static void main(String args[]) {
        int i = 0;
        while(i < 5) {
            System.out.println(i);
            i++;
        }
    }
}
// 出力
0
1
2
3
4

for文の例と同じことをしたプログラムです。

これだけ見るとfor文のほうがすっきりしていますが、while文のほうが適している状況もあります。

それは繰返しの条件が数値ではないときです。

例えば、キーボードで入力を受け付け、ある文字が入力されるまでは処理を続けるという場合。

// whileを用いた場合
import java.io.*;

class Statement6 {
    public static void main(String args[]) {
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(isr);

            while(br.readLine().equals("a")) {   // 入力受付
            }
            System.out.println("end");

            br.close();
        }
        catch(Exception e) {
            System.out.println("Exception: " + e);
        }
    }
}
// forを用いた場合
import java.io.*;

class Statement7 {
    public static void main(String args[]) {
        String s = "";

        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(isr);

            for( ; ; ) {    
                s = br.readLine();
                if(!s.equals("a")) {
                    break;
                }
            }
            System.out.println("end");

            br.close();
        }
        catch(Exception e) {
            System.out.println("Exception: " + e);
        }
    }
}

whileを用いたほうがすっきりしていますよね。

このように上手く使い分けることで見やすいコードを書くことができます。

do-while文

whileでは条件によっては1回も{ }内の処理を行わず終了することがありますが、do-whileでは必ず1回は{ }内の処理を行います。

例えば、

class Statement8 {
    public static void main(String args[]) {
        int i = 10;
        while(i < 5) {
            System.out.println(i);
            i++;
        }
    }
}
// 出力

上記のコードでは、iは最初から10でwhileの条件が i < 5 なので、{ }の中の処理は一度も行われずに終了します。

これをdo-whileにすると、

class Statement9 {
    public static void main(String args[]) {
        int i = 5;
        do {
            System.out.println(i);
            i++;
        } while(i < 5);
    }
}
// 出力
5

と一度だけ{ }の中の処理が行われていることがわかります。

break文

break文はループを強制終了させることができます。

break文は以下のように使います。

class Statement10 {
    public static void main(String args[]) {
        for(int i = 0; i < 10; i++) {
            System.out.println(i);
            if(i == 5) {
                break;
            }
        }
    }
}
// 出力
0
1
2
3
4
5

iが5に等しいときに強制終了したため、それ以降は出力されません。

continue文

continue文はそれ以降の処理をスキップし、次の繰返しに移ります。

言葉ではわかりにくいと思うので、コードをしっかり読んで理解してください。

class Statement11 {
    public static void main(String args[]) {
        for(int i = 0; i < 10; i++) {
            if(i == 5) {
                continue;
            }
            System.out.println(i);
        }
    }
}
// 出力
0
1
2
3
4
6
7
8
9

iが5に等しいときはcontinue以降の処理をスキップするため、5だけ表示されていません。

switch文

switch文はif文の複数バージョンです。

if文でもelseを使えば複数に条件分岐できますが、見栄えがよくありません。

3つ以上に分岐するときはswitch文を使うとよいでしょう。

switch文は以下のように使います。

class Statement12 {
    public static void main(String args[]) {
        int i = 3;
        switch(i) {
            case 1:
                System.out.println("one");
                break;
            case 2:
                System.out.println("two");
                break;
            case 3:
                System.out.println("three");
                break;
        }
    }
}
// 出力
three

breakがないとそれ以降の処理をすべて実行してしまいますので、忘れないようにしましょう。

おわりに

今回はJava制御文を説明しました。

次回はクラスメソッドについて説明します。

はじめてのJava ~代入と計算編~

f:id:talosta:20200330151413p:plain

今回はJavaを使って様々な計算を行います。

また、代入の仕方も同時に説明します。

一般的な算数とは少し違うので初めての方は戸惑うかもしれませんが、簡単なので気楽にいきましょう。

代入

Javaを含め、多くのプログラミング言語では以下の4行目のように代入を行います。

class Substitute1 {
    public static void main(String args[]) {
        int x;
        x = 5;
        System.out.println(x);
    }
}
/* 出力 */
5

intは基本データ型の1つで、32ビット符号付整数です。

難しいので今は整数とだけ覚えておけば大丈夫です。


また、他の変数を経由して代入することもできます。

class Substitute2 {
    public static void main(String args[]) {
        char x, y;
        y = 'a';
        x = y;
        System.out.println(x);
    }
}
/* 出力*/
a

charも基本データ型の1つで、16ビットUnicodeキャラクタデータです。

こちらも文字を表すことを覚えておけば大丈夫です。

文字列ではないのでそこだけ注意してください。

ちなみに「/* */」はコメントアウトと呼ばれ、プログラム中に記述してもコンパイラは読み飛ばします。

「/* */」は複数行「//」は1行のコメントを書くことができます。

計算

計算は以下のように行います。

class Calc1 {
    public static void main(String args[]) {
        double x, y, z;
        x = 3.0;
        y = 2.0;
        z = x + y;
        System.out.println(z);
    }
}
/* 出力 */
5.0

普通の計算と同じですね。

足し算は「+」、引き算は「-」、掛け算は「*」、割り算は「/」で行います。

doubleは64ビット符号付浮動小数点数です。

小数点以下も格納できることを覚えておけば大丈夫です。


次に少し特殊な計算をいくつか紹介します。

class Calc2 {
    public static void main(String args[]) {
        int x, y, z;
        x = 3;
        y = 2;

        // No.1
        z = x % y;
        System.out.println(z);

        // No.2
        x = x + y;  // x += y と同じ
        System.out.println(x);
    }
}
/* 出力 */
1
5

No.1の「%」は割り算の余りを計算する算術演算子です。

3 / 2 の余りは1なので出力は1になっています。


No.2の計算は一般的な計算では間違ってますが、プログラミングでは許されます。

x + y を計算し、それをxに代入します。

もともとのxの値は3、yの値は2なので、3 + 2 を計算し、5をxに代入しているので出力も5になっています。

また、この式は x += y とも書けます。

「-=」、「*=」、「/=」、「%=」もあるので、同時に覚えておきましょう。

class Calc3 {
    public static void main(String args[]) {
        int x = 3;

        // No.3
        ++x;  // x = x + 1 と同じ
        System.out.println(x);

        // No.4
        x++;
        System.out.println(x);

        // No.5
        System.out.println(++x);
        
        // No.6
        System.out.println(x++);
    }
}
/* 出力 */
4
5
6
6

No.3、No.4の計算はインクリメントと呼びます。

どちらもxに+1をします。

しかし、No.5とNo.6の出力に注目してください。

No.5の出力は5から+1されて6になっていますが、No6の出力は6から+1されていません。

これはxの後に「++」があるからです。

「++x」と書くと文の実行前にインクリメントし、「x++」と書くと文の実行後にインクリメントします。

その証拠に、一番最後にxを出力すると7と表示されるので試してみてください。

ちなみに「--」もあり、これはデクリメントと呼びます。

おわりに

今回はJavaにおける代入と計算を行いました。

次回は制御文について説明します。