Edit Page

基本の型

Kotlinでは、メンバ関数やプロパティをどんな変数からでも呼び出せるという意味で、全てのものがオブジェクトです。 いくつかの型は実装が最適化されているためビルトインであるが、ユーザから見ると普通のクラスのように見えます。このセクションでは、次の型の大部分を説明します:数値、文字、真偽値(boolean)、配列。

数値

Kotlinは、Javaに近い方法で数字を扱うが、全く同じではありません。例えば、数値の暗黙の拡大変換が存在せず、リテラルはいくつかの事例では少し異なる。

Kotlinは数値の表現用に次のビルトインの型を提供します(これはJavaに近い):

ビット幅
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

Kotlinでは文字は数値でないことに注意してください。

リテラル定数

整数値のためのリテラル定数は、次の種類があります。

  • 数値: 123
    • Long型の数を表すには大文字のLでタグ付けする: 123L
  • 16進数: 0x0F
  • 2進数: 0b00001011

注:8進数のリテラルはサポートされていません。

Kotlinは浮動小数点数の従来の表記法もサポートしています。

  • デフォルトではdouble型: 123.5, 123.5e10
  • float型を表すには f or F でタグ付けする: 123.5f

表現

Javaプラットフォームでは、null許容型な数値の参照(例:Int?)やジェネリクスが関与している場合を除いて、JVMプリミティブ型として数値が物理的に格納されています。後者の例では番号がボクシングされています。

数値のボクシングは一様性を保持しないことに注意してください:

val a: Int = 10000
print(a === a) // 'true'を出力する
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA === anotherBoxedA) // !!! 'false'を出力する !!!

一方、これは同一性を保持しています:

val a: Int = 10000
print(a == a) // 'true'を出力する
val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA == anotherBoxedA) // 'true'を出力する

明示的な変換

異なる表現であるが故に、小さな型は大きな型のサブタイプではありません。 もし仮にそうであったならば、次の種類の悩みを抱えたでしょう:

// 仮説のコードであり、実際はコンパイルできません:
val a: Int? = 1 // ボクシングされたInt型 (java.lang.Integer)
val b: Long? = a // 暗黙の変換がLong型 (java.lang.Long)へのボクシングを引き起こします
print(a == b) // 仰天!これはLong型のequals()チェックで他の部分がLong型になるのと同等に "false" を出力します

つまり、同一性だけでなく一様性でさえも全ての場所において静かに失われたのです。

その結果、小さな型は、暗黙的に大きな型に変換されるのではありません。これは明示的変換無しでByte型の値をInt型へ代入することができないことを意味します。

val b: Byte = 1 // OK, リテラルは静的にチェックされています
val i: Int = b // ERROR

明示的変換は数字を拡張する際に使用することができます。

val i: Int = b.toInt() // OK: 明示的に拡張されました

全ての数値型は次の変換をサポートしています:

  • toByte(): Byte
  • toShort(): Short
  • toInt(): Int
  • toLong(): Long
  • toFloat(): Float
  • toDouble(): Double
  • toChar(): Char

明示的変換がないことは滅多に目立ちません。なぜならその型は文脈から推測され、算術演算がオーバロードされ適切に変換されるからです。例えば:

val l = 1L + 3 // Long + Int => Long

演算

Kotlinは算術計算の標準セットをサポートしています。それらは適切なクラス(ただしコンパイラは対応する命令の呼び出しを最適化する)のメンバとして宣言されています。演算子のオーバーロードを参照してください。

ビット演算にはそのような特殊な文字列がありませんが、中置形で呼び出せる名前付き関数があります。例えば:

val x = (1 shl 2) and 0x000FF000

これらはビット単位の操作を行う全リストです(IntLongのみ利用可能):

  • shl(bits) – 符号付き左シフト (Javaの <<)
  • shr(bits) – 符号付き右シフト (Javaの >>)
  • ushr(bits) – 符号無し右シフト (Javaの >>>)
  • and(bits) – ビット演算のand
  • or(bits) – ビット演算のor
  • xor(bits) – ビット演算のxor
  • inv() – ビット演算の反転

文字

文字は、Char型で表されます。数字として直接扱うことはできません。

fun check(c: Char) {
  if (c == 1) { // ERROR: 非互換の型
    // ...
  }
}

[translation here] 文字リテラルを表現するには、シングルクォートで囲みます: '1' 特殊文字はバックスラッシュを使ってエスケープすることができます。 次のエスケープシーケンスがサポートされています:\t, \b, \n, \r, \', \", \\, \$ 他の文字をエンコードするには、Unicodeエスケープシーケンスの構文を使用します:'\uFF00'

