@blog.justoneplanet.info

日々勉強

Javaの列挙型

以下のようにしてenumを宣言し、定数を列挙することができる。

enum Suit {CLUBS, DIAMONDS, HEARTS, SPADES}

staticフィールドとして考える。以下のようにしてアクセスすることができる。

Suit.HEARTS

名前付き整数定数

一見すると以下のようなコードに対してenumのメリットがわかりにくい。

class Car {
    static final int TYPE_SEDAN = 1;
    static final int TYPE_MINI  = 2;

    static final int COLOR_RED  = 1;
    static final int COLOR_BLUE = 2;

    Car(int type, int color);
}

しかし致命的な欠点があり、以下のようなコードもエラーとならない。

Car car = new Car(Car.COLOR_RED, Car.TYPE_SEDAN);

enum

以下のようにして定義する。

class Car {
    static enum Type{SEDAN, MINI};
    static enum Color{RED, BLUE};
    Car(Type type, Color color);
}

型安全であるので以下のようにするとエラーとなる。

Car car = new Car(Car.Color.RED, Car.Type.SEDAN);

PHPにはない(よね?)ので便利である。

■宣言

最後のenum定数の後にカンマを書いておくことはできる。

enum Type {
    SEDAN,
    MINI,
}

PHPの配列定義と同じで便利である。但し、enum定数以外のものを宣言する場合はセミコロンで終了させる必要がある。

static enum Type{
    SEDAN,
    MINI;
    public static int getSize(){return 4;};
};

メソッド

全てのenum型Eはコンパイラーによって以下のstaticメソッドを持つ。

public static E[] values()
宣言された順序で各enum定数を含む配列を返す
public static E valueOf(String name)
指定されたnameを持つenum定数を返す。存在しない時はIllegalArgumentExceptionをthrowする

また以下のようなメソッドがある。

public final int ordinal()
enum定数の順序値を返す(ChessPiece.PAWN.ordinal())
public final Class getDeclaringClass()
enum定数のenum型を表しているClassオブジェクトを返す

■修飾子

以下の修飾子を付けることができる。

アノテーション
アクセス修飾子
static
全てのネストしたenumはstaticである。慣習として省略される
staticの浮動小数点(strictfp)

アクセス修飾子について

  • パッケージアクセス
  • public
ネストされている場合
  • private
  • protected
  • パッケージアクセス
  • public

■生成

以下のようにしてコンストラクタを持つことができる。

enum Type{
    SEDAN("sedan"),
    MINI("mini");
    
    String name;
    Type(String name){this.name = name;};
};

以下のようにアクセスすることができる。

String str = Type.SEDAN.name;// sedan
  • 全てのenumコンストラクタはprivateであるが慣習的に省略される
  • コンストラクタはスーパークラスのコンストラクタの呼び出しを明示することはできない
  • enumコンストラクタはenumの非定数staticフィールドを使用できない(定数ではないstaticフィールドの初期化はコンストラクタの実行後に実行される)

■用例

以下のようにして使うのが一般的である。

enum ChessPiece {
    PAWN, ROOK, BISHOP, KNIGHT, KING, QUEEN;
}
Set<Position> reachable(ChessPiece type, Position current) {
    if(type == ChessPiece.PAWN) {
        return pawnReachaable(current);
    }
    else if(type == ChessPiece.ROOK) {
        return rookReachaable(current);
    }
    else if(type == ChessPiece.QUEEN) {
        return queenReachaable(current);
    }
//...
    else {
        throw new Error("Unknow type");
    }
}

以下のように(値と処理をセットで)記述することで特定の値に対する処理を忘れることがない。

enum ChessPiece {
    PAWN {
        Set<Position> reachable(Position current) {
            return ChessRules.pawnReachable(current);
        }
    },
    ROOK {
        Set<Position> reachable(Position current) {
            return ChessRules.pawnReachable(current);
        }
    },
    QUEEN {
        Set<Position> reachable(Position current) {
            return ChessRules.pawnReachable(current);
        }
    };

    // enumが定義するメソッドの宣言
    abstract Set<Position> reachable(Position current);
}

各enum定数に対して定義されているクラスは実質的にエンクロージングenum型を継承している無名内部クラスである。staticメンバやコンストラクタを宣言することはできない。

ちなみにenum定数のコンストラクタが存在する場合は以下のようになる。

enum ChessPiece {
    PAWN("pawn") {
        Set<Position> reachable(Position current) {
            return ChessRules.pawnReachable(current);
        }
    },
    ROOK("rook") {
        Set<Position> reachable(Position current) {
            return ChessRules.pawnReachable(current);
        }
    },
    QUEEN("queen") {
        Set<Position> reachable(Position current) {
            return ChessRules.pawnReachable(current);
        }
    };

    // enumが定義するメソッドの宣言
    abstract Set<Position> reachable(Position current);
    String name;
    ChessPiece(String name){this.name = name;};
}

enumをサブクラス化できないので、enumが固有の振る舞いを持つenum定数を宣言している場合は、classをfinalにする時と同様に考慮が必要である。

Amazon EC2を使ってWebSocketサーバを10分でたてる

前回に引き続きWebSocketサーバをたてる。今回はAmazon EC2を使用する。

sudo passwd root

■インストール

rootのパスワードを設定したら以下のコマンドを実行する。

su
yum install openssl-devel gcc-c++ make
wget http://nodejs.org/dist/node-v0.4.3.tar.gz
tar xvzf node-v0.4.3.tar.gz
cd node-v0.4.3
./configure
make
make install
curl http://npmjs.org/install.sh | sh
npm install websocket-server
npm install base64

使用しているインスタンスによって、makeは時間がかかるので10分では無理。(๑°⌓°๑)

別解1

以下のようにnaveを使ってインストールする手法もある。

su
yum install openssl-devel gcc-c++ git make
git clone https://github.com/isaacs/nave.git ~/.nave
~/.nave/nave.sh install latest
~/.nave/nave.sh use latest
echo "~/.nave/nave.sh use latest" >> ~/.bash_profile
curl http://npmjs.org/install.sh | sh
npm install websocket-server
npm install base64

残念ながらmicroインスタンスでコンパイルすると負荷が高すぎて途中終了してしまった。Largeでコンパイルすればサクっと終わる。

追記

会社で同僚に教えてもらった。

別解2

nvmを使えばnpmも同時にインストールできる。

su
yum install openssl-devel gcc-c++ git make
git clone git://github.com/creationix/nvm.git ~/.nvm
source ~/.nvm/nvm.sh
echo "~/.nvm/nvm.sh" >> ~/.bash_profile
echo "nvm use v0.4.8" >> ~/.bash_profile
nvm sync
nvm install v0.4.8
npm install websocket-server
npm install base64

smallインスタンスたどコンパイルに時間がかかる。

■アカウントの作成

話が前後するがアカウントの作成からだと流石に10分は無理。作成方法については以下を参照すると良い。

■EC2まとめ

コマンドラインツールを使用するにはX.509 証明書が必要。基本的にはコントロールパネルから操作が可能。インスタンスを起動させるフローで証明書(鍵)がダウンロードできる。SSHはその鍵で接続する。そんな感じ。(。・ω・)ノ゙

■開発環境構築

以下のコマンドを実行しツールをインストールする。

npm install node-dev #ファイルを変更すると再実行
npm install node-inspector #Developer Tool
npm install cloud9 #IDE