| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

Kotlin

提供: MyMemoWiki
2021年11月27日 (土) 14:47時点におけるPiroto (トーク | 投稿記録)による版
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

Kotlin

Install

Command Line

SDKMAN

  1. $ curl -s https://get.sdkman.io | bash
  • ターミナルを開き直し
  1. $ sdk install kotlin
  • 確認
  1. $ kotolinc -help

REPL

  1. $kotlinc-jvm

IDE

Intellij IDEA

基本

コンパイルと実行

  • コンパイル
  1. $ kotlinc sample.kt
  • 実行
  1. $ kotlin sample.SampleKt

データ型

数値型

Double
Float
Long
Int
Short
Byte

パッケージと関数

  1. // ソースファイルの先頭に記述
  2. // ディレクトリ構造と一致する必要はない。
  3. package sample
  4.  
  5. // 2つのInt引数と戻り値Intをもつ
  6. fun sum(a: Int, b: Int): Int {
  7. return a + b
  8. }
  9.  
  10. // 式を持ち、戻り値を推測
  11. fun sum2(a: Int, b: Int) = a + b
  12.  
  13. // 意味のある値を返さない場合、Unitを使用
  14. fun printSum(a: Int, b: Int): Unit {
  15. println("$a + $b = ${a + b}")
  16. }
  17.  
  18. // Unit は省略可能
  19. fun printSum2(a: Int, b: Int) {
  20. println("$a + $b = ${a + b}")
  21. }
  22.  
  23. fun main(args: Array<String>) {
  24. println(sum(1,2))
  25. println(sum2(3,4))
  26. printSum(5,6)
  27. printSum(7,8)
  28. }
実行
  1. PS> kotlinc Test01.kt
  2. PS> kotlin sample.Test01Kt
  3. 3
  4. 7
  5. 5 + 6 = 11
  6. 7 + 8 = 15

ローカル変数

  1. package sample
  2.  
  3. fun main(args: Array<String>) {
  4. // val:読み取り専用
  5. val a: Int = 1 // 即時割り当て
  6. val b = 2 // Int型を推測
  7. val c: Int // 即時初期化しない場合、型は必須
  8. c = 3
  9. // c = 4 // error: val cannot be reassigned
  10.  
  11. // var:変更可能
  12. var d = 5
  13. d += 1
  14.  
  15. println("$a,$b,$c,$d")
  16. }

文字列テンプレート

  1. package sample
  2.  
  3. fun main(args: Array<String>) {
  4. // 文字列はテンプレート式を含むことができる
  5. // テンプレート式は、$で始める
  6. val a = 10
  7. println("a is $a")
  8.  
  9. // 中括弧で任意の式を表現
  10. val s = "abc"
  11. println("$s.length is ${s.length}")
  12.  
  13. // テンプレートは、raw文字列、エスケープされた文字列もサポートする
  14. // $リテラルを表示するのに、バックスラッシュエスケープは機能しない(以下参照)
  15. val l = """
  16. ${'$'}123
  17. """
  18. print(l)
  19. }
実行
  1. PS> kotlin sample.Test03Kt
  2. a is 10
  3. abc.length is 3
  4.  
  5. $123
  6.  

条件式

  • 三項演算子はないが、ifを式として利用できる
  1. package sample
  2.  
  3. fun maxOf(a: Int, b: Int): Int {
  4. if (a > b) {
  5. return a
  6. } else {
  7. return b
  8. }
  9. }
  10.  
  11. // if を式として利用
  12. fun maxOfExpression(a: Int, b: Int) = if (a > b) a else b
  13.  
  14. fun main(args: Array<String>) {
  15. println(maxOf(3,5))
  16. println(maxOfExpression(6,8))
  17. }
実行
  1. PS> kotlin sample.Test04Kt
  2. 5
  3. 8

nulableとnullチェック

<blockquote>ターミナルで、kotlinc とタイプすると、REPLが起動する。終了には、:quit</blockquote>

  • 参照は、nullが設定可能な場合、明示的に nullableとマークする必要がある
  1. >>> var a: Int? =null
  2. >>> a
  3. null
  • マークしないとエラー
  1. >>> var a: Int = null
  2. error: null can not be a value of a non-null type Int
  3. var a: Int = null

