你能在父类中获得子类注释吗?

Can you get subclass Annotation in parent?

这是有线的,但是你能做到吗?

我想使用无参数构造函数(因此开发依赖于我的框架不需要扩展构造函数),但我想在字段中使用 final。所以:

Annotation.java

public @interface Annotation {
    String value();
}

Parent.java

public abstract class Parent {

    public final String name;

    // this will cause you must extends constructor in any sub class
    public Parent(Annotation annotation){
        this.name = annotation.value();
    }
}

接口定义

public abstract class Define extends Parent {


    // You can't do that:
    // Cannot reference 'this' before supertype constructor has been called
    public Define (){
        this(this.getClass().getAnnotation(Annotation.class).value());
    }

    // You can do that, but not working 
    // Define is point at Define as is rather I hope the sub class MyModule
    public Define (){
        this(Define.class.getAnnotation(Annotation.class).value());
    }

    public Define (Annotation annotation){
        super(annotation); // You must extend this
    }

    public abstract void foo();

}

而且我希望开发人员像这样使用我的框架:

public class MyModule extends Define {

    public void foo(){
        // foo bar 
    }

}

但是由于Cannot reference 'this' before supertype constructor has been called,你必须写:

@Annotation
public class MyModule extends Define {

    // my framework using scan an IoC auto invoke 
    public MyModule(Annotation annotation){
        super(annotation.value())
    }

    public void foo(){
        // foo bar 
    }

}

矛盾的是​​name写在注解中,而this必须在newInstance之后。所以问题更像是:

如何 getClass() for sub class?

所以唯一的解决办法是放弃 final 字段并使用类似 init() 的东西?

你能接受使用反射来解决这个问题吗?

public abstract class Parent {

    final String name;

    public Parent() {
        this.name = null;
    }

    void setAnnotation(Annotation annotation) throws NoSuchFieldException, IllegalAccessException {
        Field field = Parent.class.getDeclaredField("name");
        field.setAccessible(true);
        field.set(this, annotation.value());
        field.setAccessible(false);
    }
}
public abstract class Define extends Parent {
    public Define() {
        super();
        try {
            this.setAnnotation();
        } catch (Exception e) {

        }
    }

    public abstract void foo();

    public void setAnnotation() throws NoSuchFieldException, IllegalAccessException {
        Annotation annotation = this.getClass().getAnnotation(Annotation.class);
        super.setAnnotation(annotation);
    }
}
@Annotation(value = "foo")
public class MyModule extends Define {

    @Override
    public void foo() {
    }
}

并且不要忘记在注释 class.

上添加 TargetRetention

不需要每个子class读取注释并将其传递给超级class,您可以将读取注释移动到基class:

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
  String value() default "defaultValue";
}

abstract class Base {
  final String value;
  Base() {
    MyAnnotation myAnnotation= getClass().getAnnotation(MyAnnotation.class);
    if (myAnnotation == null) {
      throw new IllegalStateException("Class " + getClass().getName() + " does not have require annotation MyAnnotation");
    }
    this.value = myAnnotation.value();
  }
}

@MyAnnotation
class DefaultValue extends Base {
}

@MyAnnotation("someValue")
class ExplicitValue extends Base {
}

class NoAnnotation extends Base {
}

鉴于这些 classes 这两行

System.out.println(new DefaultValue().value);
System.out.println(new ExplicitValue().value);

将分别打印 defaultValuesomeValue。但是,这一行将抛出 IllegalStateException:

new NoAnnotation();

不幸的是,Java 类型系统不允许在编译时对每个具体 class 强制执行注释的要求,所以这个运行时异常是你能得到的最好的(除了其他静态分析工具或 ArchUnit 等架构测试软件)。