51
Kotlin is charming; The reasons Java engineers should start Kotlin. By Kiyotaka Soranaka:空中清高

Kotlin is charming; The reasons Java engineers should start Kotlin

Embed Size (px)

Citation preview

Kotlin is charming;

The reasons Java engineers

should start Kotlin.

By Kiyotaka Soranaka:空中清高

About me

Name:空中清高(Kiyotaka Soranaka)Work:株式会社ジャストシステム

株式会社ジャストシステム

創業38年、売上182億、平均年収900万円

Javaのプロダクト採用は1.0から。一太郎Ark:1996年開発着手。

JUST.SYSTEMS

いろんなwebサービスをJavaで作ってます。

などなど...

株式会社ジャストシステムJUST.SYSTEMS

Agenda

・What is Kotlin?・Why Kotlin?・Kotlin VS Java・Kotlin AND Java

What is Kotlin?

Statically typed programming language

for the JVM, Android and the browser

https://kotlinlang.org/

Google is adding Kotlin as an official

programming language for Android

development

https://android-developers.googleblog.com/2017/05/android-announces-support-for-kotlin.html

Why Kotlin?

ConciseSafeVersatileInteroperableTooling

https://kotlinlang.org/

ConciseSafeVersatileInteroperableTooling

// Create a POJO in a single line

data class Person(val name: String, val age: Int)

// No need "new" keyword and Semicolons are optional.

val person = Person("Kiyotaka Soranaka", 29)

// String Templates

println("My name is ${person.name}.")

// > My name is Kiyotaka Soranaka.

Concise

ConciseSafeVersatileInteroperableTooling

// Null Safe: These codes cause error at compile time.

val str: String = null // compile error:String is non-null.

val nullable: String? = null // String? is nullable.

val length:Int = nullable.length // compile error:String? is nullable.

// Below codes don't cause error.

val length:Int = nullable!!.length // But this cause error at runtime if ‘nullable’ is null.

val length:Int = if (nullable != null) { nullable.length } else { 0 } // Smart-cast

val length:Int = nullable?.length ?: 0 // "?." is Safe Calls and "?:" is Elvis Operator.

Safe

ConciseSafeVersatileInteroperableTooling

Versatile

・Android Development.

・Write code in Kotlin and target JavaScript.

・Application Server.

・Spring Framework support Kotlin.

・Enterprise Java EE.

ConciseSafeVersatileInteroperableTooling

Interoperable

Kotlin is of 100% Java compatibility.

You can use any existing library on the JVM.

ConciseSafeVersatileInteroperableTooling

Tooling

IntelliJ IDEA is very powerful!

It is developed by JetBrains, where the team

that created Kotlin itself belongs.

Tooling

(Win)Alt + Enter, (Mac) ⌥Enter

Tooling

(Win)Ctrl + Alt + Shift + K

(Mac) ⌥⇧⌘K

Convert Java to Kotlin.

Kotlin VS Java

public final class Person {

public Person(String name, int age) {

this.name = name;

this.age = age;

}

private final String name;

private int age;

public String getName() { return name; }

public int getAge() { return age; }

public void setAge(int age) {

this.age = age;

}

}

Kotlin JavaKotlin VS Java

class Person(name: String, age: Int) {

val name: String = name

var age: Int = age

}

'val' and 'var' mean read-only and

mutable, respectively.

getter/setter are automatically

generated.

public final class Person {

public Person(String name, int age) {

this.name = name;

this.age = age;

}

private final String name;

private int age;

public String getName() { return name; }

public int getAge() { return age; }

public void setAge(int age) {

this.age = age;

}

}

Kotlin: Level 1 JavaKotlin VS Java

Kotlin: Level 2 JavaKotlin VS Java

class Person(val name: String,

var age: Int)

Properties are automatically generated.

public final class Person {

public Person(String name, int age) {

this.name = name;

this.age = age;

}

private final String name;

private int age;

public String getName() { return name; }

public int getAge() { return age; }

public void setAge(int age) {

this.age = age;

}

}

Kotlin: Level 3 JavaKotlin VS Java

data class Person(val name: String,

var age: Int)

Several members are automatically

generated; e.g.,

getter/setter, equals(), hashCode(),

toString(), copy(), etc..

val person = Person("Bob", 5)

println("$person")

// > Person(name=Bob, age=5)

https://kotlinlang.org/docs/reference/dat

a-classes.html