安全呼び出し

  • ?.を使うと、オブジェクトがnullの場合、nullを返し、そうでない場合メソッドを呼び出す
  1. var foo:Foo? = bar?.getInstance()

エルビス演算子

  • ?: を使用すると、オブジェクトがnullの場合に返す値を指定できる
  1. var i:Int ? = null
  2. println("%d".format(?: -1))
  3. -1
  • items(Listなど)のnullチェックを実施し、nullなら 0 の例
  1. return items?.size ?:0

強制Not null

  • !! を使用すると、nullableに対して、強制的にnot null
  1. var foo:String? = null
  2. var bar:String = foo!!
  3. tlin.KotlinNullPointerException

型チェックと自動キャスト

  • is演算子はインスタンスの型をチェックする
  • イミュータブルなローカル変数、プロパティは型がチェック済みのため明示的なキャストは不要
  1. package sample
  2.  
  3. fun getStringLen(obj: Any):Int? {
  4. if (obj is String) {
  5. // obj は、型チェックブロック内で自動的にキャストされる
  6. return obj.length;
  7. }
  8. // 型チェックブロックの外では、Anyのまま
  9. return null
  10. }
  11.  
  12. fun main(args: Array<String>) {
  13. println(getStringLen("abc"))
  14. println(getStringLen(123))
  15. }
実行
  1. PS> kotlin sample.Test05Kt
  2. 3
  3. null

forループ

  1. package sample
  2.  
  3. fun main(args: Array<String>) {
  4. var items = listOf("a", "b", "c")
  5. for (item in items) {
  6. println(item)
  7. }
  8.  
  9. for(index in items.indices) {
  10. println("item[$index] is ${items[index]}")
  11. }
  12. }
実行
  1. > kotlin sample.Test06Kt
  2. a
  3. b
  4. c
  5. item[0] is a
  6. item[1] is b
  7. item[2] is c

==

  1. for (year in 1900..2018 step 1) {
  2. println(convertJyunishiYear(year))
  3. }

whileループ

  1. var index = 0
  2. while(index < items.size) {
  3. println("item[$index] is ${items[index]}")
  4. index++
  5. }

When式

  • Kotlin には switch はない
引数あり
  1. package sample
  2.  
  3. fun describe(obj: Any?): String =
  4. when(obj) {
  5. 1 -> "One"
  6. "Hello" -> "Greeting"
  7. is Long -> "Long"
  8. !is String -> "Not a string"
  9. else -> "Unknown"
  10. }
  11.  
  12. fun main(args: Array<String>) {
  13. val items = listOf("Hello",1,9999999999,10.1,"hoge")
  14. for(item in items) {
  15. println("$item is ${describe(item)}")
  16. }
  17. }
実行
  1. PS> kotlin sample.Test07Kt
  2. Hello is Greeting
  3. 1 is One
  4. 9999999999 is Long
  5. 10.1 is Not a string
  6. hoge is Unknown
引数なし
  1. when {
  2. hoge == 0 -> {
  3. println("0")
  4. }
  5. hoge == 1 || hoge == 2 -> {
  6. println("1, 2")
  7. }
  8. else -> {
  9. println("else")
  10. }
  11. }

Rage

  1. package sample
  2.  
  3. fun main(args: Array<String>) {
  4. for (x in 1..3) {
  5. println("iteration $x")
  6. }
  7.  
  8. for (x in 1..6 step 2) {
  9. println("step $x")
  10. }
  11. for (x in 6 downTo 1 step 2) {
  12. println("downTo $x")
  13. }
  14.  
  15. // 値がRangeにの範囲内かinを使用してチェック
  16. val x = 10
  17. val y = 9
  18. if (x in 1..y+1) {
  19. println("$x in range")
  20. }
  21.  
  22. val index = -1
  23. val list = listOf("a","b","c")
  24. if (index !in 0..list.lastIndex) {
  25. println("$index is out of range")
  26. }
  27.  
  28. }
実行
  1. PS> kotlin sample.Test08Kt
  2. iteration 1
  3. iteration 2
  4. iteration 3
  5. step 1
  6. step 3
  7. step 5
  8. downTo 6
  9. downTo 4
  10. downTo 2
  11. 10 in range
  12. -1 is out of range