明示的に文字をInt型の数に変換することもできます。

fun decimalDigitValue(c: Char): Int {
  if (c !in '0'..'9')
    throw IllegalArgumentException("Out of range")
  return c.toInt() - '0'.toInt() // 暗黙的な数値への変換
}

数値のように、文字はnull許容参照が必要なときにボクシングされます。同一性ははボクシング操作されると保持されません 。

真偽値 (Boolean)

[translation here] Boolean型は真偽値を表し、truefalseの2つの値があります。

Booleanはnull許容参照が必要なときにボクシングされます。

Booleanのビルトイン演算は次を含みます:

  • || – 遅延評価論理和
  • && – 遅延評価論理積
  • ! - 否定

配列

Kotlinでの配列は Array クラスで表され、getset1関数を持ちます([]の演算子をオーバロードすることによって実現している)。また、size`プロパティがいくつかの有用なメンバ関数と共に有効になっています:

class Array<T> private constructor() {
  val size: Int
  fun get(index: Int): T
  fun set(index: Int, value: T): Unit

  fun iterator(): Iterator<T>
  // ...
}

配列を作るには、ライブラリ関数のarrayOf()にアイテムの値を渡してください。つまり、arrayOf(1, 2, 3)は[1, 2, 3]の配列を作成します。 あるいはライブラリ関数のarrayOfNulls()で、null要素で埋められた指定サイズの配列を作ることができます。

他のやり方として、配列のサイズと配列のインデックス値を与えると各要素の初期値用に値を返す関数を引数にとるファクトリ関数の使用があります。

// Array<String>を["0", "1", "4", "9", "16"]の値で作成します
val asc = Array(5, { i -> (i * i).toString() })

前述したとおり、[]演算はメンバ関数のget()set()の呼び出しを表します。

注:Javaとは異なり、Kotlinの配列は不変です。つまりKotlinではArray<Any>Array<String>を代入することができないということを表します。これは実行時エラーを回避するためです(しかし、Array<out Any>を使えば代入できます。型プロジェクションを参照してください)。

Kotlinはプリミティブ型(ByteArrayShortArrayIntArray等)の配列について、オーバーヘッド無しでボクシングができる特別なクラスを持ちます。 これらのクラスはArrayクラスと継承関係を持ちませんが、同じメソッドとプロパティを持ちます。 それぞれのクラスにおいて、対応するファクトリ関数を持ちます:

val x: IntArray = intArrayOf(1, 2, 3)
x[0] = x[1] + x[2]

文字列

文字列は、String型で表されます。文字列は不変(イミュータブル)です。 文字列の要素は、インデックスの演算でアクセスできます:s[i] 文字列は forループでイテレート(繰り返し操作)できます:

for (c in str) {
  println(c)
}

文字列リテラル

Kotlinは2つの種類の文字列リテラルを持ちます:1つはエスケープされた文字列を持ちうるエスケープ済み文字列で、もう1つは改行と任意の文字を含む生文字列です。 エスケープ済み文字列はJavaの文字列に非常によく似ています:

val s = "Hello, world!\n"

エスケープは、バックスラッシュを用いて従来の方法で行われます。サポートされているエスケープシーケンスのリストについては、文字列を参照してください。

生文字列は三連クオート (""") で区切られます。エスケープは含まれておらず、改行や他の文字を含めることができます:

val text = """
  for (c in "foo")
    print(c)
"""

先頭の空白をtrimMargin()関数で削除することができます。

val text = """
    |Tell me and I forget. 
    |Teach me and I remember. 
    |Involve me and I learn.
    |(Benjamin Franklin)
    """.trimMargin()

デフォルトでは|はマージンの接頭辞として使用されますが、trimMargin(">")のように、パラメータとして別の文字を渡すとそれを接頭辞として使用することができます。

文字列テンプレート

文字列はテンプレート式、すなわち、評価され、その結果が文字列と結合されるコードの断片を含むことができる。テンプレート式は、ドル記号($)で始まり、簡単な名前で構成されます:

val i = 10
val s = "i = $i" // "i = 10"と評価される

または、波括弧を使った従来の記法もあります:

val s = "abc"
val str = "$s.length is ${s.length}" // "abc.length is 3"と評価される

テンプレートは生文字列、エスケープ済み文字列のどちらに含まれていても動作します。 もし$の文字リテラルを生文字列内(バックスラッシュでのエスケープをサポートしない)で表現する必要がある場合は、次の文法を使用できる:

val price = """
${'$'}9.99
"""