如何从枚举在 Kotlin 中创建编译时常量?

Posted

技术标签:

【中文标题】如何从枚举在 Kotlin 中创建编译时常量?【英文标题】:How to create compile-time constant in Kotlin from enum? 【发布时间】:2020-05-06 16:32:30 【问题描述】:

我有一个注释,要求 defaultValue 是编译时常量。我从下面的enum 中取defaultValue

enum class RaceType 
    MARATHON,
    SPRINT;

    companion object 
        fun apply(type: RaceType): RaceDto 
            return when (type) 
                MARATHON -> MarathonDto()
                SPRINT -> SprintDto()
            
        
    

我的dtos 如下:

interface RaceDto 


data class MarathonDto: RaceDto

data class SprintDto: RaceDto

当我使用注解 @QraphQLArgument(defaultValue = RaceType.SPRINT.name) 时,Kotlin 要求 RaceType.SPRINT.name 是编译时常量。

注解实现本身:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface GraphQLArgument 
    String NONE = "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
    String NULL = "\n\t\t\n\t\t\n\ue000\ue001\ue002\ue003\n\t\t\t\t\n";

    String name();

    String description() default "";

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";

    Class<? extends DefaultValueProvider> defaultValueProvider() default JsonDefaultValueProvider.class;

我查看了similar questions,但没有找到解决方法。我还发现了与该主题相关的article,但到目前为止没有任何效果。

旁注:我无法更改注释,因为它来自库,我也无法更改库。

总而言之,有没有办法让 Kotlin 中的 enum 编译时常量在注解中使用?

【问题讨论】:

【参考方案1】:

有没有办法让 Kotlin 中的 enum 编译时常量在注解中使用?

不,因为正式的 enums aren't compile-time constants in Java。

但是请考虑sealed 类:

sealed class RaceType 
    object MARATHON: RaceType() 
        const val name = "MARATHON" // copy-paste is required here until https://youtrack.jetbrains.com/issue/KT-16304
    
    object SPRINT: RaceType()

    companion object 
        fun apply(type: RaceType): RaceDto 
            return when (type)  // the check is in compile time, because of sealed class
                MARATHON -> MarathonDto()
                SPRINT -> SprintDto()
            
        
    

仍然需要一小部分复制粘贴。请投票kotlin compiler bug 或follow this thread。

但是,据我了解,不幸的是,这并不能解决您对@QraphQLArgument(defaultValue = RaceType.SPRINT.name) 的问题,因为类的名称与值不同。换句话说,对于密封类,您需要编写代码将输入字符串转换为它们。

【讨论】:

谢谢。这是一个很好的解决方法,至少我知道为什么我找不到解决方案。

以上是关于如何从枚举在 Kotlin 中创建编译时常量?的主要内容,如果未能解决你的问题,请参考以下文章

在kotlin中使用java自定义注释

枚举使用编译时常量转换为字符串

KotlinKotlin 变量与常量 ( 变量声明 | 只读变量 | 类型推断 | 编译时常量 | Kotlin 字节码查看面板 | Kotlin 引用数据类型 )

从文字字符串生成编译时常量整数

Kotlin 中变量,类型,表达式,函数详解

Kotlin 中变量,类型,表达式,函数详解