This presentation shows the advantages and how easy it is for a Java developer to switch to Kotlin. There is also a sample project on github, that compares the two languages at the example of a Spring Boot application: https://github.com/Meshcloud/spring-kotlin-example
8. 1. Null-Safety
Null checks during compilation:
var x = “value”
x = null // compile error
Great support for
handling nullable values:
var x:MyClass?
val child = x?.child
Intelligent compiler:
if (x != null) {
val child = x.child
} Elvis Operator:
projectRepository.findOne(id)
?: throw NotFoundException()
Force not null:
val y: String = x!!
9. 2. Mighty little helpers
String templates:
val text = "Project ${project.name} - ${project.description}"
Ranges
for (i in 1..100)
for (i in 10 downTo 1)
Structural equality with ==
project == otherProject // calls null-safe equals
project === otherProject // referential equality
Destructuring
for ((key, value) in map) {
print("Key: $key, Value: $value")
}
10. 3. Avoid property boilerplate
Data classes (with equals, hashcode, toString & copy):
data class Project(
val name: String,
val description: String,
val fullText: String
get() = “$name - $description”
)
Implicit Getters/Setters & property access:
class Project {
var name: String
}
Project().name
11. 4. Expressive arguments
Default Arguments:
fun create(
name: String,
description: String = “default”
)
Named Arguments
create(
name = “My Project”,
description = “Some details”
)
Apply method:
Project().apply(
name = “My Project”
description = “Some details”
)
13. 6. Concise Streaming API
Java:
projectRepository
.findAll()
.stream()
.map(p -> new ProjectListDTO(p))
.collect(Collectors.toList());
Kotlin:
projectRepository
.findAll()
.map { ProjectListDTO(it)}
14. 7. Reduce the overhead
Type Inference:
Map<ResourceType, List<Resource>> resourceMapByType =
service.findResourceMapByType(); // Java
val resourceMapByType = service.findResourceMapByType() // Kotlin
Smart Casts:
if (obj is Project) {
print(obj.description) // obj is now known to be a Project
}
When Expressions:
when {
"Bitcoin" in projectNames -> println("Bad guy!")
projectNames is empty -> println("No Projects")
else -> println("Just normal projects!")
}
15. 8. Further concepts in Kotlin
Coroutines:
// experimental simplified non-blocking IO async implementation
async {
doSomething(foo)
...
}
Operator Overloading:
data class Vec(val x: Float, val y: Float) {
operator fun plus(v: Vec) = Vec(x + v.x, y + v.y)
}
val v = Vec(2f, 3f) + Vec(4f, 1f)
17. SDR ResourceProcessors
Controller with nullable param:
class ProjectController {
@GetMapping
open fun findAllOwnedByCurrentUser(principal: Principal?) {
principal!!
...
}
}
ResourceProcessor using null params
@Component
class ProjectResourceProcessor: ResourceProcessor<Resource<Project>> {
override fun process(resource: Resource<Customer>): Resource<Project>
{
resource.add(linkTo(methodOn(ProjectController::class.java)
.findAllOwnedByCurrentUser(null)).withRel("ownedProjects"))
}
}
18. Repo Queries with raw strings
@Query("""
SELECT o FROM #{#entityName} o
WHERE (o.email LIKE %:searchTerm% OR o.username LIKE %:searchTerm% OR o.name LIKE %:searchTerm%)
AND (
(
?#{principal.customer.id} IN (SELECT customer.id FROM CustomerUserGroup WHERE user.id = o.id)
OR ?#{principal.customer.id} IN (SELECT partner.id FROM CustomerUserGroup WHERE user.id = o.id)
)
AND 1 = ?#{ hasAuthority('USER_LIST') ? 1 : 0 }
OR 1 = ?#{ hasAuthority('ADM_USER_LIST') ? 1 : 0 }
)
""")