Java 使用注释创建可调用项
我正在尝试制作一个类似于 还有更多 有没有一种方法可以使用注释来减少重复代码的数量,避免调用调用方法的反射,并且仅在注册过程中使用它(如果有的话)Java 使用注释创建可调用项,java,annotations,apt,Java,Annotations,Apt,我正在尝试制作一个类似于 还有更多 有没有一种方法可以使用注释来减少重复代码的数量,避免调用调用方法的反射,并且仅在注册过程中使用它(如果有的话) 我并不反对创建注释预处理器的想法,因为我已经计划这样做以启用自动生成文档。您可以尝试新的Java 8 Lambda表达式() 可以写为: replacer.registerFormatReplacement( Pattern.quote("{worldname}"), (match, event) -> { return String
我并不反对创建注释预处理器的想法,因为我已经计划这样做以启用自动生成文档。您可以尝试新的Java 8 Lambda表达式() 可以写为:
replacer.registerFormatReplacement(
Pattern.quote("{worldname}"),
(match, event) -> { return String.format(ChatSettings.getWorldTag(), event.getEvent().getPlayer().getWorld().getName()); }
});
您还可以使用另一个接口、方法等进一步推动它。。。您可以尝试新的Java8Lambda表达式() 可以写为:
replacer.registerFormatReplacement(
Pattern.quote("{worldname}"),
(match, event) -> { return String.format(ChatSettings.getWorldTag(), event.getEvent().getPlayer().getWorld().getName()); }
});
您还可以使用另一个接口、方法等进一步推动它。。。我们假设您编写了一个小注释
@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();
}
}
}
}
}
然后,注册表将查找所有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";
}
}
}
照常继续。但要注意:反射式调用方法可能比通过代码直接调用要慢——仅为百分之几,无需担心
方法的完整示例:假设您编写了一个小注释
@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();
}
}
}
}
}
然后,注册表将查找所有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";
}
}
}
照常继续。但要注意:反射式调用方法可能比通过代码直接调用要慢——仅为百分之几,无需担心
方法的完整示例:您可以拥有一个包含大量方法的类,例如
@PatternHandler(“foo”)String someMethodName(String match,LocalTownyChatEvent event){}
,这些方法是通过该注释注册的,您可以保存replacer.registerFormatReplacement(
part.要么需要反射将每个注册为方法
,要么需要将每个注册为可调用
这是我的想法,但我的问题是“要么需要反射将每个注册为方法,要么需要将每个注册为可调用”我不知道如何开始这一部分。我还计划在某个阶段使用注释处理器来生成文档,因此这是主要的驱动原因。您可以拥有一个包含许多方法的类,例如@PatternHandler(“foo”)String someMethodName(String匹配,LocalTownyChatEvent事件){}
是通过该注释注册的,您将保存replacer.registerFormatReplacement(
部分)。要么需要反射将每个注册为方法
,要么需要将每个注册为可调用的
,这是我的想法,但我的问题是“要么需要反射将每个注册为一个方法,要么需要将每个注册为可调用的"我不知道如何开始这一部分。我还计划在某个阶段使用注释处理器来生成文档,因此这是主要的驱动原因。不幸的是,这不是一个选项。坚持在java 6上。不幸的是,这不是一个选项。坚持在java 6上。谢谢,其他人告诉我只通过反射调用方法,但是s在大多数情况下都应该避免使用它的印象下,我想这是它真正有帮助的时候之一。@RyanTheLeach任何有助于编写更干净/更少代码的东西都不应该被避免。显然有一些缺点,比如失去了一些通常的编译时类型安全性,因为必须在运行时进行检查,strange看起来是初学者不理解的代码,…但我觉得这完全值得。谢谢,其他人告诉我只需通过反射调用方法,但我的印象是大多数时候都应该避免使用,我想这是它真正有帮助的时候之一。@RyanTheLeach任何有助于你写得更干净/更少的东西代码不应该被避免。显然有一些缺点,比如失去了一些通常的编译时类型安全性,因为必须在运行时进行检查,初学者不理解的奇怪代码……但这是完全值得的。