Kotlin 1.3
M1 New Feature
Coroutine
buildSequence
andbuildIterator
moved tokotlin.sequences
.
Capturing when subject in a variable
- When のところで変数宣言できるようになった。
fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}
@JvmStatic
and @JvmField
can be used in companions of interfaces
- Interface が JVM Static な フィールド、 メンバ を持てるようになった。
コンパニオンオブジェクトの中で
@JvmStatic
,@JvmField
が使用可能。@JvmStatic
を使う場合は、 コンパイラオプション-jvm-target
を 1.8 以上にする。@JvmField
を使う場合は、public final val
という扱いになる。
interface Service {
companion object {
@JvmField
val ID = 0xF0EF
@JvmStatic
fun create(): Service = ...
}
}
Nested declarations in annotation classes
- annotation class が ネストされたクラス、 インターフェース、
コンパニオンオブジェクトを含むオブジェクトを内包できるようになった。
- 一つのアノテーションが他のアノテーションをネストできるようになった。
annotation class Outer(val param: Inner) {
annotation class Inner(val value: String)
}
annotation class Annotation {
companion object {
@JvmField
val timestamp = System.currentTimeMillis()
}
}
annotation class Annotation {
companion object {
@JvmField
val timestamp = System.currentTimeMillis()
}
}
Constant of Companion object in Basic type
Byte
,Short
,Int
,Long
,Char
: 定数SIZE_BITS
,SIZE_BYTES
Char
MIN_VALUE
:\u0000
MAX_VALUE
:\uFFFF
関数型
- 引数が255個まで使用可能になった。
Extension
orEmpty()
- sequence に追加された
isNullOrEmpty
- colelction, map, array に追加された。
Multiplatform random number generator
- Example
val number = Random.nextInt(limit) // number is in range [0, limit)
- A repeatable random generator initialized with a particular seed can be obtained with the top-level function
Random(seed)
val seriesRng = Random(42) val series = List(100) { seriesRng.nextDouble() }
SuccessOrFailure
SuccessOrFailure
- inline class The inline class SuccessOrFailure is effectively a discriminated union between successful and failed outcomes of execution of a Kotlin function: Success T | Failure Throwable.
It has been introduced to allow for capturing the result of a function execution, whether successful or not, in order to process it at a later time.
val files = listOf(File("a.txt"), File("b.txt"), File("42.txt"))
val contents: List<SuccessOrFailure<String>> = files.map { runCatching { readFileData(it) } }
println("map successful items:")
val upperCaseContents: List<SuccessOrFailure<String>> =
contents.map { r -> r.map { it.toUpperCase() } }
upperCaseContents.printResults()
println()
println("map successful items catching error from transform operation:")
val intContents: List<SuccessOrFailure<Int>> =
contents.map { r -> r.mapCatching { it.toInt() } }
intContents.printResults()
The primary driver for introducing this class is the new Continuation interface, where we want to have a single resumeWith(result: SuccessOrFailure
Experimental
M2 Feature
Standard Library
UInt
UByte
UIntArray
contentEquals
contentToString
contentHashCode
uintArrayOfZeros
UByteArray
Experimental
require
- add smart cast function
- execute lambda once.
- Enhanced New Style
- Example
fun test(x: List<Int>?) { // If the function returns false, the value is definitely not null: if (!x.isNullOrEmpty()) { println(x.size) // Yay, smart cast to not-null! } } fun test(x: Any?) { // If the function returns (does not throw), then the argument is true: require(x is String) println(x.length) // Smart cast here too! }
- affected functions
check
checkNotNull
require
requireNotNull
kotlin.test.assertTrue
kotlin.test.assertFalse
kotlin.test.assertNotNull
isNullOrEmpty
isNullOrBlank
- Example
- Analyzing variable initialization more accurately
- 変数の初期化状態について、コンパイラがより正確に判定できるようになった。(コンパイラに起因するエラーが出なくなる)
- 外のスコープの変数をグローバルに更新できるようになるということなので、あまり好ましくはないと思う。
- affected functions
run
let
with
apply
also
takeIf
takeUnless
synchronized
- Example
val x: Int synchronized(lock) { x = 42 // The compiler knows that the lambda is invoked exactly once! } println(x) // Allowed now, the compiler knows that 'x' is definitely assigned.
- 変数の初期化状態について、コンパイラがより正確に判定できるようになった。(コンパイラに起因するエラーが出なくなる)
- Copying elements between two existing arrays
- array についてのコピーメソッド
array.copyInto(targetArray, targetOffset, startIndex, endIndex)
val sourceArr = arrayOf("k", "o", "t", "l", "i", "n") val targetArr = sourceArr.copyInto(arrayOfNulls<String>(6), 3, startIndex = 3, endIndex = 6) println(targetArr.contentToString()) sourceArr.copyInto(targetArr, startIndex = 0, endIndex = 3) println(targetArr.contentToString())
- array についてのコピーメソッド
- associateWith
- create map with value
- It was possible to do it before with the associate { it to getValue(it) } function, but now we’re introducing a more efficient and easy to explore alternative: keys.associateWith { getValue(it) }
val keys = 'a'..'f' val map = keys.associateWith { it.toString().repeat(5).capitalize() } map.forEach { println(it) }
- It was possible to do it before with the associate { it to getValue(it) } function, but now we’re introducing a more efficient and easy to explore alternative: keys.associateWith { getValue(it) }
- create map with value
ifEmpty
,ifBlank
functionsifEmpty
- for Collections, maps, object arrays, char sequences and sequences. now have ifEmpty function, which allows to specify a substitute value that will be used instead of the receiver if it is empty.
fun printAllUppercase(data: List<String>) { val result = data .filter { it.all { c -> c.isUpperCase() } } .ifEmpty { listOf("<no uppercase>") } result.forEach { println(it) } } printAllUppercase(listOf("foo", "Bar")) printAllUppercase(listOf("FOO", "BAR"))
*
ifBlank
- for Char sequences and strings
val s = " \n" println(s.ifBlank { "<blank>" }) println(s.ifBlank { null })
- Random API improvements
- 非負値、非負Byte列を生成できるようになった。
nextUInt
,nextULong
,nextUBytes
の例
val randomUInt = Random.nextUInt(0x8000_0000u..0xFF00_0000u) println(randomUInt.toString(16)) val randomUBytes = Random.nextUBytes(4) println(randomUBytes.contentToString())
-
random
: collection, array, range からランダムで要素を取り出すことができるval sweets = listOf("nougat", "marshmallow", "oreo", "pie") println("I'm going to taste some ${sweets.random()} today!") val chars = 'a'..'z' val randomChars = String(CharArray(10) { chars.random() }) println(randomChars)
- 非負値、非負Byte列を生成できるようになった。
- Sealed classes reflection
KClass.sealedSubclasses
: Sealed class の 全ての直接のサブタイプ を走査できるクラス。
-
Inline classes In 1.3-M2 we introduce automatic mangling for names of functions that use inline classes in their signatures. We do it to prevent platform signature clashes when there are several overloads which are different only in the inline type, but not in the carrier type:
// All these types are inline classes mapped to String: fun foo(x: UserName) { ... } fun foo(x: Login) { ... } fun foo(x: UserHash) { ... }
Another reason for mangling is to forbid (accidental) usage from Java, which may be undesired as inline classes are a purely Kotlin concept. Mangled names will have the form of foo-
- Another two improvements
- the support for secondary constructors
- automatically generated toString/equals/hashCode functions
- Another two improvements