次の注釈のインスタンスを作成するにはどうすればよいですか(すべてのフィールドがデフォルト値に設定されています)。
_ @Retention( RetentionPolicy.RUNTIME )
public @interface Settings {
String a() default "AAA";
String b() default "BBB";
String c() default "CCC";
}
_
new Settings()
を試しましたが、うまくいかないようです...
インスタンスを作成することはできませんが、少なくともデフォルト値を取得してください
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());
インスタンスを作成するには、以下を実装するクラスを作成する必要があります。
Java.lang.annotation.Annotation
_例:_public class MySettings implements Annotation, Settings
_
ただし、equals
インターフェースによるhashCode
およびAnnotation
のcorrect実装に特別な注意を払う必要があります。 http://download.Oracle.com/javase/1.5.0/docs/api/Java/lang/annotation/Annotation.html
これを何度も実装したくない場合は、 javax.enterprise.util.AnnotationLiteral クラスを確認してください。これは、CDI(Context Dependency Injection)-APIの一部です。 (@ see code)
デフォルト値を取得するには、akuhn(以前はAdrianと呼ばれていました)で説明されている方法を使用できます。 Settings.class.getMethod("a").getDefaultValue()
コンパイルして実行したところ、満足のいく結果が得られました。
class GetSettings {
public static void main (String[] args){
@Settings final class c { }
Settings settings = c.class.getAnnotation(Settings.class);
System.out.println(settings.aaa());
}
}
同じ問題があったので、次のように解決しました。
public static FieldGroup getDefaultFieldGroup() {
@FieldGroup
class settring {
}
return settring.class.getAnnotation(FieldGroup.class);
}
メソッドで使用する場合:
@Settings
public void myMethod() {
}
これで、アノテーションがデフォルト値で初期化されました。
これは、Sun/Oracleで動作しますJava 5,6,7,8:(ただし、Java 9が含まれているため、Sunクラスが原因で壊れる可能性があります)。//editこれがOpenJDK 9b59でも動作することを確認しました。
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;
}
}
出力:
Custom annotation creation: @demo.AnnotationProxyExample$Example(bar=true, foo=42, value=required)
Traditional annotation creation: @demo.AnnotationProxyExample$Example(bar=true, foo=42, value=required)
Settings
クラスの本体を変更する余裕がある場合は、代替ソリューションがあります。
@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;
}
その後、単にSettings.DEFAULT_A
を参照できます(はい、より良い名前が役立ちます!)。