你能在父类中获得子类注释吗?
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.
上添加 Target
和 Retention
不需要每个子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);
将分别打印 defaultValue
和 someValue
。但是,这一行将抛出 IllegalStateException
:
new NoAnnotation();
不幸的是,Java 类型系统不允许在编译时对每个具体 class 强制执行注释的要求,所以这个运行时异常是你能得到的最好的(除了其他静态分析工具或 ArchUnit 等架构测试软件)。
这是有线的,但是你能做到吗?
我想使用无参数构造函数(因此开发依赖于我的框架不需要扩展构造函数),但我想在字段中使用 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.
上添加Target
和 Retention
不需要每个子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);
将分别打印 defaultValue
和 someValue
。但是,这一行将抛出 IllegalStateException
:
new NoAnnotation();
不幸的是,Java 类型系统不允许在编译时对每个具体 class 强制执行注释的要求,所以这个运行时异常是你能得到的最好的(除了其他静态分析工具或 ArchUnit 等架构测试软件)。