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.6k
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
Unityの合同同人誌や合同商業誌を書いてる僕は感想やレビューや評価が欲しい
ryotamurohoshi
0
480
Unity 2021.1での Unityパッケージの名称変更について
ryotamurohoshi
0
660
Odin Validationはいいぞ!
ryotamurohoshi
2
900
Tilemapはいいぞ!2020 〜すごいぞ、プロジェクト専用拡張Brush〜
ryotamurohoshi
0
2.3k
Unityでも、新しいC#
ryotamurohoshi
0
1.2k
Riderはいいぞ!
ryotamurohoshi
1
3.4k
Riderのススメ〜俺はRiderここが好き〜
ryotamurohoshi
1
2.3k
Unity開発者に伝えたい.NETのこと
ryotamurohoshi
4
37k
ImportedLinqのススメ
ryotamurohoshi
0
1.3k
Other Decks in Technology
See All in Technology
モノレポ開発のエラー、誰が見る?Datadog で実現する適切なトリアージとエスカレーション
biwashi
6
790
RSNA2024振り返り
nanachi
0
530
インフラをつくるとはどういうことなのか、 あるいはPlatform Engineeringについて
nwiizo
5
2.4k
「海外登壇」という 選択肢を与えるために 〜Gophers EX
logica0419
0
640
管理者しか知らないOutlookの裏側のAIを覗く#AzureTravelers
hirotomotaguchi
2
320
Platform Engineeringは自由のめまい
nwiizo
4
2k
なぜ私は自分が使わないサービスを作るのか? / Why would I create a service that I would not use?
aiandrox
0
510
ユーザーストーリーマッピングから始めるアジャイルチームと並走するQA / Starting QA with User Story Mapping
katawara
0
170
7日間でハッキングをはじめる本をはじめてみませんか?_ITエンジニア本大賞2025
nomizone
2
1.7k
OpenID BizDay#17 KYC WG活動報告(法人) / 20250219-BizDay17-KYC-legalidentity
oidfj
0
140
5分で紹介する生成AIエージェントとAmazon Bedrock Agents / 5-minutes introduction to generative AI agents and Amazon Bedrock Agents
hideakiaoyagi
0
230
2024.02.19 W&B AIエージェントLT会 / AIエージェントが業務を代行するための計画と実行 / Algomatic 宮脇
smiyawaki0820
10
1.5k
Featured
See All Featured
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
6
550
Facilitating Awesome Meetings
lara
51
6.2k
Adopting Sorbet at Scale
ufuk
74
9.2k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
366
25k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7.1k
What's in a price? How to price your products and services
michaelherold
244
12k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.4k
Designing on Purpose - Digital PM Summit 2013
jponch
117
7.1k
Docker and Python
trallard
44
3.3k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.3k
Rails Girls Zürich Keynote
gr2m
94
13k
How GitHub (no longer) Works
holman
313
140k
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