Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用注释创建可调用项_Java_Annotations_Apt - Fatal编程技术网

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任何有助于你写得更干净/更少的东西代码不应该被避免。显然有一些缺点,比如失去了一些通常的编译时类型安全性,因为必须在运行时进行检查,初学者不理解的奇怪代码……但这是完全值得的。