public final class Person {

public Person(String name, int age) {

this.name = name;

this.age = age;

}

private final String name;

private int age;

public String getName() { return name; }

public int getAge() { return age; }

public void setAge(int age) {

this.age = age;

}

@Override

public boolean equals(Object obj) {

...

Kotlin JavaKotlin VS Java

data class Person(val name: String = "",

var age: Int = 0)

You can use default values.

'Telescoping' is not needed.

'Telescoping' is as follows.

public Person() {

this("");

}

public Person(String name) {

this(name, 0);

}

public Person(String name, int age) {

this.name = name;

this.age = age;

}

Kotlin JavaKotlin VS Java

data class Person(var height: Int = 155,

var weight: Int = 50)

By using 'Named Arguments',

you don't have to care the order of the

arguments.

val p1 = Person(height = 170, weight = 60)

val p2= Person(weight = 60, height = 170)

val p3= Person(height = 170)

val p4= Person(weight = 60)

https://kotlinlang.org/docs/reference/fun

ctions.html

public Person() {

this(155);

}

public Person(int height) {

this(height, 50);

}

public Person(int height, int weight) {

this.height = height;// cm

this.weight = weight;// kg

}

Person p1 = new Person(170, 60);

Person p2 = new Person(60, 170);

Kotlin: Level 1 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

var jjugCal = cache["JJUG"]

if (jjugCal == null) {

jjugCal = Calendar.getInstance()

jjugCal.set(2017, Calendar.MAY, 20)

cache.put("JJUG", jjugCal)

}

return jjugCal!!.time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

Kotlin: Level 1 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

var jjugCal = cache["JJUG"]

if (jjugCal == null) {

jjugCal = Calendar.getInstance()

jjugCal.set(2017, Calendar.MAY, 20)

cache.put("JJUG", jjugCal)

}

return jjugCal!!.time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

This code almost the same as Java.

But you can modify more concise.

Kotlin: Level 1 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

var jjugCal = cache["JJUG"]

if (jjugCal == null) {

jjugCal = Calendar.getInstance()

jjugCal.set(2017, Calendar.MAY, 20)

cache.put("JJUG", jjugCal)

}

return jjugCal!!.time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

To be more concise.

・Simplify the code to initialize the calendar.

・Change the type of "jjugCal" to read-only Calendar.

Kotlin: Level 2 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

val jjugCal = cache["JJUG"] ?:

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

cache.put("JJUG", this)

}

return jjugCal.time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

Kotlin: Level 2 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

val jjugCal = cache["JJUG"] ?:

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

cache.put("JJUG", this)

}

return jjugCal.time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

Use "?:"(Elvis Operator).

Use "apply"(scoping function).

Type of "jjugCal" is read-only Calendar.

Kotlin: Level 2 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

val jjugCal = cache["JJUG"] ?:

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

cache.put("JJUG", this)

}

return jjugCal.time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

To be more concise.

・Delete local variable "jjugCal".

・Use kotlin stdlib function.

Kotlin: Level 3 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

return cache.getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

Kotlin: Level 3 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

return cache.getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

Use kotlin.stdlib function.

Delete the local variable "jjugCal".

Kotlin: Level 3 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate(): Date {

return cache.getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

To be more concise.

・"return" and return type is optional.

Kotlin: Level 4 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate() =

cache .getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

Kotlin: Level 4 JavaKotlin VS Java

val cache = HashMap<String, Calendar>()

fun getJJUGDate() =

cache .getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

Map<String, Calendar> cache = new

HashMap<>();

public Date getJJUGDate() {

Calendar jjugCal = cache.get("JJUG");

if (jjugCal == null) {

jjugCal = Calendar.getInstance();

jjugCal.set(2017, Calendar.MAY, 20);

cache.put("JJUG", jjugCal);

}

return jjugCal.getTime();

}

"return" is omitted.

Kotlin AND Java

Kotlin JavaKotlin AND Java

package example.kotlin

Import example.java.Person

fun example() {

val p = Person("Bob", 5)

p.age = p.age + 1

}

package example.java;

public class Person {

public Person(String name, int age) {

this.name = name;

this.age = age;

}

private final String name;

private int age;

public String getName() { return name; }

public int getAge() { return age; }

public void setAge(int age) {

this.age = age;

}

}

Kotlin JavaKotlin AND Java

You can use any existing library on JVM.

Jackson, for example,

data class Data(val id:Int = 0,

val name:String = "")

val mapper = ObjectMapper()

val data = Data(10, "Soranaka")

val json = mapper

.writeValueAsString(data)

println(json)

// > {"id":10,"name":"Soranaka"}

val data2 = mapper

.readValue(json, Data::class.java)

println(data2)

// > Data(id=10, name=Soranaka)

Kotlin JavaKotlin AND Java

data class Data(val id:Int,var name:String) Data data = new Data(10, "J");

data.setName(data.getName() + "JUG");

System.out.println(data);

// > Data(id=10, name=JJUG)

Kotlin JavaKotlin AND Java

class KotlinUtil {

val cache =

HashMap<String, Calendar>()

fun getJJUGDate() =

cache .getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

KotlinUtil kotlinUtil = new KotlinUtil();

Date jjugDate = kotlinUtil.getJJUGDate();

Kotlin JavaKotlin AND Java

class KotlinUtil {

val cache =

HashMap<String, Calendar>()

fun getJJUGDate() =

cache .getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

KotlinUtil kotlinUtil = new KotlinUtil();

Date jjugDate = kotlinUtil.getJJUGDate();

Do you want it to be singleton?

Kotlin JavaKotlin AND Java

object KotlinUtil {

val cache =

HashMap<String, Calendar>()

fun getJJUGDate() =

cache .getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

Date jjugDate =

KotlinUtil.INSTANCE.getJJUGDate();

Kotlin JavaKotlin AND Java

object KotlinUtil {

val cache =

HashMap<String, Calendar>()

fun getJJUGDate() =

cache .getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

Date jjugDate =

KotlinUtil.INSTANCE.getJJUGDate();

Do you want it to be static?

Kotlin JavaKotlin AND Java

class KotlinUtil {

companion object {

private val cache =

HashMap<String, Calendar>()

@JvmStatic

fun getJJUGDate() =

cache.getOrPut("JJUG", {

Calendar.getInstance().apply {

set(2017, Calendar.MAY, 20)

}

}).time

}

}

Date jjugDate = KotlinUtil.getJJUGDate();

株式会社ジャストシステム

Kotlinを使える仕事に興味を持った方ぜひ、一緒に働きましょう!

JUST.SYSTEMS

Thank you

Kiyotaka Soranaka:空中清高@soranakk