在Kotlin中使用枚举类getter中的when子句

时间:2018-05-09 22:01:21

标签: enums kotlin switch-statement getter

我正在尝试在kotlin中获取属性的特定getter,以基于调用它的枚举值。这是我到目前为止所得到的:

enum class Endpoint {
    EVENTS, GAMES;

    val baseUrl = "https://www.example.com/api"

    val path: String
        get() = when(this){
            EVENTS -> "$baseUrl/events"
            GAMES -> "$baseUrl/games"
        }
}

这样称呼:

print(Endpoint.EVENTS.path)

虽然这个编译没有任何问题,但只要我运行它就会得到NullPointerException错误Attempt to invoke virtual method 'java.lang.Object [...].Endpoint[].clone()' on a null object reference

我不确定我做错了什么或者完成上述内容的正确方法是什么。

编辑:异常的完整记录:

05-09 22:51:33.793 15673-15673/com.filippovigani.eventvods E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.filippovigani.eventvods, PID: 15673
java.lang.ExceptionInInitializerError
    at com.filippovigani.eventvods.networking.Endpoint.getPath(Endpoint.kt:21)
    at com.filippovigani.eventvods.networking.Endpoint.<init>(Endpoint.kt:25)
    at com.filippovigani.eventvods.networking.Endpoint.<clinit>(Endpoint.kt)
    at com.filippovigani.eventvods.networking.EventvodsApi$Companion.getEvents(EventvodsApi.kt:8)
    at com.filippovigani.eventvods.MainActivity.onCreate(MainActivity.kt:19)
    at android.app.Activity.performCreate(Activity.java:5990)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
    at android.app.ActivityThread.access$800(ActivityThread.java:151)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5254)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object com.filippovigani.eventvods.networking.Endpoint[].clone()' on a null object reference
    at com.filippovigani.eventvods.networking.Endpoint.values(Endpoint.kt)
    at com.filippovigani.eventvods.networking.Endpoint$WhenMappings.<clinit>(Unknown Source)
    at com.filippovigani.eventvods.networking.Endpoint.getPath(Endpoint.kt:21) 
    at com.filippovigani.eventvods.networking.Endpoint.<init>(Endpoint.kt:25) 
    at com.filippovigani.eventvods.networking.Endpoint.<clinit>(Endpoint.kt) 
    at com.filippovigani.eventvods.networking.EventvodsApi$Companion.getEvents(EventvodsApi.kt:8) 
    at com.filippovigani.eventvods.MainActivity.onCreate(MainActivity.kt:19) 
    at android.app.Activity.performCreate(Activity.java:5990) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) 
    at android.app.ActivityThread.access$800(ActivityThread.java:151) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5254) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

2 个答案:

答案 0 :(得分:3)

我无法重现您的错误,代码工作正常。不过,我认为解决方案有点过于复杂,为什么不使用构造函数参数来提供常量特定的值:

enum class Endpoint(service: String) {
    EVENTS("/events"), GAMES("/games");

    private val baseUrl = "https://www.example.com/api"
    val path: String = baseUrl + service
}

答案 1 :(得分:1)

该异常表示您尝试在枚举的构造函数中访问path。这会导致问题,因为在构造期间枚举还没有准备好使用。

这意味着以下调用链导致失败:

  1. 初始Endpoint
  2. 初始Endpoint.EVENTS
  3. 致电Endpoint.getPath()(此代码中未显示)
  4. 使用Endpoint$WhenMapping,开始该类的初始化。
  5. Endpoint$WhenMapping使用EndPoint.values(),但由于我们仍在初始化枚举的实例,因此无法提供values数组,返回null
  6. 为了确保它不被修改,WhenMapping克隆并缓存数组,但由于数组为空,因为它永远不应该在初始化之外,这会导致NPE。
  7. 简单地把你的代码放在某种程度上依赖于一个需要完全初始化才能使用的类。由于您的代码未显示您正在调用Endpoint.EVENTS.path的方式,因此可以说明这一点。