قم بإنشاء مثيل التعليق التوضيحي بالإعدادات الافتراضية في Java

StackOverflow https://stackoverflow.com/questions/266903

  •  06-07-2019
  •  | 
  •  

سؤال

كيف يمكنني إنشاء مثيل للتعليق التوضيحي التالي (مع تعيين جميع الحقول على قيمتها الافتراضية).

    @Retention( RetentionPolicy.RUNTIME )
    public @interface Settings {
            String a() default "AAA";
            String b() default "BBB";
            String c() default "CCC";
    }

حاولت new Settings(), ، لكن لا يبدو أن هذا ينجح..

هل كانت مفيدة؟

المحلول 2

ولا يمكنك إنشاء مثيل، ولكن على الأقل الحصول على القيم الافتراضية

Settings.class.getMethod("a").getDefaultValue()
Settings.class.getMethod("b").getDefaultValue()
Settings.class.getMethod("c").getDefaultValue()

وبعد ذلك، يمكن أن تستخدم وكيل الديناميكي للعودة القيم الافتراضية. الذي، بقدر ما استطيع ان اقول، يتم التعامل معها بطريقة شروح من قبل جافا نفسها أيضا.

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
  • والتعليق التوضيحي الذي تريد "محاكاته"

على سبيل المثال: public class MySettings implements Annotation, Settings

ولكن عليك أن تولي اهتماما خاصا لل صحيح بداية شئ equals و hashCode بحسب ال Annotation واجهه المستخدم.http://download.Oracle.com/javase/1.5.0/docs/api/Java/lang/annotation/Annotation.html

إذا كنت لا ترغب في تنفيذ ذلك مرارًا وتكرارًا، فقم بإلقاء نظرة على javax.enterprise.util.AnnotationLiteral فصل.هذا جزء من CDI (حقن تبعية السياق) -API.(@انظر الكود)

للحصول على القيم الافتراضية يمكنك استخدام الطريقة التي وصفها 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() {
}

والآن تتم تهيئة الشرح مع القيم الافتراضية.

وهذا يعمل مع الشمس / أوراكل جافا 5،6،7،8: (ولكن يحتمل أن كسر مع جافا 9 بسبب الطبقات الشمس المعنية). // تحرير مجرد التحقق من أن هذا لا يزال يعمل مع 9b59 OpenJDK.

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 (نعم، فإن اسم أفضل مساعدة!).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top