Skip to content

Instantly share code, notes, and snippets.

@yatatsu
Last active February 15, 2016 05:46
Show Gist options
  • Save yatatsu/923ef66dc829878f2db8 to your computer and use it in GitHub Desktop.
Save yatatsu/923ef66dc829878f2db8 to your computer and use it in GitHub Desktop.
javaの定数固有メソッド実装を持つenumのクラス名

javaの定数固有メソッド実装を持つenumのクラス名

定数固有メソッド実装

javaのenum(列挙型)には、enumクラス全体で定義したメソッドを各定数でoverrideすることができるという機能があります。 Effective Java 第6章項目30 に定数固有メソッド実装(constant-specific method implementation)として紹介されています。

クラス名を取得する

TestEnumClassName.javaMethod#getAltNameのようなメソッドを想定したとします。 Method.class.getSimpleName()で得られる文字列(クラス名)と定数名を連結させた文字列を取得する、 というのがこのメソッドの期待する振る舞いですが、定数固有メソッド実装をしているPOST/PUTでは想定した振る舞いをしません。

実行結果

GET alt name:  Method#GET
GET class#getName():  Method
GET class#getSimpleName():  Method
GET class#getCanonicalName():  Method
-------
POST alt name:  #POST
POST class#getName():  Method$1
POST class#getSimpleName():  
POST class#getCanonicalName():  null
-------
PUT alt name:  #PUT
PUT class#getName():  Method$2
PUT class#getSimpleName():  
PUT class#getCanonicalName():  null
-------
DELETE alt name:  Method#DELETE
DELETE class#getName():  Method
DELETE class#getSimpleName():  Method
DELETE class#getCanonicalName():  Method

なぜか

TestEnumClassName.javaのようなファイルをコンパイルすると、

  • TestEnumClassName.class
  • Method.class
  • Method$1.class
  • Method$2.class

というクラスファイルが生成されます。 Method$1.classをデコンパイルするとMethodクラスを継承したクラスが生成されていることがわかります。

まとめ

定数固有メソッドを実装したenum定数は新しくクラスを生成するため注意が必要です。

/*
* Decompiled with CFR 0_110.
*/
static final class Method
extends Method {
Method(String string2, int n2) {
super(string, n, null);
}
@Override
boolean allowEmptyBody() {
return false;
}
}
/***
* java TestEnumClassName
GET alt name: Method#GET
GET class#getName(): Method
GET class#getSimpleName(): Method
GET class#getCanonicalName(): Method
-------
POST alt name: #POST
POST class#getName(): Method$1
POST class#getSimpleName():
POST class#getCanonicalName(): null
-------
PUT alt name: #PUT
PUT class#getName(): Method$2
PUT class#getSimpleName():
PUT class#getCanonicalName(): null
-------
DELETE alt name: Method#DELETE
DELETE class#getName(): Method
DELETE class#getSimpleName(): Method
DELETE class#getCanonicalName(): Method
-------
*/
public class TestEnumClassName {
public static void main(String args[]) {
for (Method method : Method.values()) {
System.out.println(method.name() + " alt name: " + method.getAltName());
System.out.println(method.name() + " class#getName(): " + method.getClass().getName());
System.out.println(method.name() + " class#getSimpleName(): " + method.getClass().getSimpleName());
System.out.println(method.name() + " class#getCanonicalName(): " + method.getClass().getCanonicalName());
System.out.println("-------");
}
}
}
enum Method {
GET,
POST {
@Override
boolean allowEmptyBody() {
return false;
}
},
PUT {
@Override
boolean allowEmptyBody() {
return false;
}
},
DELETE,
;
boolean allowEmptyBody() {
return true;
}
String getAltName() {
return getClass().getSimpleName() + "#" + name();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment