Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
KotlinとJavaとnullのライトな話
Search
RyotaMurohoshi
November 26, 2016
Technology
2
1.7k
KotlinとJavaとnullのライトな話
2016/11/26(土)のKotlin Internal勉強会の資料です
#kotlin_internal
https://connpass.com/event/40360/
RyotaMurohoshi
November 26, 2016
Tweet
Share
More Decks by RyotaMurohoshi
See All by RyotaMurohoshi
Tilemapのアップデートについて
ryotamurohoshi
0
49
Unityの合同同人誌や合同商業誌を書いてる僕は感想やレビューや評価が欲しい
ryotamurohoshi
0
560
Unity 2021.1での Unityパッケージの名称変更について
ryotamurohoshi
0
750
Odin Validationはいいぞ!
ryotamurohoshi
2
1k
Tilemapはいいぞ!2020 〜すごいぞ、プロジェクト専用拡張Brush〜
ryotamurohoshi
0
2.4k
Unityでも、新しいC#
ryotamurohoshi
0
1.4k
Riderはいいぞ!
ryotamurohoshi
1
3.6k
Riderのススメ〜俺はRiderここが好き〜
ryotamurohoshi
1
2.5k
Unity開発者に伝えたい.NETのこと
ryotamurohoshi
4
38k
Other Decks in Technology
See All in Technology
ECS組み込みのBlue/Greenデプロイを動かしてELB側の動きを観察してみる
yuki_ink
3
410
重厚長大企業で、顧客価値をスケールさせるためのプロダクトづくりとプロダクト開発チームづくりの裏側 / Developers X Summit 2025
mongolyy
0
180
JJUG CCC 2025 Fall バッチ性能!!劇的ビフォーアフター
hayashiyuu1
1
410
技術広報のOKRで生み出す 開発組織への価値 〜 カンファレンス協賛を通して育む学びの文化 〜 / Creating Value for Development Organisations Through Technical Communications OKRs — Nurturing a Culture of Learning Through Conference Sponsorship —
pauli
5
520
Dev Containers と Skaffold で実現する クラウドネイティブ開発環境 ローカルのみという制約に挑む / Cloud-Native Development with Dev Containers and Skaffold: Tackling the Local-Only Constraint
bitkey
PRO
0
130
現地速報!Microsoft Ignite 2025 M365 Copilotアップデートレポート
kasada
2
1.6k
AI エージェントを評価するための温故知新と Spec Driven Evaluation
icoxfog417
PRO
2
680
新しい風。SolidFlutterで実現するシンプルな状態管理
zozotech
PRO
0
130
クラスタ統合リアーキテクチャ全貌~1,000万ユーザーのウェルネスSaaSを再設計~
hacomono
PRO
0
140
単一Kubernetesクラスタで実現する AI/ML 向けクラウドサービス
pfn
PRO
1
350
TypeScript 6.0で非推奨化されるオプションたち
uhyo
15
4.9k
"'TSのAPI型安全”の対価は誰が払う?不公平なスキーマ駆動に終止符を打つハイブリッド戦略
hal_spidernight
0
120
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Building Applications with DynamoDB
mza
96
6.8k
For a Future-Friendly Web
brad_frost
180
10k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
GitHub's CSS Performance
jonrohan
1032
470k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
Being A Developer After 40
akosma
91
590k
Producing Creativity
orderedlist
PRO
348
40k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.7k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Transcript
KotlinͱJavaͱnullͷϥΠτͳ @RyotaMurohoshi 2016/11/26()(Kotlin(internal(ษڧձ
͜Μͳ͜ͱ͠·͢ • nullʹ·ͭΘΔKotlinݴޠ༷ͷ֬ೝ • όΠτίʔυͱσίϯύΠϧͨ͠JavaͲ͏ͳΔʁ • ͪΐͬͱ͚ͩίϯύΠϥͷίʔυݟΔ
ࣗݾհ • ྄ࣨଠ(ΉΖ΄͠) • @RyotaMurohoshi • ࣄͰKotlin+Android • झຯͰC#+UnityͰήʔϜ։ൃ
ͱ͜ΖͰɺ࠷ۙʹͨ͠هࣄͱ͔
ʰnull$ͱϓϩάϥϛϯάݴޠʱ
ʰnull͕;ΜͪΌ͔ʱ
ʰnull͕͋Δϓϩάϥϛϯάݴޠ ͳΜͪΌΒʱ
ۤ͠ΜͰΔ͔ΒΈΜͳnullͷ͖
KotlinͷnullΛ͓͞Β͍
String?Λฦؔ͢((Kotlinͷίʔυ) fun returnStringNullableKotlin(): String? = null
͜ΕΛ͏ͱ!(Kotlinͷίʔυ) val str = returnNullableStringKotlin() // ͜ΕOK // val str
: String? = returnNullableStringKotlin() // ͜ΕίϯύΠϧΤϥʔ Type Mismatch // val str : String = returnNullableStringKotlin() // println(str.length) // ίϯύΠϧΤϥʔ println(str?.length) // ͜ΕͳΒOK
͞Α͏ͳΒnullʂʂʂ
ຊʹʁ
ݱ࣮ͦΜͳʹ͘ͳ͍
Kotlin͚ͩͰίʔυΛॻ͖͖ΕΔΘ͚Ͱͳ͍ ͦ͏ɺJavaͷίʔυΛݺͼग़͞ͳ͍ͱ͍͚ͳ͍ ͦͷ߹nullɺNullableʁ
StringΛฦؔ͢'(Javaͷίʔυ) public class Utility { public static String returnNullableStringJava() {
return null; } }
͜ΕΛ͏ͱ!(JavaͷίʔυΛKotlinͷίʔυ͔ΒݺͿ) val str = Utility.returnNullableStringJava() // ͜ΕOK // val str
: String? = Utility.returnNullableStringJava() // ʂʂʂ // ͜ΕOKʂʂ ʂ // val str : String = Utility.returnNullableStringJava()
JavaͰॻ͍ͨStringΛฦ͢ϝιουͷฦΓɺ StringܕʹString?ܕʹೖͰ͖Δ StringͱString?ͬͯҧ͏ܕͩͬͨͣͳͷʹʁ
ʲ࠶ܝʳ͜ΕΛ͏ͱ!(Kotlinͷίʔυ) val str = returnNullableStringKotlin() // ͜ΕOK // val str
: String? = returnNullableStringKotlin() // ͜ΕίϯύΠϧΤϥʔ Type Mismatch // val str : String = returnNullableStringKotlin() // println(str.length) // ίϯύΠϧΤϥʔ println(str?.length) // ͜ΕͳΒOK
Pla$orm(Type U"lity.returnNullableStringJava()ͷฦΓPla6orm9Type
• JavaͷࢀরܕͷϝιουͷฦΓͳͲɺPla'orm+Typeʹ • IDEͷ্ͰɺString!ͱ͔Person!ͱ͔ͬͯද͢ • ͚ͲίʔυͰɺString!ͱॻ͚ͳ͍
ܕΛ໌ࣔతʹॻ͍ͨΒͲ͏ͳΔʁ
U"lity.returnNullableStringJava()ͷฦΓ Stringܕʹೖͨ͠ΒҎޙɺStringܕͱͯ͠ѻ͏͠ String?ܕʹೖͨ͠ΒҎޙɺString?ܕͱͯ͠ѻ͏
JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ String?ʹೖ val str : String? = Utility.returnNullableStringJava() println(str?.length) //
ίϯύΠϧΤϥʔ // println(str.length)
JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹೖ val str : String = Utility.returnNullableStringJava() println(str.length) //
ίϯύΠϧΤϥʔʮͰʯͳ͍͚Ͳ // ͦΕඞཁͳ͍Αͬͯɺܯࠂ͕ग़Δ // println(str?.length)
JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ ܕΛ໌ࣔ͠ͳ͍ͱ val str = Utility.returnNullableStringJava() // ͜ΕOK println(str?.length) //
͜ΕOKʁ(ίϯύΠϧΤϥʔʮͰʯͳ͍) println(str.length)
ͳΔ΄ͲɺΊͰͨ͠ΊͰͨ͠ʁ
ʹͳΒͳ͍ ղઆΛޙճ͠ʹ͕ͨ͠ʮ2ͭʯʂ
ʲ࠶ܝʳStringΛฦؔ͢'(Javaͷίʔυ) public class Utility { public static String returnNullableStringJava() {
return null; } }
͍ͭ͜nullฦͧ͢ʂ
JavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ ܕΛ໌ࣔ͠ͳ͍ͱ val str = Utility.returnNullableStringJava() // ͜ΕOK println(str?.length) //
ίϯύΠϧΤϥʔͰͳ͍͚ΕͲɺ // ࣮ߦ࣌ʹʮjava.lang.NullPointerExceptionʯ println(str.length)
͵ΔΆग़Δ͡ΌΜʂ Pla$orm(TypeͰɺʮNullPointerExcep5onʯͳ͛͏Δ
͏ͻͱͭ
ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹೖ val str : String = Utility.returnNullableStringJava() println(str.length) //
ίϯύΠϧΤϥʔʮͰʯͳ͍͚Ͳ // ͦΕඞཁͳ͍Αͬͯɺܯࠂ͕ग़Δ // println(str?.length)
ͩΊͦ͏ U"lity.returnNullableStringJava()nullΛฦ͢ ͜ΕΛɺStringܕʹೖͯ͠ ී௨ʹϝϯόʹΞΫηεͯ͠͠·͍ͬͯΔ
ɺͲ͏ͳΔʁ • ϝϯόʹΞΫηεͨ͠λΠϛϯάͰNullPointerExcep0on • ͦΕҎ֎ʢԿ͔ͷλΠϛϯάͰͳΜ͔ͷྫ֎Λ͛Δʣ
ਖ਼ղɺʰͦΕҎ֎ʱ ϝϯόʹΞΫηε͢Δલʹྫ֎Λ͛Δ
ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹೖ val str : String = Utility.returnNullableStringJava() println(str.length) //
ίϯύΠϧΤϥʔʮͰʯͳ͍͚Ͳ ͜ͷίʔυΛ࣮ߦ͢Δͱ...
java.lang.IllegalStateExcep0on Λ͛Δ U"lity.returnNullableStringJava()5must5not5be5null
NullPointerExcep/onͰͳͯ͘IllegalStateExcep/on ͱ͍͏͜ͱɺίϯύΠϥ͕Կ͔͍ͯ͠Δͣʂ ݟͯΈΑ͏
ʲ࠶ܝʳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Stringʹೖ val str : String = Utility.returnNullableStringJava() println(str.length) //
ίϯύΠϧΤϥʔʮͰʯͳ͍͚Ͳ ͜ͷByte%CodeΛΈͯΈΔ IDEAͰɺTools)>)Kotlin)>)Show)Kotlin)Bytecode
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ʂ
KotlinΛBytecodeʹͯ͠ɺͦΕΛ͞ΒʹDecompile String var10000 = Utility.returnNullableStringJava(); Intrinsics.checkExpressionValueIsNotNull(var10000, "Utility.returnNullableStringJava()"); String str =
var10000; int var1 = str.length(); System.out.println(var1);
ϙΠϯτ ʮIntrinsics.checkExpressionValueIsNotNullʯ ϝϯόʹΞΫηε͢Δલʹɺ͜Ε͕ݺΕ͍ͯΔʂ
ίʔυΛݟͯΈ·͠ΐ͏ʂ Intrinsics.checkExpressionValueIsNotNull
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")); } } /*ུ*/ }
ͳΔ΄Ͳɺ͔֬ʹnullͩͬͨΒIllegalStateExcep.on͍͛ͯΔ
Ͱɺ͜Ε୭͕Αͼ͍ͩͯ͠Δͷ͔ʁ ʮcheckExpressionValueIsNotNullʯͰ୳͢
h"ps:/ /github.com/JetBrains/kotlin/blob/1.0.5/compiler/backend/src/org/jetbrains/kotlin/codegen/ AsmU?l.java#L650 AsmU%lͱ͍͏தͰݺͼग़͍ͯ͠Δʂʂʂ ͞ΒʹಡΈਐΊΔͱ
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
ͳΔ΄Ͳ
ͯ͞ɺKotlinͰίʔυΛॻ͚Δͱݴͬͯ Javaͱͷ૬ޓӡ༻ඞਢʂ nullͱͷઓ͍ͭͮ͘ͷͰ͋ͬͨ
͚ͲͳΜͱ͔͍ͨ͠
@NotNull ͱ @Nullable
@NotNull
Javaͷίʔυ // ΞϊςʔγϣϯΛ͚ͭΔ @NotNull public static String returnStringWithNotNullAnnotation() { return
""; }
@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
@NotNullͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Bytecode()>(JavaͰίϯύΠϧ String str = Utility.returnStringWithNotNullAnnotation(); int var1 = str.length();
System.out.println(var1);
@Nullable
Javaͷίʔυ // ΞϊςʔγϣϯΛ͚ͭΔ @Nullable public static String returnStringWithNullableAnnotation() { return
""; }
@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) // ͜ΕίϯύΠϧΤϥʔ
@NullableͳJavaͷίʔυΛKotlinͷίʔυ͔ΒݺΜͰ Bytecode()>(JavaͰίϯύΠϧ String str = Utility.returnStringWithNullableAnnotation(); Integer var1 = str
!= null?Integer.valueOf(str.length()):null; System.out.println(var1);
૬ޓӡ༻લఏͷJavaͷίʔυʹɺ @Nullabeͱ@NotNullΛ͚ͭΑ͏
Androiderͷํɺ @Nullabeͱ͍͑ʁ
LombokϢʔβʔͷํɺ @Nullableͱ͍͑ʁ
FindbugsϢʔβʔͷํɺ @Nullableͱ͍͑ʁ
JetBrainsతʹ @Nullabeͱ͍͑ʁ
@NullableΊͬͪΌ͋Δʂʂʂ ͲͷNullableͩΑʂʁ
࣮ෳରԠ͍ͯ͠Δ • 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
࣮ෳରԠ͍ͯ͠Δʢଓ͖ʣ • 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
͜͜ΒΜOK
ίʔυΛ͍·͠ΐ͏
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") )
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
·ͱΊ • Pla%orm)TypeΛཧղ͠Α͏ • Javaͱͷ૬ޓӡ༻ՕॴͰɺNullPointetExcep8on IllegalStateExcep8onՄೳੑ͋Γ • JavaͷϥΠϒϥϦʹɺ@Nullableͱ@NotNull͚ͭΑ͏
NextΞΫγϣϯ ίϯύΠϥɺJavaTypeQualifiersΛ༻͍ͯ AsmU%l͕Intrinsicsݺͼग़͢ίʔυΛు͍͍ͯΔ ͱࢥΘΕΔͷͰɺௐࠪ
͋Γ͕ͱ͏͍͟͝·ͨ͠
ؔ࿈ɾࢀߟ • 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