JVM
Android
Browser
Native
Kotlin 1.6
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
BackEndHills
DesktopCountry
VeganGrounds
MobileRivers
CloudMountains
ConfigIsland
FrontendArea
NativeGrounds
https://www.menti.com
Code: 1842 9218
public class Person {
private final String firstName;
private final String lastName;
private final LocalDate birthDay;
public Person(String firstName, String lastName,
LocalDate birthDay) {
this.firstName = firstName;
this.lastName = lastName;
this.birthDay = birthDay;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public LocalDate getBirthDay() {
return birthDay;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(firstName, person.firstName) &&
Objects.equals(lastName, person.lastName) &&
Objects.equals(birthDay, person.birthDay);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName, birthDay);
}
@Override
public String toString() {
return "Person{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", birthDay=" + birthDay +
'}';
}
}
data class PersonK(
val firstName: String,
val lastName: String,
val birthDay: LocalDate
)
Java
Kotlin
Prägnanz
Sicher
var name: String
name = null
println(name.length)
Kotlin
// Compile Error 🤗
⚡NullpointerException 🤔
var name: String?
name = null
if(name != null){
println(name.length)
}
Sicher
var output: String
output = null
Kotlin
val name: String? = null
println(name.length)
fun calculateTotal(obj: Any) {
if (obj is Invoice){
obj.calculateTotal()
}
}
fun isCloneBaby(father: Person, son: Person): Boolean {
return father == son
}
// Compile Error
// Compile Error
// Autocast
// equals()
Interoperabel
fun callJava(){
val backend = LegacyBackend()
backend.sendMail("Be prepared... we deploy")
}
Kotlin
private void callKotlin(){
var backend = new NewBackend();
backend.sendSlack("We introduced NetID oAuth!");
}
Java
Interoperabel
Optimales Tooling
Prägnant
Sicher
Interoperabel
Optimales Tooling
Frei & OpenSource
Inline Classes
Extensions
Delegtions
String Builders
Contracts
Operator Overloading
Gradle DSL
Data Classes
Coroutines
https://stackshare.io/kotlin
https://octoverse.github.com
https://github.com/ygaller/kotlin-companies/wiki
Trello
Evernote
Trivago
Runtastic
Tinder
Uber
My Taxi
Klarna
Mastercard
N26
182 %
Wachstum auf GitHub 2019
Jul 2011 - Öffentliche Bekanntmachung
Feb 2016 - Release Version 1.0
Nov 2017 - Release Version 1.2
Mai 2017 - Offizielle Sprache für Android
Kotlin Native v0.4 & Multiplatform
Okt 2018 - Gründung Kotlin Foundation
Jul 2011 - Öffentliche Bekanntmachung
Feb 2016 - Release Version 1.0
Nov 2017 - Release Version 1.2
Mai 2017 - Offizielle Sprache für Android
Kotlin Native v0.4 & Multiplatform
Okt 2018 - Gründung Kotlin Foundation
Aug 2020 - Kotlin Multiplatform Mobile - Alpha
Nov 2020 - Jetpack Compose for Desktop - M1
Mai 2021 - Jetpack Compose for Web
Nov 2021 - Release Kotlin 1.6
Dez 2021 - Compose Multiplatform 1.0
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Kotlin
Compiler
Java
Compiler
Kotlin
Runtime
*.kt
*.class
*.java
*.jar
Interoperabel
fun callJava(){
val backend = LegacyBackend()
backend.sendMail("Be prepared... we deploy")
}
Kotlin
private void callKotlin(){
var backend = new NewBackend();
backend.sendSlack("We introduced NetID oAuth!");
}
Java
https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html
@RestController
public class HelloController {
@GetMapping("/hello")
public String handle() {
return "Hello WebFlux";
}
}
Spring WebFlux provides an annotation-based programming model, where @Controller and @RestController components use annotations to express request mappings, request input, handle exceptions, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces.
The following listing shows a basic example:
https://docs.spring.io/spring/docs/.../web-reactive.html
Kotlin
Java
@RestController
class HelloController {
@GetMapping("/hello")
fun handle() = "Hello WebFlux"
}
Spring WebFlux provides an annotation-based programming model, where @Controller and @RestController components use annotations to express request mappings, request input, handle exceptions, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces.
The following listing shows a basic example:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html
https://docs.spring.io/spring/docs/.../web-reactive.html
Kotlin
Java
Kotlin
Java
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
plugins {
kotlin("jvm") version "1.5"
java
}
group = "de.tfr.presentation"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-js"))
testCompile("junit", "junit", "4.12")
}
configure<JavaPluginConvention> {
languageVersion.set(JavaLanguageVersion.of(11))
}
Example 1. Dependency declarations for a JVM-based project
Groovy
Kotlin
plugins {
id 'java-library'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.hibernate:hibernate-core:3.6.7.Final'
api 'com.google.guava:guava:23.0'
testImplementation 'junit:junit:4.+'
}
Example 1. Dependency declarations for a JVM-based project
Groovy
Kotlin
plugins {
`java-library`
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.hibernate:hibernate-core:3.6.7.Final")
api("com.google.guava:guava:23.0")
testImplementation("junit:junit:4.+")
}
fun ourCoolBuildScript(){
val timeStamp = LocalDateTime.now()
downloadI18nMessages()
formatMessageProperties()
mergeChangeLogEntries(timeStamp)
sendSlackMessage("We're gonna deploy that stuff 🤘")
}
*.kts
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Kotlin Native
Technologie um Kotlin Code zu nativen Binaries zu kompilieren, die ohne VM laufen.
JVM
Android
Browser
Native
Kotlin
Compiler
LLVM
Compiler
*.kt
LLVM IR
*.exe
The LLVM Compiler Infrastructure.
IR = Intermediate Representation
Kotlin
Compiler
Kotlin
Compiler
*.kt
LLVM IR
*.exe
The LLVM Compiler Infrastructure.
IR = Intermediate Representation
Frontend
Backend
val appData = SystemUtil.getEnvironmentVariable("LOCALAPPDATA")
val toolboxPath = """$appData\JetBrains\Toolbox"""
val channelsPath = """$toolboxPath\apps\IDEA-U\ch-0\"""
fun main(args: Array<String>) {
runIntelliJ(getProjectPath(args))
}
fun runIntelliJ(projectPath: String?) {
File(path = channelsPath)
.listAllFolders()
.filter(::isVersion)
.mapToVersion()
.findNewestVersion()
?.getIntellIJPath()
?.exec(params = projectPath)
}
import kotlinx.cinterop.alloc
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.ptr
import kotlinx.cinterop.toKString
import platform.windows.*
data class File(val fileName: String? = null, val path: String, val type: Type) {
enum class Type { File, Folder, Unknown }
fun listAllFiles(): List<File> {
val searchPath = "$path*".replace("/", "\\")
val files = mutableListOf<File>()
val fileData = nativeHeap.alloc<_WIN32_FIND_DATAA>()
val handle: HANDLE? = FindFirstFileA(searchPath, fileData.ptr)
var fileNumber = 0
val maxFilesToScan = 1000
if (handle != INVALID_HANDLE_VALUE) {
do {
val fileName = fileData.cFileName.toKString()
var type = Type.Unknown
if (fileData.dwFileAttributes.toInt() and FILE_ATTRIBUTE_NORMAL > 0) {
type = Type.File
}
if (fileData.dwFileAttributes.toInt() and FILE_ATTRIBUTE_DIRECTORY > 0) {
type = Type.Folder
}
files += File(fileName = fileName, path = path, type = type)
fileNumber++
} while (FindNextFileA(handle, fileData.ptr) != 0
&& fileNumber < maxFilesToScan)
FindClose(handle)
} else {
println("Illegal Path")
}
return files
}
fun exec(params: String? = "") {
val command = "${toAbsolutePath()} ${params ?: ""}"
WinExec(command, SW_SHOW)
}
fun toAbsolutePath(): String {
return path + fileName
}
fun listAllFolders(): List<File> {
return listAllFiles().filter { file -> file.type == Type.Folder }
}
fun isFolder() = type == Type.Folder
override fun toString() = "$type:${toAbsolutePath()}"
}
Wie schnell ist das denn?
Wie schnell ist das denn?
fun main(args: Array<String>) {
val start = getTimeMillis()
var c = 0L
var string = ""
for(i in 0.. 100_000){
c += (i / 2)
c += 1
string += c
}
println( getTimeMillis() - start)
}
BENCHMARK
[ millisekunden / run ] ► weniger ist besser
IT DEPENDS
Source Code
Runtime
VM
Graal
VM
Graal
JVM
Java 15
JVM
Java 15
Math
String
Memory
Math
String
Memory
Chromium
Native Win x64
Kotlin 1.5
Kotlin 1.4
Compiler
fun benchMath(iterations: Int): Double {
var c = 0.0
for (i in 0..iterations) {
c += (i / 2.0)
c += (i % 3.0)
c += sqrt(i * 3.0)
c += 1
}
return c
}
Math Benchmark
100_000_000
fun benchString(iterations: Int) {
var c = 0L
var string = ""
for (i in 0..iterations) {
c += (i / 3)
c += 1
val next = c % 10
string += next
}
}
String Benchmark
100_000
fun benchObjectList(iterations: Int): Int {
val list = mutableListOf<Machine>()
for (i in 0..iterations) {
list.add(Machine("ABC-0$i", i, i / 3.0))
}
return list.size
}
class Machine(val name: String, val wheels: Int, val weight: Double)
Memory Benchmark
10_000_000
void benchMath(int iterations) {
var c = 0.0;
for (int i =0; i < iterations; i++) {
c += (i / 2.0);
c += (i % 3.0);
c += Math.sqrt(i * 3.0);
c += 1;
}
}
Math Benchmark
100_000_000
void benchString(int iterations) {
var c = 0;
var string = "";
for (int i = 0; i < iterations; i++) {
c += (i / 3);
c += 1;
var next = c % 10;
string += next;
}
}
String Benchmark
100_000
Math Benchmark
100_000_000
public class BenchmarkMemory {
void benchObjectList(int iterations) {
var list = new ArrayList<PerpetuumMobile>();
for (int i = 0; i < iterations; i++) {
list.add(new PerpetuumMobile("ABC-0" + i, i, (i / 3.0)));
}
}
private static class Machine {
String name;
Integer wheels;
Double weight;
public Machine(String name, int wheels, double weight) {
this.name = name;
this.wheels = wheels;
this.weight = weight;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Machine that = (Machine) o;
return wheels == that.wheels && Double.compare(that.weight, weight)
== 0 && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, wheels, weight);
}
}
}
Chrome Headless | 90.4430.93 |
Open JDK | 15.0.2 |
GraalVM Native-Image | 21.0.0.2 |
Windows 10 x64 | AMD Ryzen 7 1800X 64GB RAM |
Und der Speicher?
Und der Speicher?
Und der Speicher?
Memory Benchmark 10_000_000
Und der Speicher?
Und der Speicher?
Wie groß ist es?
Wie groß ist es?
Wie groß ist es?
Kotlin Native Hallo World
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Language Choice
High Performance
Advanced Tools
Ahead-of-Time Compilation
Startup Time
Memory Footprint
Kotlin Native | Graal VM | |
---|---|---|
Fokus | Interoperabilität | Polyglot + Performance |
Sprache | Kotlin 1.6 | Java 17, R, JS, Python |
Status | Beta | 21.3 |
Platform | Win, Linux, Mac, IOS, Android, Embedded | Linux, Mac, (Win) |
Lizenz | Apache License 2.0 | GPL - Community Ed. |
kotless {
config {
aws {
storage {
bucket = "kotless.s3.example.com"
}
profile = "example"
region = "eu-west-1"
}
}
webapp {
dns("kotless", "example.com")
}
}
Kotlin serverless framework
settings.gradle.kts:
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Kotlin
Transpiler
*.kt
*.ts
*.js
*.map
[
{
"title": "Temtem",
"price": "39,99 €",
"description": "Temtem ist ein Multiplayer-Kreaturen-Sammlung Abenteuer,
inspiriert von Pokémon.",
"url": "https://store.steampowered.com/app/745920/Temtem/",
"coverUrl": "https://steamcdn-a.akamaihd.net/steam/apps/745920/header.jpg"
},
{
"title": "A Plague Tale: Innocence",
"price": "39,99 €",
"description": "Folge den Spuren von Hugo [..]",
"url": "https://store.steampowered.com/app/752590/A_Plague_Tale_Innocence/",
"coverUrl": "https://steamcdn-a.akamaihd.net/steam/apps/752590/header.jpg"
}
]
game_wishlist.json
plugins {
id("kotlin2js") version "1.6.10"
}
dependencies {
implementation(kotlin("stdlib-js"))
}
build.gradle.kts
<html>
<body>
<!-- Link to the compiled js files-->
<script src="kotlin.js"></script>
<!-- Link to the compiled js files-->
<script src="output.js"></script>
</body>
</html>
index.html
import kotlinx.browser.document
import kotlinx.browser.window
import kotlinx.dom.addClass
import org.w3c.dom.Element
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLImageElement
fun build(game: Game): Element {
val containerElement = document.createElement("div") as HTMLDivElement
val imageElement = document.createElement("img") as HTMLImageElement
val titleElement = document.createElement("div") as HTMLDivElement
val priceElement = document.createElement("div") as HTMLDivElement
val descriptionElement = document.createElement("div") as HTMLDivElement
}
data class Game(val title: String, val price: String, val description: String, val url: String, val coverUrl: String)
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Kotlin
Compiler
Java
Compiler
*.kt
*.class
*.java
JVM
Java Virtual Machine
Kotlin
Compiler
Java
Compiler
*.kt
*.class
*.java
DEX
Compiler
DVM
Dalvik Virtual Machine
Kotlin
Compiler
Java
Compiler
*.kt
*.class
*.java
DEX
Compiler
ART
Android Runtime
AOT
Compiler
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Technologie um Kotlin Code auf unterschiedlichen Plattformen
wiederzuverwenden.
Kotlin 1.3
JVM
JS
Linux
macOS
Common
JVM
JS
Linux
macOS
Common
Native
JVM + JS
JVM
JS
Linux
macOS
Common
Native
JVM + JS
JVM
JS
Linux
macOS
Common
Native
JVM + JS
JVM
JS
Linux
macOS
Common
Native
JVM + JS
*.kt
Kotlin
Compiler
Kotlin
Compiler
Kotlin
Compiler
*.js
*.class
*.kt
*.kt
Kotlin 1.4
*.exe
Kotlin
Compiler
Backend
LLVM IR
Kotlin
Compiler
*.kt
Kotlin
Compiler
Kotlin
Compiler
Kotlin
Compiler
*.js
*.class
*.kt
*.kt
LLVM IR
Kotlin 1.5
*.exe
Backend
Frontend
JVM
JS
Linux
IOS
Common
Android
Dependency Management
JVM
JS
Linux
IOS
Common
Android
Dependency Management
JVM
Common-Date-Util-Lib
JVM
JS
Linux
IOS
Common
Android
Dependency Management
Mobile-DB-OR-Mapper-Lib
Android
JVM
JS
Linux
IOS
Common
Android
Dependency Management
Twitter-Rest-API
JS
internal expect fun writeLogMessage(message: String, logLevel: LogLevel)
internal actual fun writeLogMessage(message: String, logLevel: LogLevel) {
println("[$logLevel]: $message")
}
Common
internal actual fun writeLogMessage(message: String, logLevel: LogLevel) {
when (logLevel) {
LogLevel.DEBUG -> console.log(message)
LogLevel.WARN -> console.warn(message)
LogLevel.ERROR -> console.error(message)
}
}
expect
actual
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Multiplatform
Mobile
Kotlin
Multiplatform
Mobile
Kotlin
Multiplatform
Mobile
Kotlin
https://kotlinlang.org/lp/mobile/case-studies/
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
For
Android
For
Desktop
For
Web
Nov 2020
TECHNICAL
PREVIEW
Mai 2021
TECHNICAL
PREVIEW
STABLE
Jul 2021
@Composable
fun App() {
MaterialTheme {
Button(){
Text("Hallo World")
}
}
}
f( )
Data
UI
@Composable
fun App() {
MaterialTheme {
halloButton("Hallo World")
}
}
@Composable
private fun halloButton(text: String) {
Button() {
Text(text)
}
}
f( )
Data
UI
@Composable
fun App() {
MaterialTheme {
halloButton("Hallo World")
}
}
@Composable
private fun halloButton(text: String) {
var textProperty by remember { mutableStateOf(text) }
Button( onClick = { text += " - Live in Peace" }) {
Text(textProperty)
}
}
@Composable
private fun halloButton(text: String) {
Kotlin Compiler
Compose Compiler Plugin
Kotlin JVM
Kotlin Native
Kotlin JS
Desktop
IOS
JAR
APK
Native Exe
Native App
Web
App
Android
Candy Crush Clone
Game Wishlist
IntelliJ Launcher - Win 32 API
HitKlack Spiel - Korge
BETA
STABLE
ALPHA
EXPERIMENTAL
try it only in toy projects
use at your own risk,
expect migration issues
you can use it, we'll do our best to minimize migration issues for you
use it even in most conservative scenarios
Kotlin/JVM
STABLE
kotlin-stdlib (JVM)
STABLE
Kotlin/Native Runtime
BETA
KLib binaries
ALPHA
Kotlin Scripts (*.kts)
BETA
Multiplatform Projects
ALPHA
expect/actual feature
BETA
KMM IDE Plugin
ALPHA
Compiler Plugin API
EXPERIMENTAL
Kotlin/JVM
STABLE
kotlin-stdlib (JVM)
STABLE
Kotlin/Native Runtime
BETA
KLib binaries
ALPHA
Kotlin Scripts (*.kts)
BETA
Multiplatform Projects
ALPHA
expect/actual feature
BETA
Compiler Plugin API
EXPERIMENTAL
KMM IDE Plugin
ALPHA
VeganCountry
MobileRivers
CloudMountains
NativeIsland
FrontendArea
ConfigHills
BackEndGrounds
Kotlin JS Beispiel - Game Wishlist
github.com/TobseF/KotlinJsGameWishlist
Kotlin Native Beispiel - IntelliJ Launcher
github.com/TobseF/IntelliJ-Launcher-n
Multiplatform Beispiel - Hit Klack - Korge
Multiplatform Benchmark
https://android-developers.googleblog.com/2020/08/announcing-jetpack-compose-alpha.html
https://blog.mindorks.com/how-does-the-kotlin-multiplatform-work
https://blog.jetbrains.com/kotlin/2021/02/the-jvm-backend-is-in-beta-let-s-make-it-stable-together/
https://blog.jetbrains.com/kotlin/2020/07/kotlin-native-memory-management-roadmap/