Slide 1

Slide 1 text

KotlinͱJavaͱnullͷϥΠτͳ࿩ @RyotaMurohoshi 2016/11/26(౔)(Kotlin(internal(ษڧձ

Slide 2

Slide 2 text

͜Μͳ͜ͱ࿩͠·͢ • nullʹ·ͭΘΔKotlinݴޠ࢓༷ͷ֬ೝ • όΠτίʔυͱσίϯύΠϧͨ͠Java͸Ͳ͏ͳΔʁ • ͪΐͬͱ͚ͩίϯύΠϥͷίʔυ΋ݟΔ

Slide 3

Slide 3 text

ࣗݾ঺հ • ࣨ੕྄ଠ(ΉΖ΄͠) • @RyotaMurohoshi • ࢓ࣄͰKotlin+Android • झຯͰC#+UnityͰήʔϜ։ൃ

Slide 4

Slide 4 text

ͱ͜ΖͰɺ࠷ۙ໨ʹͨ͠هࣄͱ͔

Slide 5

Slide 5 text

ʰnull$ͱϓϩάϥϛϯάݴޠʱ

Slide 6

Slide 6 text

ʰnull͕;ΜͪΌ͔ʱ

Slide 7

Slide 7 text

ʰnull͕͋Δϓϩάϥϛϯάݴޠ͸ ͳΜͪΌΒʱ

Slide 8

Slide 8 text

ۤ͠ΜͰΔ͔ΒΈΜͳnullͷ࿩޷͖

Slide 9

Slide 9 text

KotlinͷnullΛ͓͞Β͍

Slide 10

Slide 10 text

String?Λฦؔ͢਺((Kotlinͷίʔυ) fun returnStringNullableKotlin(): String? = null

Slide 11

Slide 11 text

͜ΕΛ࢖͏ͱ!(Kotlinͷίʔυ) val str = returnNullableStringKotlin() // ͜Ε΋OK // val str : String? = returnNullableStringKotlin() // ͜Ε͸ίϯύΠϧΤϥʔ Type Mismatch // val str : String = returnNullableStringKotlin() // println(str.length) // ίϯύΠϧΤϥʔ println(str?.length) // ͜ΕͳΒOK

Slide 12

Slide 12 text

͞Α͏ͳΒnullʂʂʂ

Slide 13

Slide 13 text

ຊ౰ʹʁ

Slide 14

Slide 14 text

ݱ࣮͸ͦΜͳʹ؁͘ͳ͍

Slide 15

Slide 15 text

Kotlin͚ͩͰίʔυΛॻ͖͖ΕΔΘ͚Ͱ͸ͳ͍ ͦ͏ɺJavaͷίʔυΛݺͼग़͞ͳ͍ͱ͍͚ͳ͍ ͦͷ৔߹null͸ɺNullable͸ʁ

Slide 16

Slide 16 text

StringΛฦؔ͢਺'(Javaͷίʔυ) public class Utility { public static String returnNullableStringJava() { return null; } }

Slide 17

Slide 17 text

͜ΕΛ࢖͏ͱ!(JavaͷίʔυΛKotlinͷίʔυ͔ΒݺͿ) val str = Utility.returnNullableStringJava() // ͜Ε΋OK // val str : String? = Utility.returnNullableStringJava() // ஫໨ʂʂʂ // ͜Ε΋OKʂʂ ʂ // val str : String = Utility.returnNullableStringJava()

Slide 18

Slide 18 text

JavaͰॻ͍ͨStringΛฦ͢ϝιουͷฦΓ஋͸ɺ Stringܕʹ΋String?ܕʹ΋୅ೖͰ͖Δ StringͱString?ͬͯҧ͏ܕͩͬͨ͸ͣͳͷʹʁ

Slide 19

Slide 19 text

ʲ࠶ܝʳ͜ΕΛ࢖͏ͱ!(Kotlinͷίʔυ) val str = returnNullableStringKotlin() // ͜Ε΋OK // val str : String? = returnNullableStringKotlin() // ͜Ε͸ίϯύΠϧΤϥʔ Type Mismatch // val str : String = returnNullableStringKotlin() // println(str.length) // ίϯύΠϧΤϥʔ println(str?.length) // ͜ΕͳΒOK

Slide 20

Slide 20 text

Pla$orm(Type U"lity.returnNullableStringJava()ͷฦΓ஋͸Pla6orm9Type

Slide 21

Slide 21 text

• JavaͷࢀরܕͷϝιουͷฦΓ஋ͳͲ͸ɺPla'orm+Typeʹ • IDEͷ্Ͱ͸ɺString!ͱ͔Person!ͱ͔ͬͯද͢ • ͚ͲίʔυͰɺString!ͱ͸ॻ͚ͳ͍

Slide 22

Slide 22 text

ܕΛ໌ࣔతʹॻ͍ͨΒͲ͏ͳΔʁ

Slide 23

Slide 23 text

U"lity.returnNullableStringJava()ͷฦΓ஋ Stringܕʹ୅ೖͨ͠ΒҎޙɺStringܕͱͯ͠ѻ͏͠ String?ܕʹ୅ೖͨ͠ΒҎޙɺString?ܕͱͯ͠ѻ͏

Slide 24

Slide 24 text

JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ String?ʹ୅ೖ val str : String? = Utility.returnNullableStringJava() println(str?.length) // ίϯύΠϧΤϥʔ // println(str.length)

Slide 25

Slide 25 text

JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹ୅ೖ val str : String = Utility.returnNullableStringJava() println(str.length) // ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ // ͦΕඞཁͳ͍Αͬͯɺܯࠂ͕ग़Δ // println(str?.length)

Slide 26

Slide 26 text

JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ ܕΛ໌ࣔ͠ͳ͍ͱ val str = Utility.returnNullableStringJava() // ͜Ε΋OK println(str?.length) // ͜Ε΋OKʁ(ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍) println(str.length)

Slide 27

Slide 27 text

ͳΔ΄ͲɺΊͰͨ͠ΊͰͨ͠ʁ

Slide 28

Slide 28 text

ʹ͸ͳΒͳ͍ ղઆΛޙճ͠ʹͨ͠఺͕ʮ2ͭʯʂ

Slide 29

Slide 29 text

ʲ࠶ܝʳStringΛฦؔ͢਺'(Javaͷίʔυ) public class Utility { public static String returnNullableStringJava() { return null; } }

Slide 30

Slide 30 text

͍ͭ͜nullฦͧ͢ʂ

Slide 31

Slide 31 text

JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ ܕΛ໌ࣔ͠ͳ͍ͱ val str = Utility.returnNullableStringJava() // ͜Ε΋OK println(str?.length) // ίϯύΠϧΤϥʔͰ͸ͳ͍͚ΕͲɺ // ࣮ߦ࣌ʹʮjava.lang.NullPointerExceptionʯ println(str.length)

Slide 32

Slide 32 text

͵ΔΆग़Δ͡ΌΜʂ Pla$orm(TypeͰ͸ɺʮNullPointerExcep5onʯͳ͛͏Δ

Slide 33

Slide 33 text

΋͏ͻͱͭ

Slide 34

Slide 34 text

ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹ୅ೖ val str : String = Utility.returnNullableStringJava() println(str.length) // ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ // ͦΕඞཁͳ͍Αͬͯɺܯࠂ͕ग़Δ // println(str?.length)

Slide 35

Slide 35 text

ͩΊͦ͏ U"lity.returnNullableStringJava()͸nullΛฦ͢ ͜ΕΛɺStringܕʹ୅ೖͯ͠ ී௨ʹϝϯόʹΞΫηεͯ͠͠·͍ͬͯΔ

Slide 36

Slide 36 text

໰୊ɺͲ͏ͳΔʁ • ϝϯόʹΞΫηεͨ͠λΠϛϯάͰNullPointerExcep0on • ͦΕҎ֎ʢԿ͔ͷλΠϛϯάͰͳΜ͔ͷྫ֎Λ౤͛Δʣ

Slide 37

Slide 37 text

ਖ਼ղ͸ɺʰͦΕҎ֎ʱ ϝϯόʹΞΫηε͢Δલʹྫ֎Λ౤͛Δ

Slide 38

Slide 38 text

ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹ୅ೖ val str : String = Utility.returnNullableStringJava() println(str.length) // ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ ͜ͷίʔυΛ࣮ߦ͢Δͱ...

Slide 39

Slide 39 text

java.lang.IllegalStateExcep0on Λ౤͛Δ U"lity.returnNullableStringJava()5must5not5be5null

Slide 40

Slide 40 text

NullPointerExcep/onͰ͸ͳͯ͘IllegalStateExcep/on ͱ͍͏͜ͱ͸ɺίϯύΠϥ͕Կ͔͍ͯ͠Δ͸ͣʂ ݟͯΈΑ͏

Slide 41

Slide 41 text

ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹ୅ೖ val str : String = Utility.returnNullableStringJava() println(str.length) // ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ ͜ͷByte%CodeΛΈͯΈΔ IDEAͰɺTools)>)Kotlin)>)Show)Kotlin)Bytecode

Slide 42

Slide 42 text

L0 LINENUMBER 73 L0 INVOKESTATIC com/muhron/kotlin_java_interpolator/Utility.returnNullableStringJava ()Ljava/lang/String; DUP LDC "Utility.returnNullableStringJava()" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V ASTORE 0 L1 LINENUMBER 74 L1 ALOAD 0 INVOKEVIRTUAL java/lang/String.length ()I ISTORE 1 NOP L2 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ILOAD 1 INVOKEVIRTUAL java/io/PrintStream.println (I)V L3 ͜ΕΛ͞ΒʹDecompoleʂ

Slide 43

Slide 43 text

KotlinΛBytecodeʹͯ͠ɺͦΕΛ͞ΒʹDecompile String var10000 = Utility.returnNullableStringJava(); Intrinsics.checkExpressionValueIsNotNull(var10000, "Utility.returnNullableStringJava()"); String str = var10000; int var1 = str.length(); System.out.println(var1);

Slide 44

Slide 44 text

ϙΠϯτ͸ ʮIntrinsics.checkExpressionValueIsNotNullʯ ϝϯόʹΞΫηε͢Δલʹɺ͜Ε͕ݺ͹Ε͍ͯΔʂ

Slide 45

Slide 45 text

ίʔυΛݟͯΈ·͠ΐ͏ʂ Intrinsics.checkExpressionValueIsNotNull

Slide 46

Slide 46 text

h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/core/run;me.jvm/src/kotlin/jvm/internal/ Intrinsics.java#L86 package kotlin.jvm.internal; @SuppressWarnings("unused") public class Intrinsics { private Intrinsics() { } /*ུ*/ public static void checkExpressionValueIsNotNull(Object value, String expression) { if (value == null) { throw sanitizeStackTrace(new IllegalStateException(expression + " must not be null")); } } /*ུ*/ }

Slide 47

Slide 47 text

ͳΔ΄Ͳɺ͔֬ʹnullͩͬͨΒIllegalStateExcep.on౤͍͛ͯΔ

Slide 48

Slide 48 text

Ͱ͸ɺ͜Ε͸୭͕Αͼ͍ͩͯ͠Δͷ͔ʁ ʮcheckExpressionValueIsNotNullʯͰ୳͢

Slide 49

Slide 49 text

h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/compiler/backend/src/org/jetbrains/kotlin/codegen/ AsmU?l.java#L650 AsmU%lͱ͍͏தͰݺͼग़͍ͯ͠Δʂʂʂ ͞ΒʹಡΈਐΊΔͱ

Slide 50

Slide 50 text

ExpressionCodegen#genQualified h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/compiler/backend/src/org/jetbrains/kotlin/codegen/ ExpressionCodegen.java#L291 ͱ Func%onCodegen#genDelegate h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/compiler/backend/src/org/jetbrains/kotlin/codegen/ Func>onCodegen.java#L1029

Slide 51

Slide 51 text

ͳΔ΄Ͳ

Slide 52

Slide 52 text

ͯ͞ɺKotlinͰίʔυΛॻ͚Δͱݴͬͯ΋ Javaͱͷ૬ޓӡ༻͸ඞਢʂ nullͱͷઓ͍͸ͭͮ͘ͷͰ͋ͬͨ

Slide 53

Slide 53 text

͚ͲͳΜͱ͔͍ͨ͠

Slide 54

Slide 54 text

@NotNull ͱ @Nullable

Slide 55

Slide 55 text

@NotNull

Slide 56

Slide 56 text

Javaͷίʔυ // ΞϊςʔγϣϯΛ͚ͭΔ @NotNull public static String returnStringWithNotNullAnnotation() { return ""; }

Slide 57

Slide 57 text

@NotNullͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ // IDE͸ɺฦΓ஋ܕ͕Stringͬͯڭ͑ͯ͘ΕΔʢString!Ͱ͸ͳ͍ʣ val str = Utility.returnStringWithNotNullAnnotation() // ͜Ε΋OK // val str : String = Utility.returnStringWithNotNullAnnotation() // ࣮͸ɺ͜Ε΋OK //val str : String? = Utility.returnStringWithNotNullAnnotation() println(str?.length) // ܯࠂ͕ͰΔ println(str.length) // ͜Ε͸OK

Slide 58

Slide 58 text

@NotNullͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Bytecode()>(JavaͰίϯύΠϧ String str = Utility.returnStringWithNotNullAnnotation(); int var1 = str.length(); System.out.println(var1);

Slide 59

Slide 59 text

@Nullable

Slide 60

Slide 60 text

Javaͷίʔυ // ΞϊςʔγϣϯΛ͚ͭΔ @Nullable public static String returnStringWithNullableAnnotation() { return ""; }

Slide 61

Slide 61 text

@NullableͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ // IDE͸ɺฦΓ஋ܕ͕String?ͬͯڭ͑ͯ͘ΕΔʢString!Ͱ͸ͳ͍ʣ val str = Utility.returnStringWithNullableAnnotation() // ͜Ε΋OK //val str : String? = Utility.returnNullableStringJava() // ͜Ε͸ίϯύΠϧΤϥʔ //val str : String = Utility.returnStringWithNullableAnnotation() println(str?.length) // ͜Ε͸OK // println(str.length) // ͜Ε͸ίϯύΠϧΤϥʔ

Slide 62

Slide 62 text

@NullableͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Bytecode()>(JavaͰίϯύΠϧ String str = Utility.returnStringWithNullableAnnotation(); Integer var1 = str != null?Integer.valueOf(str.length()):null; System.out.println(var1);

Slide 63

Slide 63 text

૬ޓӡ༻લఏͷJavaͷίʔυʹ͸ɺ @Nullabeͱ@NotNullΛ͚ͭΑ͏

Slide 64

Slide 64 text

Androiderͷํɺ @Nullabeͱ͍͑͹ʁ

Slide 65

Slide 65 text

LombokϢʔβʔͷํɺ @Nullableͱ͍͑͹ʁ

Slide 66

Slide 66 text

FindbugsϢʔβʔͷํɺ @Nullableͱ͍͑͹ʁ

Slide 67

Slide 67 text

JetBrainsతʹ @Nullabeͱ͍͑͹ʁ

Slide 68

Slide 68 text

@NullableΊͬͪΌ͋Δʂʂʂ ͲͷNullableͩΑʂʁ

Slide 69

Slide 69 text

࣮͸ෳ਺ରԠ͍ͯ͠Δ • org.jetbrains.annota.ons.Nullable • android.support.annota.on.Nullable • com.android.annota.ons.Nullable • org.eclipse.jdt.annota.on.Nullable • org.checkerframework.checker.nullness.qual.Nullable h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/ java/JvmAnnota?onNames.kt

Slide 70

Slide 70 text

࣮͸ෳ਺ରԠ͍ͯ͠Δʢଓ͖ʣ • javax.annota*on.Nullable • javax.annota*on.CheckForNull • edu.umd.cs.findbugs.annota*ons.CheckForNull • edu.umd.cs.findbugs.annota*ons.Nullable • edu.umd.cs.findbugs.annota*ons.PossiblyNull h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/ java/JvmAnnota?onNames.kt

Slide 71

Slide 71 text

͜͜Β΁Μ΋OK

Slide 72

Slide 72 text

ίʔυΛ௥͍·͠ΐ͏

Slide 73

Slide 73 text

h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/ java/JvmAnnota?onNames.kt val NULLABLE_ANNOTATIONS = listOf( JvmAnnotationNames.JETBRAINS_NULLABLE_ANNOTATION, FqName("android.support.annotation.Nullable"), FqName("com.android.annotations.Nullable"), FqName("org.eclipse.jdt.annotation.Nullable"), FqName("org.checkerframework.checker.nullness.qual.Nullable"), FqName("javax.annotation.Nullable"), FqName("javax.annotation.CheckForNull"), FqName("edu.umd.cs.findbugs.annotations.CheckForNull"), FqName("edu.umd.cs.findbugs.annotations.Nullable"), FqName("edu.umd.cs.findbugs.annotations.PossiblyNull") )

Slide 74

Slide 74 text

typeQualifiers.ktͷதʹ.... class JavaTypeQualifiers internal constructor( val nullability: NullabilityQualifier?, val mutability: MutabilityQualifier?, internal val isNotNullTypeParameter: Boolean ) { companion object { val NONE = JavaTypeQualifiers(null, null, false) } } ͷnullabilityͷੜ੒ʹ࢖ΘΕ͍ͯΔ h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/ java/typeEnhancement/typeQualifiers.kt#L42

Slide 75

Slide 75 text

·ͱΊ • Pla%orm)TypeΛཧղ͠Α͏ • Javaͱͷ૬ޓӡ༻ՕॴͰ͸ɺNullPointetExcep8on΍ IllegalStateExcep8onՄೳੑ͋Γ • JavaͷϥΠϒϥϦʹ͸ɺ@Nullableͱ@NotNull͚ͭΑ͏

Slide 76

Slide 76 text

NextΞΫγϣϯ ίϯύΠϥ͸ɺJavaTypeQualifiersΛ༻͍ͯ AsmU%l͕Intrinsicsݺͼग़͢ίʔυΛు͍͍ͯΔ ͱࢥΘΕΔͷͰɺௐࠪ

Slide 77

Slide 77 text

͋Γ͕ͱ͏͍͟͝·ͨ͠

Slide 78

Slide 78 text

ؔ࿈ɾࢀߟ • Calling(Java(code(from(Kotlin h5ps:/ /kotlinlang.org/docs/reference/java=interop.html • Kotlin(M9Ͱ௥Ճ͞ΕͨPlaAorm(Typeͷ࿩ h5p:/ /taro.hatenablog.jp/entry/2014/10/16/233702 • ʲίʔυϦʔσΟϯάʳKotlin(to(JavaScriptίϯύΠϥϝϞ h5p:/ /yyyank.blogspot.jp/2015/05/kotlinkotlin=to= javascript.html