Kotlin 不可空值可以为空吗?

Kotlin not nullable value can be null?

我有后端 return 我有一些 json。

我将其解析为我的 class:

class SomeData(
  @SerializedName("user_name") val name: String,
  @SerializedName("user_city") val city: String,
  var notNullableValue: String)

使用gson转换器工厂:

Retrofit retrofit = new Retrofit.Builder()
  .baseUrl(ENDPOINT)
  .client(okHttpClient)
  .addConverterFactory(GsonConverterFactory.create(gson))
  .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  .build();

在我的界面中:

interface MyAPI {
    @GET("get_data")
    Observable<List<SomeData>> getSomeData();
}

然后我从服务器(使用 rxJava)检索数据,没有任何错误。但我预计会出现错误,因为我认为我应该做这样的事情(以防止 GSON 转换器错误,因为 notNullableValue 不存在于我的 JSON 响应中):

class SomeData @JvmOverloads constructor(
  @SerializedName("user_name") val name: String,
  @SerializedName("user_city") val city: String,
 var notNullableValue: String = "")

从后端接收数据并使用没有 def 值的构造函数解析到我的 SomeData class 后,notNullableValue == null 的值。

据我了解,不可空值在 Kotlin 中可以为空?

是的,那是因为您为其指定了默认值。当然它永远不会为空。这就是默认值的全部意义所在。

从构造函数中删除 ="",您将得到一个错误。

编辑:发现问题。 GSON 使用神奇的 sun.misc.Unsafe class 它有一个 allocateInstance 方法,这显然被认为是非常 unsafe 因为它所做的是跳过初始化(constructors/field 初始化器等) 和安全检查。所以这就是为什么 Kotlin 不可空字段可以为空的答案。违规代码在 com/google/gson/internal/ConstructorConstructor.java:223

关于 Unsafe class 的一些有趣细节:http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/

尝试像这样覆盖构造函数:

class SomeData(
        @SerializedName("user_name") val name: String,
        @SerializedName("user_city") val city: String,
        var notNullableValue: String = "") {
    constructor() : this("","","")
}

现在在服务器响应后,您可以检查 notNullableValue 是否为空 - 它是空的