如何通过反射访问 Kotlin 中的类型使用注解?

huangapple go评论87阅读模式
英文:

How do I access type use annotations in kotlin through reflection?

问题

一个我正在使用的利用类型使用注解来对变量添加约束。例如,如果您想要一个可配置的不透明度(以百分比表示,由float类型表示),您可以对float类型进行注解:

public @Setting.Constrain.Range(min = 0, max = 1, step = 0.1) float opacity = 1f;

我无法让同样的库在相同的 Kotlin 代码上工作。

为了简化问题,让我们自己声明注解和使用方式:

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaAnnot { }
public class TestJava {

    @JavaAnnot int a = 5;

    public static void main(String[] args) {
        System.out.println(TestJava.class.getDeclaredFields()[0].getAnnotatedType().isAnnotationPresent(JavaAnnot.class));
    }

}

运行 TestJava#main 会得到 true,表明类型上存在 JavaAnnot 注解。

如果我们引入一个新的 Kotlin 类 TestKotlin,其中有一个类似的 a 字段和带有注解的类型:

class TestKotlin {

    val a: @JavaAnnot Int = 5

}

之前的检查,现在针对 TestKotlin 类:

TestKotlin.class.getDeclaredField("a").getAnnotatedType().isAnnotationPresent(JavaAnnot.class)

得到 false,表明 JavaAnnot 注解在 aInt 类型上不存在,尽管我们明确对其进行了注解。

我尝试过:

  • 使用 @JvmFielda 进行注解。但这并没有改变行为。
  • 在 Kotlin 中声明一个相同的注解:
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
annotation class KotlinAnnot
val a: @KotlinAnnot Int = 5

但这没有解决问题。

  • 检查通过反射可访问的其他元数据:我没有找到有用的信息。

这是 Kotlin 的一个 bug 吗?类型使用注解在 Kotlin 中不存在,还是语法不同?我做错了什么?

谢谢。

英文:

A library I'm using utilises type use annotations to add constraints to variables. For example, if you wanted a configurable opacity (in percent, represented by a float), you'd annotate the float type:

public @Setting.Constrain.Range(min = 0, max = 1, step = 0.1) float opacity = 1f;

I could not get the same library to work on identical kotlin code.

To simplify the question, let's declare the annotation and usage ourselves:

@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaAnnot { }
public class TestJava {

    @JavaAnnot int a = 5;

    public static void main(String[] args) {
        System.out.println(TestJava.class.getDeclaredFields()[0].getAnnotatedType().isAnnotationPresent(JavaAnnot.class));
    }

}

Running TestJava#main yields true, indicating that the JavaAnnot annotation is present on the type.

If we introduce a new kotlin class TestKotlin with a similar a field and annotated type:

class TestKotlin {

    val a: @JavaAnnot Int = 5

}

The previous check, now on the TestKotlin class:

TestKotlin.class.getDeclaredField("a").getAnnotatedType().isAnnotationPresent(JavaAnnot.class)

yields false, indicating that the JavaAnnot annotation is NOT present on the Int type of a, even though we clearly did annotate it.

I've tried:

  • Annotating a with @JvmField. This did not change the behaviour.
  • Declaring an identical annotation in kotlin:
@Target(AnnotationTarget.TYPE)
@Retention(AnnotationRetention.RUNTIME)
annotation class KotlinAnnot
val a: @KotlinAnnot Int = 5

Did not fix the problem.

  • Inspecting other metadata accessible through reflection: I did not find anything useful.

Is this a kotlin bug? Do type use annotations not exist in kotlin, or is the syntax different? What am I doing wrong?

Thanks.

答案1

得分: 1

自 Kotlin 字段的 AnnotatedType 的注解存储在 Kotlin Metadata 注解中,只能通过 Kotlin 反射访问。

更新:

自 Kotlin 1.4.0 起,编译器会按预期编写类型注解。

英文:

Annotations of AnnotatedType of Kotlin fields are stored with Kotlin Metadata annotation and can be accessed only by Kotlin Reflection.

Update:

Since Kotlin 1.4.0, the compiler writes type annotations as it is expected.

huangapple
  • 本文由 发表于 2020年7月26日 05:40:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63093833.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定