!!!Kotlin *https://kotlinlang.org {{amazon 4865940391}} *[リファレンス|https://kotlinlang.org/docs/reference/] !!Install [Command Line|https://kotlinlang.org/docs/tutorials/command-line.html] !SDKMAN *http://sdkman.io/ *https://qiita.com/saba1024/items/967ee3d8a79440a97336 $ curl -s https://get.sdkman.io | bash *ターミナルを開き直し $ sdk install kotlin *確認 $ kotolinc -help !REPL $kotlinc-jvm !!IDE !Intellij IDEA *https://www.jetbrains.com/idea/ !!!基本 !!コンパイルと実行 *コンパイル $ kotlinc sample.kt *実行 $ kotlin sample.SampleKt !!データ型 !数値型 ,型 ,Double ,Float ,Long ,Int ,Short ,Byte !!パッケージと関数 // ソースファイルの先頭に記述 // ディレクトリ構造と一致する必要はない。 package sample // 2つのInt引数と戻り値Intをもつ fun sum(a: Int, b: Int): Int { return a + b } // 式を持ち、戻り値を推測 fun sum2(a: Int, b: Int) = a + b // 意味のある値を返さない場合、Unitを使用 fun printSum(a: Int, b: Int): Unit { println("$a + $b = ${a + b}") } // Unit は省略可能 fun printSum2(a: Int, b: Int) { println("$a + $b = ${a + b}") } fun main(args: Array) { println(sum(1,2)) println(sum2(3,4)) printSum(5,6) printSum(7,8) } ::実行 PS> kotlinc Test01.kt PS> kotlin sample.Test01Kt 3 7 5 + 6 = 11 7 + 8 = 15 !!ローカル変数 package sample fun main(args: Array) { // val:読み取り専用 val a: Int = 1 // 即時割り当て val b = 2 // Int型を推測 val c: Int // 即時初期化しない場合、型は必須 c = 3 // c = 4 // error: val cannot be reassigned // var:変更可能 var d = 5 d += 1 println("$a,$b,$c,$d") } !!文字列テンプレート package sample fun main(args: Array) { // 文字列はテンプレート式を含むことができる // テンプレート式は、$で始める val a = 10 println("a is $a") // 中括弧で任意の式を表現 val s = "abc" println("$s.length is ${s.length}") // テンプレートは、raw文字列、エスケープされた文字列もサポートする // $リテラルを表示するのに、バックスラッシュエスケープは機能しない(以下参照) val l = """ ${'$'}123 """ print(l) } ::実行 PS> kotlin sample.Test03Kt a is 10 abc.length is 3 $123 !!条件式 *三項演算子はないが、ifを式として利用できる package sample fun maxOf(a: Int, b: Int): Int { if (a > b) { return a } else { return b } } // if を式として利用 fun maxOfExpression(a: Int, b: Int) = if (a > b) a else b fun main(args: Array) { println(maxOf(3,5)) println(maxOfExpression(6,8)) } ::実行 PS> kotlin sample.Test04Kt 5 8 !!nulableとnullチェック ""ターミナルで、kotlinc とタイプすると、REPLが起動する。終了には、:quit *参照は、nullが設定可能な場合、明示的に nullableとマークする必要がある >>> var a: Int? =null >>> a null *マークしないとエラー >>> var a: Int = null error: null can not be a value of a non-null type Int var a: Int = null !!安全呼び出し *?.を使うと、オブジェクトがnullの場合、nullを返し、そうでない場合メソッドを呼び出す var foo:Foo? = bar?.getInstance() !!エルビス演算子 *?: を使用すると、オブジェクトがnullの場合に返す値を指定できる var i:Int ? = null println("%d".format(i ?: -1)) -1 *items(Listなど)のnullチェックを実施し、nullなら 0 の例 return items?.size ?:0 !!強制Not null *!! を使用すると、nullableに対して、強制的にnot null var foo:String? = null var bar:String = foo!! tlin.KotlinNullPointerException !!型チェックと自動キャスト *is演算子はインスタンスの型をチェックする *イミュータブルなローカル変数、プロパティは型がチェック済みのため明示的なキャストは不要 package sample fun getStringLen(obj: Any):Int? { if (obj is String) { // obj は、型チェックブロック内で自動的にキャストされる return obj.length; } // 型チェックブロックの外では、Anyのまま return null } fun main(args: Array) { println(getStringLen("abc")) println(getStringLen(123)) } ::実行 PS> kotlin sample.Test05Kt 3 null !!forループ package sample fun main(args: Array) { var items = listOf("a", "b", "c") for (item in items) { println(item) } for(index in items.indices) { println("item[$index] is ${items[index]}") } } ::実行 > kotlin sample.Test06Kt a b c item[0] is a item[1] is b item[2] is c :: for (year in 1900..2018 step 1) { println(convertJyunishiYear(year)) } !!whileループ var index = 0 while(index < items.size) { println("item[$index] is ${items[index]}") index++ } !!When式 *Kotlin には switch はない ::引数あり package sample fun describe(obj: Any?): String = when(obj) { 1 -> "One" "Hello" -> "Greeting" is Long -> "Long" !is String -> "Not a string" else -> "Unknown" } fun main(args: Array) { val items = listOf("Hello",1,9999999999,10.1,"hoge") for(item in items) { println("$item is ${describe(item)}") } } ::実行 PS> kotlin sample.Test07Kt Hello is Greeting 1 is One 9999999999 is Long 10.1 is Not a string hoge is Unknown ::引数なし *https://qiita.com/AAkira/items/3d5b694d488fe029d7b9 when { hoge == 0 -> { println("0") } hoge == 1 || hoge == 2 -> { println("1, 2") } else -> { println("else") } } !!Rage package sample fun main(args: Array) { for (x in 1..3) { println("iteration $x") } for (x in 1..6 step 2) { println("step $x") } for (x in 6 downTo 1 step 2) { println("downTo $x") } // 値がRangeにの範囲内かinを使用してチェック val x = 10 val y = 9 if (x in 1..y+1) { println("$x in range") } val index = -1 val list = listOf("a","b","c") if (index !in 0..list.lastIndex) { println("$index is out of range") } } ::実行 PS> kotlin sample.Test08Kt iteration 1 iteration 2 iteration 3 step 1 step 3 step 5 downTo 6 downTo 4 downTo 2 10 in range -1 is out of range !!Try-with-resouce val stream = Files.newDirectoryStream(FileSystems.getDefault().getPath(targetDir)) stream.use { for (path in stream) { println(path.fileName) } } !!!クラスとオブジェクト !!プロパティ class Address { var name: String = ... var street: String = ... var city: String = ... var state: String? = ... var zip: String = ... } !!列挙 enum class Jikkan { Kinoe, Kinoto, Hinoe, Hinoto, Tuchinoe, Tuchinoto, Kanoe, Kanoto, Mizunoe, Mizunoto } *初期化 enum class Jikkan(val value: String) { Kinoe("甲"), Kinoto("乙"), Hinoe("丙"), Hinoto("丁"), Tuchinoe("戊"), Tuchinoto("己"), Kanoe("庚"), Kanoto("辛"), Mizunoe("壬"), Mizunoto("癸") } !!書式 "%s%s".format(foo,bar) !!!コレクション *[Kotlin のコレクション使い方メモ|https://qiita.com/opengl-8080/items/36351dca891b6d9c9687]から引用 {{ref_image kotlin_collection.png}} !書き込み可能なコレクション val list = mutableListOf(1, 2, 3) val map = mutableMapOf("foo" to "FOO", "bar" to "BAR") 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() var hs = hashSetOf() var hm = hashMapOf() !!!イディオム !!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) { 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) { foo() foo(9,"custom") } !!リストのフィルタ package sample fun main(args: Array) { // 変更可能なリスト val mutableList: MutableList = 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 *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) { 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 *[Android + Kotlin で Firebaseによるメール認証|http://typea.info/blg/glob/2018/06/android-kotlin-firebase.html] !!Link *[kotlin標準ライブラリ|https://qiita.com/droibit/items/75416c0955b797931bb8]