小さな注釈を書いたとしましょう
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface PatternHandler {
String value();
}
そして、次のようなクラスを作成します
class Callables {
@PatternHandler("foo")
public static final TownyChatReplacerCallable FOO = new TownyChatReplacerCallable() {
@Override
public String call(String match, String event) {
return "This is foo handler called with " + match + "," + event;
}
};
@PatternHandler("bar")
public static final TownyChatReplacerCallable BAR = new TownyChatReplacerCallable() {
@Override
public String call(String match, String event) {
return "This is foo handler called with " + match + "," + event;
}
};
}
これらの静的フィールドを含むクラス全体または複数のクラスを取得して、そのクラスの各フィールドを反射的に反復するレジストリ メソッドに渡すことができます。
class AnnotationRegistry {
public static void register(String pattern, TownyChatReplacerCallable handler) {}
public static void register(Class<?> clazz) {
// only fields declared by this class, not inherited ones (static fields can't be inherited)
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// must have that annotation
PatternHandler annotation = field.getAnnotation(PatternHandler.class);
if (annotation != null) {
// must be static
if (!Modifier.isStatic(field.getModifiers())) {
System.out.println("Field must be static:" + field.getName());
continue;
}
// get content of that field
try {
Object object = field.get(null);
// must be != null and a callable
if (object instanceof TownyChatReplacerCallable) {
register(annotation.value(), (TownyChatReplacerCallable) object);
} else {
System.out.println("Field must be instanceof TownyChatReplacerCallable:" + field.getName());
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
これにより、コードを少し節約でき、リフレクションを使用してこれらの呼び出し可能オブジェクトを呼び出す必要がないため、実行時に速度が低下することはありません。
完全な例はこちら: http://ideone.com/m3PPcY
静的フィールドを使用する以外に、クラスのインスタンスをレジストリに渡す場合は、非静的フィールドを使用することもできObject object = field.get(instance);
ますnull
。
さらに、フィールドの代わりに、同じアプローチがメソッドで機能し、記述するコードが少なくなります。
@PatternHandler("foo")
public static String fooMethod(String match, String event) {
return "This is foo handler called with " + match + "," + event;
}
次に、レジストリはすべての s を探しますMethod
。次に、たとえばそれらをラップします
class MethodAdapter implements TownyChatReplacerCallable {
private final Method method;
public MethodAdapter(Method m) {
method = m;
}
@Override
public String call(String match, String event) {
try {
return (String) method.invoke(null, match, event);
} catch (Exception e) {
e.printStackTrace();
return "OMGZ";
}
}
}
そしていつものように続けます。ただし、注意してください: メソッドをリフレクティブに呼び出すと、コードを介して直接呼び出すよりも遅くなる可能性があります - ほんの数パーセントで、心配する必要はありません
メソッドの完全な例: http://ideone.com/lMJsrl