replacer.registerFormatReplacement(Pattern.quote("{worldname}"), new TownyChatReplacerCallable() {
@Override
public String call(String match, LocalTownyChatEvent event) throws Exception {
return String.format(ChatSettings.getWorldTag(), event.getEvent().getPlayer().getWorld().getName());
}
});
replacer.registerFormatReplacement(Pattern.quote("{town}"), new TownyChatReplacerCallable() {
@Override
public String call(String match, LocalTownyChatEvent event) throws Exception {
return event.getResident().hasTown() ? event.getResident().getTown().getName() : "";
}
});
等等。
有没有办法使用注释来减少重复代码的数量,避免反射调用调用方法,只在注册时使用它,如果有的话?
我并不反对创建注释预处理器的想法,因为我已经计划这样做以启用自动生成文档。
答案 0 :(得分:1)
我们假设你写了一个小的注释
@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();
}
}
}
}
}
这样可以节省一些代码,并且在运行时没有速度劣势,因为不需要使用反射来调用这些callables。
此处的完整示例: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;
}
然后,注册表将查找所有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
答案 1 :(得分:0)
您可以尝试使用新的Java 8 Lambda表达式(http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)。
replacer.registerFormatReplacement(Pattern.quote("{worldname}"), new TownyChatReplacerCallable() {
@Override
public String call(String match, LocalTownyChatEvent event) throws Exception {
return String.format(ChatSettings.getWorldTag(), event.getEvent().getPlayer().getWorld().getName());
}
});
可以写成:
replacer.registerFormatReplacement(
Pattern.quote("{worldname}"),
(match, event) -> { return String.format(ChatSettings.getWorldTag(), event.getEvent().getPlayer().getWorld().getName()); }
});
您还可以使用另一个界面,方法......进行进一步推送