Значение Kotlin not nullable может быть null?

у меня есть бэкэнд, который возвращает мне JSON.

я разбираю его в своем классе:

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 converter, потому что notNullableValue нет в моем ответе JSON):

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

после того, как данные получен из бэкэнда и проанализирован в мой класс SomeData с конструктором без значения def, значение notNullableValue == null.

как я понимаю, значение not nullable может быть null в Kotlin?

2 ответов


Да, это потому, что вы даете ему значение по умолчанию. Конечно, он никогда не будет null. В этом весь смысл значения по умолчанию.

удалить ="" из конструктора, и вы получите ошибку.

Edit: найдена проблема. GSON использует магию sun.misc.Unsafe класс, который имеет allocateInstance метод, который, очевидно, считался очень unsafe потому что он пропускает инициализацию (конструкторы/инициализаторы полей и тому подобное) и проверки безопасности. Итак, вот ваш ответьте, почему поле Kotlin non-nullable может быть null. Обидеть кода com/google/gson/internal/ConstructorConstructor.java:223

некоторые интересные детали о Unsafe класс: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 не null - пустой