Engineering Note

プログラミングなどの技術的なメモ

Java入門 列挙型(enum)

java

本記事は、Javaを一から学んでいく際の学習メモとして書かれています。

主にインプレスから出版されている「スッキリわかるJava入門 第2版 (スッキリシリーズ)」の内容に沿ったかたちで学習していきます。

今回は、Javaの列挙型(enum型)について学んでいきます。

  

 

列挙型とは

列挙型(enum型)とは、java.lang.Enumクラスを継承し、定数の集合を定義するための特殊なクラスの一種となります。

enumenumerationの略で、そのまま「列挙」という意味を持ちます。

C言語にも列挙型があり、同じように定数の集まりとして定義されておりますが、実体としては登録したメンバ順にint型の整数として割り当てられます。

また、Pythonでも3.4のバージョンからEnum型が標準ライブラリとしてサポートいます。

 

定数とは

定数(Constant)は、クラス内でフィールドを宣言する際に、「public static final」の修飾子を付けた変数を定義することで実現します。

このようにすることで、その変数の値を変更不可能にし、変更しようとした場合はコンパイルエラーが発生します。

 

// TestConnection.java
public class TestConnection {
    public static final String TELNET = "TELNET";
    public static final String SSH = "SSH";
    public static final String HTTP = "HTTP";

    public static void connectTcpPort(String port){
        System.out.println("connecting to " + port + " server");
    }
    public static void main(String[] args) {
        connectTcpPort(TELNET);
        // connecting to TELNET server
        TELNET = "SSH"; // コンパイルエラー
    }
}

 

しかし、connectTcpPortメソッドは、上記で作成した「TELNETSSH、HTTP」の何れかを引数として利用するものと想定しており、もし"FTP"という文字列リテラルが渡された場合、開発側としては想定外であり、型安全でない状態が起こってしまいます。

 

このように型安全な状態を作るのが列挙型になります。

 

列挙型の作成

まずが基本的な列挙型を作成します。

 

// TcpPort.java
public enum TcpPort {
    SSH, TELNET, HTTP
}

 

上記で作成した列挙型を以下のMainクラスで利用してみます。

 

// Main.java
public class Main {
    public static void connectTcpPort(TcpPort port){
        System.out.println("connecting to " + port + " server");
    }
    public static void main(String[] args) {
        TcpPort port = TcpPort.HTTP;
        connectTcpPort(port);
        // connecting to HTTP server
        switch (port) {
            case SSH:
                System.out.println("connecting to 22 port");
                break;
            case TELNET:
                System.out.println("connecting to 23 port");
                break;
            case HTTP:
                System.out.println("connecting to 80 port");
                break;
        }
        // connecting to 80 port
    }
}

 

上記でconnectTcpPortメソッドの引数をTcpPort型にすることで、型安全な状態を作ることができます。

また、switch文で利用する場合、caseに続く値にはTcpPort.*のように書いた場合はコンパイルエラーとなるため、注意が必要です。

 

コンストラクタ、フィールド及びメソッドの定義

上述の通り列挙型もクラスの一種なので、コンストラクタ・フィールド・メソッドの定義が可能です。

コンストラクタに定義する場合は、「定数(args...)」のように記述し、フィールドの初期化などが可能です。

なお、コンストラクタのアクセス修飾子は必ずprivateとしなければならず、他のアクセス修飾子を指定した場合はコンパイルエラーとなります。

 

// TcpPort.java
public enum TcpPort {
    SSH(22), TELNET(23), HTTP(80);

    private final int portNum;

    private TcpPort(int portNum){
        this.portNum = portNum;
    }
    public int getPortNum(){
        return portNum;
    }
}
// Main.java
public class Main {
    public static void main(String[] args) {
        TcpPort port = TcpPort.HTTP;
        System.out.println("connecting to " + port + " port");
        // connecting to HTTP port
        System.out.println("connecting to " + port.getPortNum() + " port");
        // connecting to 80 port
    }
}

 

最後に

今回はJavaの列挙型(enum型)についての基本的なルールを学びました。

次回からは、オブジェクト指向の3大要素である「カプセル化、継承、ポリモーフィズム」について学んでいきます。

 

参考書籍

スッキリわかるJava入門 第2版 (スッキリシリーズ)

 

Java本格入門 ~モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで