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

JavaからKotlinへの移行(プラットフォーム型) #Kotlin_Sansan

JavaからKotlinへの移行(プラットフォーム型) #Kotlin_Sansan

第6回 Kotlin勉強会@Sansan( https://sansan.connpass.com/event/57683/ )で使用したスライドです。

14c9795d267f5b85abb98ca5e8780646?s=128

Taro Nagasawa

June 29, 2017
Tweet

Transcript

  1. JavaからKotlinへの移行 -KotlinからJavaを使う: プラットフォーム型編- 2017-06-29 Kotlin勉強会@Sansan 長澤太郎 @ngsw_taro

  2. 6月15日 第1回 CA.kt

  3. JavaからKotlinへの移行 -JavaからKotlinが呼び出される編- • Kotlinにはstaticという概念がない ◦ @JvmStaticや@JvmFieldを上手く使う • FWのためだけに毎回openするのが面倒 ◦ Springならkotlin-springコンパイラプラグインを使う

    ◦ all-openコンパイラプラグインを使う • デフォルトコンストラクタを提供したくない ◦ no-argコンパイラプラグインを使う
  4. KotlinからJavaを使う: プラットフォーム型編

  5. 自己紹介 • 長澤 太郎(たろーって呼んでね) • @ngsw_taro • エムスリー株式会社でエンジニアやってます • Kotlinエバンジェリスト(JetBrains黙認)

    • 日本Kotlinユーザグループ代表 • 「Kotlinスタートブック」の著者
  6. Null安全 • nullの可能性のあるものと、そうでないものを厳格に区別する ことでケアレスミスを防ぐ val a: Int = null //

    コンパイルエラー val b: Int? = null // OK b.toString() // コンパイルエラー if (b != null) b.toString() // OK b?.toString() // OK
  7. Java(の参照型)は常にnullの可能性がある // Java Optional<String> nullは返さないよ() { return null; }

  8. Javaコードの呼び出し結果はハテナだらけ? val foo: File = File("/") val bar: File? =

    foo.absoluteFile val baz: File? = foo.parentFile
  9. Javaコードの呼び出し結果はハテナだらけ? val foo: File = File("/") val bar: File? =

    foo.absoluteFile val baz: File? = foo.parentFile コンストラクタの 戻り値はNotNull getXxx()メソッドは xxxプロパティのように
  10. Javaコードの呼び出し結果はハテナだらけ? val foo: File = File("/") val bar: File? =

    foo.absoluteFile val baz: File? = foo.parentFile 常にnullを返さないメソッドもあ るのに面倒だな
  11. ハテナだらけだったら まだ「めんどくさい」で 済んだ...!

  12. プラットフォーム型 • nullかもしれないし、nullじゃないかもしれない型 • 受ける型を省略することで、プラットフォーム型を維持 • 例えば「File!」として表記される val baz =

    foo.parentFile baz.exists() //=> ぬるぽ
  13. プラットフォーム型 • nullかもしれないし、nullじゃないかもしれない型 • 受ける型を省略することで、プラットフォーム型を維持 • 例えば「File!」として表記される val baz =

    foo.parentFile baz.exists() //=> ぬるぽ File!が返される 型を省略しているので File!のまま 危険な操作であるにも関わらず普通に メンバアクセス可能 (上手く行くこともあるが、今回はぬるぽ)
  14. ifでnullチェックして回避 val baz = foo.parentFile if (baz != null) baz.exists()

    else false
  15. ifでnullチェックして回避 val baz = foo.parentFile if (baz != null) baz.exists()

    else false Javaと 変わらん!! ※プラットフォーム型 + nullチェックはJavaと同じだが、 Nullable + nullチェックはJavaよりも安全。nullチェックを 否定したいわけではないことに注意。
  16. 安全呼び出しで回避 val baz = foo.parentFile baz?.exists() まぁ安全

  17. だったらNullableとして明示すりゃあいい val baz: File? = foo.parentFile // あとはご自由に • とにかく安全!

    • プラットフォーム型の存在意義とは • 結局ハテナだらけで面倒問題に戻る →注意深くコーディングして、うっかり死ぬよりマシ
  18. NotNullとして明示すると...? val baz: File = foo.parentFile // 上手くいけば、あとはご自由に

  19. NotNullとして明示すると...? val baz: File = foo.parentFile // 上手くいけば、あとはご自由に nullでない参照が返されればOK。 以後、NotNullとして扱える

  20. NotNullとして明示すると...? val baz: File = foo.parentFile // 上手くいけば、あとはご自由に nullでない参照が返されればOK。 以後、NotNullとして扱える

    nullが返されるとクラッシュ! IllegalArgumentException
  21. 結論: プラットフォーム型は厄介 • プラットフォーム型のまま扱うということはJavaの世界と同じ で、いつNPEが起きてもおかしくない状況 • Javaコードがnullを返す可能性があるのかどうか自信が持 てない場合は、Nullableを明示するのが無難! • Javaコードがnullを返さないことに自信がある場合には、

    NotNullを明示する。なぜなら、それがnullだった場合に早 期に発見できるから。
  22. Java側でNullable/NotNullを表明する • JSR-305: @Nullable, @Nonnull • JetBrains: @Nullable, @NotNull •

    Android Support: @Nullable, @NonNull // Java class Hoge { @Nonnull static Hoge newInstance() {...} } // Kotlin val hoge = Hoge.newInstance() hoge.doSomething() NotNullとして見える