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
Unityの合同同人誌や合同商業誌を書いてる僕は感想やレビューや評価が欲しい
ryotamurohoshi
0
530
Unity 2021.1での Unityパッケージの名称変更について
ryotamurohoshi
0
710
Odin Validationはいいぞ!
ryotamurohoshi
2
960
Tilemapはいいぞ!2020 〜すごいぞ、プロジェクト専用拡張Brush〜
ryotamurohoshi
0
2.4k
Unityでも、新しいC#
ryotamurohoshi
0
1.3k
Riderはいいぞ!
ryotamurohoshi
1
3.5k
Riderのススメ〜俺はRiderここが好き〜
ryotamurohoshi
1
2.4k
Unity開発者に伝えたい.NETのこと
ryotamurohoshi
4
37k
ImportedLinqのススメ
ryotamurohoshi
0
1.4k
Other Decks in Technology
See All in Technology
Claude Code Actionを使ったコード品質改善の取り組み
potix2
PRO
6
2.6k
怖くない!はじめてのClaude Code
shinya337
0
300
生成AI活用の組織格差を解消する 〜ビジネス職のCursor導入が開発効率に与えた好循環〜 / Closing the Organizational Gap in AI Adoption
upamune
5
4.6k
Amazon S3標準/ S3 Tables/S3 Express One Zoneを使ったログ分析
shigeruoda
5
590
LangSmith×Webhook連携で実現するプロンプトドリブンCI/CD
sergicalsix
1
150
使いたいMCPサーバーはWeb APIをラップして自分で作る #QiitaBash
bengo4com
0
1.3k
SpringBoot x TestContainerで実現するポータブル自動結合テスト
demaecan
0
120
高速なプロダクト開発を実現、創業期から掲げるエンタープライズアーキテクチャ
kawauso
1
250
Tokyo_reInforce_2025_recap_iam_access_analyzer
hiashisan
0
140
2025-06-26_Lightning_Talk_for_Lightning_Talks
_hashimo2
2
110
ビギナーであり続ける/beginning
ikuodanaka
2
250
ドメイン特化なCLIPモデルとデータセットの紹介
tattaka
1
470
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
42
2.7k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
24k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Six Lessons from altMBA
skipperchong
28
3.9k
For a Future-Friendly Web
brad_frost
179
9.8k
The Cost Of JavaScript in 2023
addyosmani
51
8.5k
Writing Fast Ruby
sferik
628
62k
Practical Orchestrator
shlominoach
188
11k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
5.9k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
The World Runs on Bad Software
bkeepers
PRO
69
11k
Building an army of robots
kneath
306
45k
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