enum class Command(private vararg val commands: String) {

  @FieldEnrich("changeLanguages", "commands")
  CHANGE_LANGUAGE;
}

enum class CreatingCarStep(private vararg val values: String) : AbstractStep<CreatingCarStep> {
  @FieldEnrich("brand-name", "values")
  BRAND_NAME {
    override fun next() = MODEL
    override fun previous() = BRAND_NAME
  };
}

我有两个带有vararg属性和@FieldEnrich注释的枚举.

批注看起来像

@Target(FIELD, CLASS)
@Retention(RUNTIME)
annotation class FieldEnrich(
  val property: String,
  val field: String
)

注释正在按对象处理

object FieldEnricher {

  lateinit var configurationProvider: ConfigurationProvider

  fun enrichClass(clazz: Class<*>) {
    clazz.enumConstants.forEach {
      enrichField(it, clazz)
    }
  }

  private fun enrichField(enum: Any, clazz: Class<*>) {
    val enumClass = enum::class.java
    if (enumClass.isAnnotationPresent(FieldEnrich::class.java)) {
      val fieldEnrich = enumClass.getAnnotation(FieldEnrich::class.java)
      val values = configurationProvider.getProperty(fieldEnrich.property, Array<String>::class.java)
      val field = clazz.declaredFields.firstOrNull { it.name == fieldEnrich.field }
      field?.isAccessible = true
      field?.set(enum, values)
    }
  }
}

逻辑如下.我们用注释@FieldEnrich注释枚举成员,并传递要从中读取值的属性以及设置属性值的字段的名称.

我在调试时发现,当它试图处理CreatingCarStep枚举时是可以的,因为enumConstants方法返回枚举值的实际对象.所以我可以只取这个值的类,得到这个枚举的实际类,然后用我的方法enrichField处理它.但当它试图处理命令enum时,我只得到了enum值.因此,如果我们采用enum value类,那么将返回相同的命令类.在此处输入图像描述.

命令图像-&gt;

创建Carstep图像-&gt;

推荐答案

它适用于CreatingCarStep,因为它的枚举常量具有非空体.这迫使kotlin编译器 for each 枚举常量创建枚举类的子类.此外,枚举常量上的注释将放在生成的子类上.因此,enum::class.java计算为Class<*>实例,该实例表示具有FieldEnrich注释的CreatingCarStep子类.

当枚举常量的主体为空或根本没有主体时,不会生成任何子类.枚举常量是枚举类本身的实例.因此,enum::class.java的计算结果为Command::class.java,而Command::class.java没有FieldEnrich注释.

与其得到clazz.enumConstants并在::class.java上得到注释,不如得到枚举常量fields上的注释.这样,您就不必依赖于枚举常量是否有空体.

fun enrichClass(clazz: Class<*>) {
    clazz.declaredFields.forEach {
        if (it.isEnumConstant) {
            enrichField(it, clazz)
        }
    }
}

private fun enrichField(enumField: Field, clazz: Class<*>) {
    if (enumField.isAnnotationPresent(FieldEnrich::class.java)) {
        val fieldEnrich = enumField.getAnnotation(FieldEnrich::class.java)
        val values = configurationProvider.getProperty(fieldEnrich.property, Array<String>::class.java)
        val field = clazz.declaredFields.firstOrNull { it.name == fieldEnrich.field }
        field?.isAccessible = true
        field?.set(enumField.get(null), values)
    }
}

Java相关问答推荐

Spring Jpa findById会导致StackOverFlow错误,但其他查询没有问题

Kotlin ReadWriteProperty:无法使用T作为具体化类型参数.改为使用类

Java -使用空比较或instanceof?

Java 8 RDX-如何设置单个选项卡标题文本的 colored颜色

当耗时的代码完成时,Circular ProgressIndicator显示得太晚

将linkedHashMap扩展到Java中的POJO类

Java List with all combinations of 8 booleans

我需要生成一个文件来整合每个特性执行的所有JSON结果

我找不到&Quot;配置&的位置

如何创建一个2d自上而下的移动系统,其中移动,同时持有两个关键是可能的处理?

在处理2个映射表时,没有更多的数据可从套接字读取

当b是一个字节并且在Java中值为-1时,为什么b>;>;>;1总是等于-1?

如果List是一个抽象接口,那么Collectors.toList()如何处理流呢?

何时调用密封层次 struct 的switch 中的默认情况

具有最大共同前景像素的图像平移优化算法

处理4.3问题:javax.xml.ind包不存在(&Q;).您可能在学习GitHub教程时遗漏了库.&Q

接受类及其接口的Java类型(矛盾)

Java递归泛型是否可以被视为继承和重写的语法糖

基于距离的APACHE POI公式判断

验证没有';t work on Hibernate Entity';s字段