Kotlin初探
Kotlin资料汇总
如何看待 kotlin
- a better java、 java-kotlin 特别版 、java-语法糖特别版
- java 系开发了解新一代函数式编程语言、跨平台客户端编程的绝佳选择
- 上手快、java 原本的生态都在 不需要改变技术栈 可以无缝转换
- java:繁体 kotlin:简体 go:草书**
上手
在线(任选)
英语好的直接上手官方文档:https://kotlinlang.org/docs/basic-syntax.html
英语不好的看中文:https://book.kotlincn.net/text/basic-syntax.html
快速熟悉语法:https://www.runoob.com/kotlin/kotlin-basic-syntax.html
- 极客时间:朱涛 kotlin第一课(先熟悉语法再看)
书籍
视频
IDEA练习
- IDEA课程:kotlin koans
提示
任选其一了解语法基础可以上手应用了
如果kt代码看着别扭 那是因为还没有习惯
协程进阶
书籍:
很好的图书搜索网址-且行且珍惜
生态
- 生态:awesome kotlin https://kotlin.link/
应用
使用gradle
熟悉即可
- Gradle vs Maven 基本对比
- Migrating Spring Boot’s Build to Gradle
- 自从用完Gradle后,有点嫌弃Maven了!速度贼快!
- 从Apache Maven迁移构建
- Gradle学习笔记
Gradle | Gradle vs Maven Comparison - SpringBoot+Gradle构建多模块项目 - 掘金
- Gradle最佳实践 - 木小丰 - 博客园
为什么要用它?
- 性能和速度
增量构建: Gradle 支持增量构建功能,能够通过检测哪些部分的代码和配置发生了更改,仅构建需要更新的部分,从而加快构建速度。 高效缓存: Gradle 使用本地构建缓存和远程构建缓存,减少了重复任务的执行时间,加快了构建过程。
- 灵活性和可扩展性
灵活的构建脚本: Gradle 使用 Groovy 或 Kotlin DSL,让你可以编写更灵活和可编程的构建脚本。这种灵活性可以实现复杂的自动化任务。 插件生态系统: Gradle 提供了数量庞大的插件库,可以为不同的需求快速添加功能,包括代码质量检查、部署、自定义构建步骤等。
- 简洁性和可维护性
简化的项目配置: Gradle 的 DSL 可以显著减少繁琐冗长的 XML 配置,从而提高可读性和可维护性。 更好的多项目构建支持: Gradle 本身对多项目的支持更加自然且易于配置。它可以自动化项目间的依赖关系并管理版本。
- 灵活的平台、环境无关性
Gradle 的工具链功能(Java Toolchains)是一项强大的特性,使得构建环境更加独立于开发者的本地环境,进而提升平台无关性,并在开发和生产环境间始终保持一致性,更加符合云原生。

