Возьмем класс класса данных:
data class User(
val userNumber: Int = -1,
val name: String,
val userGroups; List<String> = emptyList(),
val screenName: String = "new-user"
)
При вызове этой функции из Kotlin это довольно просто. Для этого я могу просто использовать синтаксис named-argument. Вызов из Java, я должен указать все значения или использовать аннотацию @JvmOverloads
, которая генерирует следующие конструкторы (в дополнение к конструктору, который kotlin генерирует с битовой маской для значений по умолчанию):
User(int userNumber, @NotNull String name, @NotNull List userGroups,
@NotNull String screenName)
User(int userNumber, @NotNull String name, @NotNull List userGroups)
User(int userNumber, @NotNull String name)
User(@NotNull String name)
Теперь, если я хочу создать объект User
в Java, эквивалентный User(name="John Doe", userGroups=listOf("admin", "super")
, я не могу сделать это с помощью указанных выше конструкторов. Я могу, однако, сделать это, если я положил val userNumber: Int = -1
в конце объявления data class
(генерация конструкторов, похоже, зависит от порядка, в котором определены дополнительные аргументы). Это хорошо, потому что ожидая, что котлин будет генерировать все перестановки, будет сильно раздуваться несколько классов.
Самая большая проблема в том, что такие инструменты, как Jackson
, просто не работают, поскольку они понятия не имеют, какой конструктор использовать (а не как я могу аннотировать один из сгенерированных специально).
Итак, есть способ генерации (одиночного) конструктора типа:
User(Integer userNumber, String name, List<String> userGroups, String screenName) {
this.userNumber = (userNumber == null) ? -1 : userNumber;
this.userGroups = (userGroups == null) ? Collections.emptyList() : userGroups;
//...
}
В настоящее время я использую вышеупомянутый подход, но вручную определяю конструкторы, в которых они мне нужны.
ИЗМЕНИТЬ
Я должен уточнить, создание аналогичного конструктора не работает, очевидно, потому что обе подписи будут сталкиваться с JVM. Это то, что он хотел бы в моем случае:
data class User(
val userNumber: Int = -1,
val name: String,
val userGroups; List<String> = emptyList(),
val screenName: String = "new-user"
) {
companion object {
@JvmStatic
@JsonCreator
fun constructionSupport(
@JsonProperty("userNumber") userNumber : Int?,
@JsonProperty("name") name : String,
@JsonProperty("userGroups") userGroups : List<String>?,
@JsonProperty("screenName") screenName : String?
) = User(
userNumber = userNumber ?: -1,
name = name,
userGroups = userGroups ?: emptyList(),
screenName = screenName ?: "new-user"
)
}
}
Также обратите внимание на избыточность, когда я должен дважды писать значения по умолчанию для свойств. Теперь, когда я смотрю на это, я сомневаюсь, что для этого существует решение. Возможно, это хороший прецедент для моего бокового проекта kapt
:)