Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KotlinとJavaとnullのライトな話

F46c97bb74758d481531990654933050?s=47 RyotaMurohoshi
November 26, 2016

 KotlinとJavaとnullのライトな話

2016/11/26(土)のKotlin Internal勉強会の資料です

#kotlin_internal

https://connpass.com/event/40360/

F46c97bb74758d481531990654933050?s=128

RyotaMurohoshi

November 26, 2016
Tweet

More Decks by RyotaMurohoshi

Other Decks in Technology

Transcript

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

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

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

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

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

  6. ʰnull͕;ΜͪΌ͔ʱ

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

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

  9. KotlinͷnullΛ͓͞Β͍

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

  11. ͜ΕΛ࢖͏ͱ!(Kotlinͷίʔυ) val str = returnNullableStringKotlin() // ͜Ε΋OK // val str

    : String? = returnNullableStringKotlin() // ͜Ε͸ίϯύΠϧΤϥʔ Type Mismatch // val str : String = returnNullableStringKotlin() // println(str.length) // ίϯύΠϧΤϥʔ println(str?.length) // ͜ΕͳΒOK
  12. ͞Α͏ͳΒnullʂʂʂ

  13. ຊ౰ʹʁ

  14. ݱ࣮͸ͦΜͳʹ؁͘ͳ͍

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

  16. StringΛฦؔ͢਺'(Javaͷίʔυ) public class Utility { public static String returnNullableStringJava() {

    return null; } }
  17. ͜ΕΛ࢖͏ͱ!(JavaͷίʔυΛKotlinͷίʔυ͔ΒݺͿ) val str = Utility.returnNullableStringJava() // ͜Ε΋OK // val str

    : String? = Utility.returnNullableStringJava() // ஫໨ʂʂʂ // ͜Ε΋OKʂʂ ʂ // val str : String = Utility.returnNullableStringJava()
  18. JavaͰॻ͍ͨStringΛฦ͢ϝιουͷฦΓ஋͸ɺ Stringܕʹ΋String?ܕʹ΋୅ೖͰ͖Δ StringͱString?ͬͯҧ͏ܕͩͬͨ͸ͣͳͷʹʁ

  19. ʲ࠶ܝʳ͜ΕΛ࢖͏ͱ!(Kotlinͷίʔυ) val str = returnNullableStringKotlin() // ͜Ε΋OK // val str

    : String? = returnNullableStringKotlin() // ͜Ε͸ίϯύΠϧΤϥʔ Type Mismatch // val str : String = returnNullableStringKotlin() // println(str.length) // ίϯύΠϧΤϥʔ println(str?.length) // ͜ΕͳΒOK
  20. Pla$orm(Type U"lity.returnNullableStringJava()ͷฦΓ஋͸Pla6orm9Type

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

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

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

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

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

    ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ // ͦΕඞཁͳ͍Αͬͯɺܯࠂ͕ग़Δ // println(str?.length)
  26. JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ ܕΛ໌ࣔ͠ͳ͍ͱ val str = Utility.returnNullableStringJava() // ͜Ε΋OK println(str?.length) //

    ͜Ε΋OKʁ(ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍) println(str.length)
  27. ͳΔ΄ͲɺΊͰͨ͠ΊͰͨ͠ʁ

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

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

    return null; } }
  30. ͍ͭ͜nullฦͧ͢ʂ

  31. JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ ܕΛ໌ࣔ͠ͳ͍ͱ val str = Utility.returnNullableStringJava() // ͜Ε΋OK println(str?.length) //

    ίϯύΠϧΤϥʔͰ͸ͳ͍͚ΕͲɺ // ࣮ߦ࣌ʹʮjava.lang.NullPointerExceptionʯ println(str.length)
  32. ͵ΔΆग़Δ͡ΌΜʂ Pla$orm(TypeͰ͸ɺʮNullPointerExcep5onʯͳ͛͏Δ

  33. ΋͏ͻͱͭ

  34. ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹ୅ೖ val str : String = Utility.returnNullableStringJava() println(str.length) //

    ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ // ͦΕඞཁͳ͍Αͬͯɺܯࠂ͕ग़Δ // println(str?.length)
  35. ͩΊͦ͏ U"lity.returnNullableStringJava()͸nullΛฦ͢ ͜ΕΛɺStringܕʹ୅ೖͯ͠ ී௨ʹϝϯόʹΞΫηεͯ͠͠·͍ͬͯΔ

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

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

  38. ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹ୅ೖ val str : String = Utility.returnNullableStringJava() println(str.length) //

    ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ ͜ͷίʔυΛ࣮ߦ͢Δͱ...
  39. java.lang.IllegalStateExcep0on Λ౤͛Δ U"lity.returnNullableStringJava()5must5not5be5null

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

  41. ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹ୅ೖ val str : String = Utility.returnNullableStringJava() println(str.length) //

    ίϯύΠϧΤϥʔʮͰ͸ʯͳ͍͚Ͳ ͜ͷByte%CodeΛΈͯΈΔ IDEAͰɺTools)>)Kotlin)>)Show)Kotlin)Bytecode
  42. 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ʂ
  43. KotlinΛBytecodeʹͯ͠ɺͦΕΛ͞ΒʹDecompile String var10000 = Utility.returnNullableStringJava(); Intrinsics.checkExpressionValueIsNotNull(var10000, "Utility.returnNullableStringJava()"); String str =

    var10000; int var1 = str.length(); System.out.println(var1);
  44. ϙΠϯτ͸ ʮIntrinsics.checkExpressionValueIsNotNullʯ ϝϯόʹΞΫηε͢Δલʹɺ͜Ε͕ݺ͹Ε͍ͯΔʂ

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

  46. 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")); } } /*ུ*/ }
  47. ͳΔ΄Ͳɺ͔֬ʹnullͩͬͨΒIllegalStateExcep.on౤͍͛ͯΔ

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

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

  50. 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

  51. ͳΔ΄Ͳ

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

  53. ͚ͲͳΜͱ͔͍ͨ͠

  54. @NotNull ͱ @Nullable

  55. @NotNull

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

    ""; }
  57. @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
  58. @NotNullͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Bytecode()>(JavaͰίϯύΠϧ String str = Utility.returnStringWithNotNullAnnotation(); int var1 = str.length();

    System.out.println(var1);
  59. @Nullable

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

    ""; }
  61. @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) // ͜Ε͸ίϯύΠϧΤϥʔ
  62. @NullableͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Bytecode()>(JavaͰίϯύΠϧ String str = Utility.returnStringWithNullableAnnotation(); Integer var1 = str

    != null?Integer.valueOf(str.length()):null; System.out.println(var1);
  63. ૬ޓӡ༻લఏͷJavaͷίʔυʹ͸ɺ @Nullabeͱ@NotNullΛ͚ͭΑ͏

  64. Androiderͷํɺ @Nullabeͱ͍͑͹ʁ

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

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

  67. JetBrainsతʹ @Nullabeͱ͍͑͹ʁ

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

  69. ࣮͸ෳ਺ରԠ͍ͯ͠Δ • 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
  70. ࣮͸ෳ਺ରԠ͍ͯ͠Δʢଓ͖ʣ • 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
  71. ͜͜Β΁Μ΋OK

  72. ίʔυΛ௥͍·͠ΐ͏

  73. 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") )
  74. 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
  75. ·ͱΊ • Pla%orm)TypeΛཧղ͠Α͏ • Javaͱͷ૬ޓӡ༻ՕॴͰ͸ɺNullPointetExcep8on΍ IllegalStateExcep8onՄೳੑ͋Γ • JavaͷϥΠϒϥϦʹ͸ɺ@Nullableͱ@NotNull͚ͭΑ͏

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

  77. ͋Γ͕ͱ͏͍͟͝·ͨ͠

  78. ؔ࿈ɾࢀߟ • 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