Try-with-resouce

  1. val stream = Files.newDirectoryStream(FileSystems.getDefault().getPath(targetDir))
  2. stream.use {
  3. for (path in stream) {
  4. println(path.fileName)
  5. }
  6. }

クラスとオブジェクト

プロパティ

  1. class Address {
  2. var name: String = ...
  3. var street: String = ...
  4. var city: String = ...
  5. var state: String? = ...
  6. var zip: String = ...
  7. }

列挙

  1. enum class Jikkan {
  2. Kinoe,
  3. Kinoto,
  4. Hinoe,
  5. Hinoto,
  6. Tuchinoe,
  7. Tuchinoto,
  8. Kanoe,
  9. Kanoto,
  10. Mizunoe,
  11. Mizunoto
  12. }
  • 初期化
  1. enum class Jikkan(val value: String) {
  2. Kinoe("甲"),
  3. Kinoto("乙"),
  4. Hinoe("丙"),
  5. Hinoto("丁"),
  6. Tuchinoe("戊"),
  7. Tuchinoto("己"),
  8. Kanoe("庚"),
  9. Kanoto("辛"),
  10. Mizunoe("壬"),
  11. Mizunoto("癸")
  12. }

書式

  1. "%s%s".format(foo,bar)

コレクション

0752 kotlin collection.png


書き込み可能なコレクション

  1. val list = mutableListOf(1, 2, 3)
  2. val map = mutableMapOf("foo" to "FOO", "bar" to "BAR")
  3. val set = mutableSetOf(9, 8, 7)

読み取り専用コレクション

val list = listOf(1, 2, 3)
val map = mapOf("foo" to "FOO", "bar" to "BAR")
val set = setOf(9, 8, 7)

Javaのコレクションを生成

var ia = arrayListOf<Int>()
var hs = hashSetOf<Int>()
var hm = hashMapOf<Int, Int>()


イディオム

DTO(POJO/POCO)

  • 以下が提供される
    • プロパティに対するgetter/setter
    • equals(),hashCode(),toString(),copy()
    • component1(),component2(),...componentN()全プロパティ
package sample

data class Customer(val name: String, val email: String)

fun main(args: Array<String>) {
    val cust = Customer("hoge","hoge@hoge.com")
    println(cust.toString())
    println("component1=${cust.component1()}")
    println("component2=${cust.component2()}")
    val(name,email) = cust
    print("name=$name,email=$email")
}
実行
PS> kotlin sample.Idiom01Kt
Customer(name=hoge, email=hoge@hoge.com)
component1=hoge
component2=hoge@hoge.com
name=hoge,email=hoge@hoge.com

関数パラメータデフォルト値

fun foo(a: Int=1, b: String="default") {
    println("a=$a,b=$b")
}

fun main(arg: Array<String>) {
    foo()
    foo(9,"custom")
}

リストのフィルタ

package sample

fun main(args: Array<String>) {
    // 変更可能なリスト
    val mutableList: MutableList<Int> = mutableListOf()
    for(n in 1..10) {
        mutableList.add(n)
    }
    println(mutableList)
    // リストのフィルタ
    println(mutableList.filter{x -> x % 2 == 0})
}
実行
PS> kotlin sample.Idiom03Kt
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[2, 4, 6, 8, 10]

Kotlin Android

Tips

File

読み込む

val reader = File(path)
reader.forEachLine {
    println(it)
}

指定のフォルダのファイル全てを読む

import java.io.File
import java.nio.file.*

class EachReader {

    fun check(targetDir: String) {

        val stream = Files.newDirectoryStream(FileSystems.getDefault().getPath(targetDir))
        stream.use {
            for (path in stream) {

                val fd = path.toFile()
                fd.forEachLine {
                    println(it)

                }
            }
        }
    }
}

fun main(args: Array<String>) {
    val targetDir = """C:\work"""
    var checker = EachReader()
    checker.check(targetDir)
}

固定バイトで読み込む

val reader = File(path).reader()
var buf:CharArray = CharArray(140)
while(reader.read(buf) > 0) {
    val line = String(buf)
    println(line)
}

文字コードを指定して読み書き

読み
val reader = File(file).bufferedReader(Charset.forName("Shift_JIS"))
書き
val writer = File("out.csv").bufferedWriter(Charset.forName("Shift_JIS"))

Sample

Link