gpt4 book ai didi

java - 使用注释创建 Callable

转载 作者:太空宇宙 更新时间:2023-11-04 07:30:16 26 4
gpt4 key购买 nike

我正在尝试制作一个类似于 https://github.com/ElgarL/TownyChat/blob/master/src/com/palmergames/bukkit/TownyChat/TownyChatFormatter.java 的系统

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() : "";
}
});

还有更多。

有没有办法使用注释来减少重复代码量,避免反射调用 call 方法,并且仅在注册期间使用它(如果有的话)?

我并不反对创建注释预处理器的想法,因为我已经计划这样做以实现自动生成文档。

最佳答案

假设您编写了一个小注释

@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;
}

注册中心将查找所有 Method s。然后例如将它们包裹在

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

关于java - 使用注释创建 Callable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17832381/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com