集成spring
spring生态下语言支持系列:Kotlin :: Spring Framework
**springboot项目必读 **:Spring Projects in Kotlin :: Spring Framework
提示
看完必读 下述差异问题大多都不复存在 总体来说与Java无异,上手非常快,没有难度,Java水平如何就如何,但有些使用方式需要做些改变
现有maven转gradle项目:Migrating Builds From Apache Maven
可以转 但效果一般 还是要自己修改
差异
实体问题
**必须要理解 kt 对于类的定义 **Kotlin:类(class)概述
不管是 data class 还是 class 当所有属性都富有初始值时,编辑器才会默认创建一个无参构造val name ="" val name? ="" 还是 name? = null 都属于赋值
lombok问题
kotlin lombok支持还在实验性阶段 没有很好的builder模式构建实体赋值
实体属性复制
kt的pojo实体类使用 data class
缺少 builder 类 实体属性复制
使用map struct 或map struct plus 使用静态增强代码方式 原生set方式 性能比反射高
implementation("io.github.oshai:kotlin-logging-jvm:4.0.0-beta-22")配置项
提示
尽可能使用properties类属性配置
@value 转义问题
https://blog.csdn.net/aa642531/article/details/112131264
配置Properties
解决办法:
https://spring.io/guides/tutorials/spring-boot-kotlin/ --- 属性配置
jackson序列化问题
添加 jackson-module-kotlin
假设有这样一个类
data class RedisAddReq(
/**
* key
*/
@field: NotBlank(message = "redis key 不能为空")
var key: String = "",
/**
* value
*/
@field: NotBlank(message = "redis value 不能为空")
var value: String,
/**
* ttl
*/
var ttl: Long = 0L,
/** redis数据类型 */
@field:NotNull(message = "redis 类型不能为空")
var redisDataType: Int
)传递json参数的时候不传递key
{
// "key": "test_35ac617fa272",
"value": "test_5604abeaeae4",
"ttl": 68,
"redisDataType": 1
}这个时候会报错:不是因为上述少了个属性 key,而是因为没有无参构造
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `team.aikero.scf.grocery.redis.vo.req.RedisAddReq` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 2, column: 3]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1615)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1332)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:331)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4524)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3519)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:273)
... 63 common frames omitted添加依赖:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
<version>2.11.2</version>
</dependency>implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.11.2")如果没有生效 检查一下objectMapper是否已经加载了module(registerKotlinModule)
objectMapper.registerKotlinModule()参数校验
针对可空类型
相关信息
针对构造器定义属性方式无效 需要设置标记告诉编译器处理在 getter 或 field
针对普通类:
/**
* 使用构造器定义属性 需要加小逗号 还要转换 JSR 的注解打在 getter 或 field 上
*/
class SimpleClassReqWitConstructor constructor(
@field: NotBlank(message = "name不能为空")
val name: String? = null,
val pwd: String? = null,
val age: Int? = null,
) {
//注意这里是空的
}针对 data class
/**
*
* 和普通类的构造器定义属性一样
*/
data class DataClassReqWithDefNull(
@field:NotBlank(message = "name不能为空")
val name: String? = null,
val pwd: String? = null,
val age: Int? = null
) {
//注意这里是空的
}结构体定义的属性正常使用
/**
* 这一种方式属性定义在结构体(类体花括号)内 使用方式无差 并且可以不用小数点
* 因为所有字段可空并且初始值是 null kt 默认会创建一个无参构造
*
*/
class SimpleClassReqWithBody {
@NotBlank(message = "name不能为空")
val name: String? = null
val pwd: String? = null
val age: Int? = null
}
// 但是它没有全参构造 SimpleClassReqWithBody("dadsa", "dsadsa", 1)
// 只能SimpleClassReqWithBody()针对不可空类型
/**
* 不为空属性定义
* 这就表明所有的属性在传递的时候是都要给值的
*/
data class DataClassReq(
// 这样原始的注解是不起作用的
@NotBlank(message = "name不能为空")
val name: String,
// 这里定义了 pwd 不可为空 不赋值是可以的
val pwd: String,
val age: Int
) {
//注意这里是空的
}**正常传递全部属性 没问题 **
**有任何一个属性不传的都将报错 因为不可为空嘛 **
{
"pwd": "pwd_grx7d",
"age": 1
}org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Instantiation of [simple type, class com.example.cleanspring2kt.DataClassReq] value failed for JSON property name due to missing (therefore NULL) value for creator parameter name which is a non-nullable type; nested exception is com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class com.example.cleanspring2kt.DataClassReq] value failed for JSON property name due to missing (therefore NULL) value for creator parameter name which is a non-nullable type
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 4, column: 1] (through reference chain: com.example.cleanspring2kt.DataClassReq["name"])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:391)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:343)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:185)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:160)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:133)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)注意⚠️ Int 不赋值有默认值 0
{
"name": "name_pj6p0",
"pwd": "pwd_grx7d"
}不会报错 age=0
DataClassReq(name=name_pj6p0, pwd=pwd_grx7d, age=0)正确做法
/**
* 不为空属性定义
*/
data class DataClassReq(
@field:NotBlank(message = "name不能为空")
val name: String = "",
val pwd: String = "",
val age: Int = 0
) {
//注意这里是空的
}
// 添加 @field 很重要
// 指定 String=“” 也很重要尽管 data class 在使用上有一些不一样,但还是建议用 data class数据类 · Kotlin 官方文档 中文版

字段序列化问题
这是JavaBean规范!JavaBean
对于Java来说 当属性类型为Boolean类型并且属性名为isXxx开头的 默认生成的setter getter 会擦除is前缀!在序列化框架下会变为xxx名称 曾经的项目没有问题 因为没有使用Boolean类型而是Integer类型
kotlin把这个传统扩大到了任意类型 所有类型is开头都会擦除is前缀,连String也不放过 以前isXxxx相关字段全是违背Java规范的 避免无谓的问题
提示
数据库字段与实体属性禁止 is前缀开头 直接使用形容词 名词定义 不影响词义 enable deleted 完全能表示意思 避免不必要的兼容处理!兼容是无奈之举 不是秀操作的地方! 属性名不让用 is 开头,应该用什么?
数据库设计中boolean类型的处理 - 后端知识 - UJCMS
