在Java中使用默认值创建注释实例
如何创建以下注释的实例(所有字段都设置为默认值) 我尝试了在Java中使用默认值创建注释实例,java,annotations,instantiation,Java,Annotations,Instantiation,如何创建以下注释的实例(所有字段都设置为默认值) 我尝试了新设置(),但似乎不起作用…如果与方法一起使用: @Settings public void myMethod() { } 现在,您的批注已使用默认值初始化。您无法创建实例,但至少可以获得默认值 Settings.class.getMethod("a").getDefaultValue() Settings.class.getMethod("b").getDefaultValue() Settings.class.getMethod("
新设置()
,但似乎不起作用…如果与方法一起使用:
@Settings
public void myMethod() {
}
现在,您的批注已使用默认值初始化。您无法创建实例,但至少可以获得默认值
Settings.class.getMethod("a").getDefaultValue()
Settings.class.getMethod("b").getDefaultValue()
Settings.class.getMethod("c").getDefaultValue()
然后,可以使用动态代理返回默认值。就我所知,这也是Java本身处理注释的方式
class Defaults implements InvocationHandler {
public static <A extends Annotation> A of(Class<A> annotation) {
return (A) Proxy.newProxyInstance(annotation.getClassLoader(),
new Class[] {annotation}, new Defaults());
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.getDefaultValue();
}
}
Settings s = Defaults.of(Settings.class);
System.out.printf("%s\n%s\n%s\n", s.a(), s.b(), s.c());
类默认值实现调用处理程序{
的公共静态A(类注释){
返回(A)Proxy.newProxyInstance(annotation.getClassLoader(),
新类[]{annotation},新默认值();
}
公共对象调用(对象代理、方法、对象[]参数)
扔掉的{
返回方法.getDefaultValue();
}
}
设置s=默认值.of(Settings.class);
System.out.printf(“%s\n%s\n%s\n”,s.a(),s.b(),s.c());
我编译并在下面运行,结果令人满意
class GetSettings {
public static void main (String[] args){
@Settings final class c { }
Settings settings = c.class.getAnnotation(Settings.class);
System.out.println(settings.aaa());
}
}
要创建实例,您需要创建一个实现以下功能的类:
- 以及要“模拟”的注释
公共类MySettings实现注释、设置
但是您需要特别注意根据注释
界面对equals
和hashCode
的正确实现。
如果您不想一次又一次地实现它,那么请查看该类。
这是CDI(上下文依赖注入)API的一部分。
要获得默认值,可以使用akuhn(以前称为:Adrian)描述的方法。
Settings.class.getMethod(“a”).getDefaultValue()
也有同样的问题,我解决了它如下
public static FieldGroup getDefaultFieldGroup() {
@FieldGroup
class settring {
}
return settring.class.getAnnotation(FieldGroup.class);
}
这适用于Sun/OracleJava5,6,7,8:(但由于涉及Sun类,可能会与Java9发生冲突)。 //edit刚刚验证了这仍然适用于openjdk9b59
package demo;
import sun.reflect.annotation.AnnotationParser;
import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class AnnotationProxyExample
{
public static void main(String[] args)
{
System.out.printf("Custom annotation creation: %s%n",
createAnnotationInstance(Collections.singletonMap("value", "required"), Example.class));
System.out.printf("Traditional annotation creation: %s%n",
X.class.getAnnotation(Example.class));
}
private static <A extends Annotation> A createAnnotationInstance(Map<String, Object> customValues, Class<A> annotationType)
{
Map<String, Object> values = new HashMap<>();
//Extract default values from annotation
for (Method method : annotationType.getDeclaredMethods())
{
values.put(method.getName(), method.getDefaultValue());
}
//Populate required values
values.putAll(customValues);
return (A) AnnotationParser.annotationForMap(annotationType, values);
}
@Example("required")
static class X
{
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Example
{
String value();
int foo() default 42;
boolean bar() default true;
}
}
如果您有能力更改
设置
类的主体,则有另一种解决方案:
@Retention( RetentionPolicy.RUNTIME )
public @interface Settings {
String DEFAULT_A = "AAA";
String DEFAULT_B = "BBB";
String DEFAULT_C = "CCC";
String a() default DEFAULT_A;
String b() default DEFAULT_B;
String c() default DEFAULT_C;
}
然后您可以简单地引用
设置。默认设置(是的,更好的名称会有帮助!)。本地类,我总是忘记它们,很好的黑客!实际上,这一个看起来可能比当前接受的答案更好,因为它一直保持静态输入。而当前接受的答案依赖于字符串中的方法名称。@SaM不完全正确,接受的解决方案对传递给代理的方法对象调用getDefaultValue
。这与Java本身实现注释的方式相同,因此它与您的注释一样“类型安全”。(使用字符串选择方法的初始代码示例仅用于说明原理。)@akuhn这更好。方法名称没有拼写错误。无需将DefaultValue强制转换为字符串。这很好-但如果保留策略为SOURCE,则不起作用:/annotation的“您无法创建实例”是错误的!可以创建注释的实例。您只需要创建一个实现java.lang.annotation.annotation和具体注释接口(例如设置)的类,然后就可以创建该类的实例。更多详情请参见我的答案谢谢您的解决方案!从技术上讲,您可以创建批注子类的实例,就像运行时代理一样。@akuhn,您还可以将@SuppressWarnings(“未选中”)添加到工厂方法“of”;虽然带有抑制警告的typecast看起来并不干净,但我喜欢您的解决方案,因为它确实是类型安全的,并且允许安全地使用IDE的重构功能。谢谢!工作得很好,但是如果有没有默认值的基本成员,它就会崩溃。使用com.google.common.base.Defaults可以执行以下操作:return method.getDefaultValue()!=无效的method.getDefaultValue():Defaults.defaultValue(method.getReturnType());美丽的。诚实的真漂亮。我自己也尝试过,它应该成为这个问题的认可解决方案。你认为这个解决方案需要手动实现注释的每个“方法”吗?@Adrian:对,你必须实现注释定义的接口。--如果您需要方法a()
、b()
和c()
,至少在使用Eclipse时,您必须为实现提供注释的完全限定名称。这将编译错误减少为警告。java.lang.Annotation
不存在,是否应该是java.lang.Annotation.Annotation
?如果是这样,显式实现它有什么意义,因为它是任何注释的超级接口。
Custom annotation creation: @demo.AnnotationProxyExample$Example(bar=true, foo=42, value=required)
Traditional annotation creation: @demo.AnnotationProxyExample$Example(bar=true, foo=42, value=required)
@Retention( RetentionPolicy.RUNTIME )
public @interface Settings {
String DEFAULT_A = "AAA";
String DEFAULT_B = "BBB";
String DEFAULT_C = "CCC";
String a() default DEFAULT_A;
String b() default DEFAULT_B;
String c() default DEFAULT_C;
}