代码之家  ›  专栏  ›  技术社区  ›  Locke

多种注释类型的注释

  •  0
  • Locke  · 技术社区  · 6 年前

    我希望能够用两种注释类型的列表来注释一个类,它们在函数上是相关的,但在参数上是完全不同的。不过,这个列表的顺序很重要。我已经试过寻找这个,但找不到任何参考(我不知道该怎么称呼它)。

    编辑:

    最后我想做的是:

    //place holder for example (Abstract)
    public @interface A {
    }
    
    @Target(PARAMETER)
    public @interface B extends A {
        //Gets stuff
        Class type();
        int key();
    }
    
    @Target(PARAMETER)
    public @interface FlaggedListOfA extends A {
        //List of A
        A[] set();
    }
    
    //Goal is to have annotation that does this
    @Target(METHOD)
    public @interface ImportantFunc {
        A[] dataForA() default {};
        String[] names();
        int property() default 0;
        //etc.
    }
    
    //End goal:
    public class SomeImportantClass {
    
        @ImportantFunc(dataForA = {@B(...), @B(...}, ...)
        public void doStuff() {
    
        }
    
        //So I can have an end goal of this (Order matters, may contain repeats,
        //and has unknown length!)
        @ImportantFunc(dataForA = {@B(...), @FlaggedListOfA(@B(...), @B(...))}, ...)
        public void doStuffB() {
    
        }
    
        @ImportantFunc(dataForA = {@FlaggedListOfA(@B(...)), @FlaggedListOfA(@B(...), @B(...))}, ...)
        public void doStuffC() {
    
        }
    
        @ImportantFunc(dataForA = {@FlaggedListOfA(@B(...), @FlaggedListOfA(@B(...), @B(...))), @B(...)}, ...)
        public void doStuffD() {
    
        }
    }
    

    编辑:

    解决这个问题的另一种方法是找到一种将两个注释组合在一起的方法。

    能够做到这一点并不完全理想,但肯定会使其更具可行性:

    public @interface Example {
        AnyTypeOfAnnotation[] set();
    }
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Radiodef    6 年前

    一个愚蠢的方法是 A 联合 B C . 这意味着它拥有 二者都 B C ,但你只把它当作 任何一个

    这是一个有效的例子。

    import java.lang.annotation.*;
    
    enum NoType {;}
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface A {
        Class<?> data()  default NoType.class; // field from B
        int      dataA() default 0;            // field from C
        String   dataB() default "";           // field from C
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface D {
        A[] value() default {};
    }
    
    class Foo {}
    class Bar {}
    
    class Example {
        @D({
            @A(data = Bar.class),
            @A(dataA = 5, dataB = "Bla"),
            @A(data = Foo.class)
        })
        public static void main(String[] args) throws Exception {
            for (A a : Example.class.getMethod("main", String[].class)
                            .getAnnotation(D.class).value()) {
                if (a.data() != NoType.class) {
                    System.out.printf("B(%s)%n", a.data());
                } else {
                    System.out.printf("C(dataA = %d, dataB = \"%s\")%n",
                        a.dataA(), a.dataB());
                }
            }
        }
    }
    

    这个 output of that program

    B(class Bar)
    C(dataA = 5, dataB = "Bla")
    B(class Foo)
    

    当然,这不是一个很好的解决方案,但它确实有效。

        2
  •  0
  •   Jai    6 年前

    public @interface A {
    }
    
    public @interface B extends A {
        //Gets stuff
        Class data();
    }
    
    public @interface C extends A {
        //Gets different stuff related to same goal
        int dataA();
    
        String dataB();
    }
    
    public @interface D {
        Class<? extends A>[] order();
    }
    
    
    @B(Bar.class)
    @C(dataA = 5, dataB = "Bla")
    @D(order = {B.class, C.class})
    public class SomeImportantClass {
    
    }
    

    D 注释作为保持注释顺序的一种手段。缺点是不能添加同一类型的多个注释。

    还有另一种方法 A , B C 进入正常班级。

    public abstract class AnnotationAttribute {
        public abstract Class<?>[] getDataTypes();
        public abstract Object[] getData();
    }
    
    public class B extends AnnotationAttribute {
        @Override public Class<?>[] getDataTypes() {
            return new Class<?>[] {Foo.class, Bar.class};
        }
        @Override public Object[] getData() {
            return new Object[] {new Foo(), new Bar()};
        }
    }
    
    public @interface D {
        Class<? extends AnnotationAttribute>[] data() default {};
    }
    
    @D(data = {B.class});
    public class Test {
    }
    

    此方法要求您为一个具体的属性类型创建一个类。这是因为注释必须是编译时常量,并且通过 Class 要求您在代码中定义类。