Kotlin - Javaとの相互運用


# はじめに

[Kotlin文法 - アノテーション、リフレクション、型安全なビルダー、動的型](http://qiita.com/k5n/items/3eaafc5aa5a07cd02f5c)の続き。

[Kotlin Reference](https://kotlinlang.org/dscs/reference/)のInterop章の大雑把日本語訳。適宜説明を変えたり端折ったり補足したりしている。

# KotlinからJavaのコードを呼ぶ

KotlinはJavaとの相互運用を念頭において設計されている。既存のJavaコードはKotlinから自然な方法で呼び出すことができる。そしてKotlinのコードも同様にかなりスムーズにJavaから利用することができる。この節ではKotlinからJavaのコードを呼ぶ場合の詳細を記述する。

ほとんど全てのJavaコードは何の問題もなく利用できる。

```kotlin
import java.util.*

fun demo(source: List<Int>) {
  val list = ArrayList<Int>()
  // Javaコレクションでのforループが動作する
  for (item in source)
    list.add(item)
  // 演算子置換ルールも同様に機能する
  for (i in 0..source.size() - 1)
    list[i] = source[i] // get と set が呼ばれる
}
```

## GetterとSetter

Javaの慣習に従ったgetterとsetter（*get*  で始まる名前の引数なしメソッドと、*set* で始まる１引数のメソッド）はKotlinではプロパティとして解釈される。例えば以下のように。

```kotlin
import java.util.Calendar

fun calendarDemo() {
    val calendar = Calendar.getInstance()
    if (calendar.firstDayOfWeek == Calendar.SUNDAY) {  // getFirstDayOfWeek()を呼ぶ
        calendar.firstDayOfWeek = Calendar.MONDAY      // setFirstDayOfWeek()を呼ぶ
    }
}
```

もしJavaクラスがsetterしか持たなかったら、Kotlinではプロパティとして見えないことに注意。今のところKotlinではsetしかできないプロパティはサポートしていないので。

## voidを返すメソッド

もしJavaメソッドがvoidを返す場合、Kotlinから呼び出されるときは *Unit* を返す。ひょっとして誰かがその値を使うなら、Kotlinコンパイラによって呼び出し箇所で代入される。値そのものは事前に（*Unit* になると）わかっているので。

## KotlinでキーワードになっているJava識別子のエスケープ

幾つかのKotlinキーワードはJavaでは有効な識別子。つまり *in*, *object*, *is* など。もしJavaライブラリがKotlinキーワードをメソッドに使っていたら、バッククォートでエスケープして呼び出すことができる。

```kotlin
foo.`is`(bar)
```

## Null安全とプラットフォーム型

Javaでの全ての参照は *null* になりうる。なのでJavaから来るオブジェクトに対しては、Kotlinの厳格なnull安全要求は実現困難になる。Java宣言の型はKotlinでは特別扱いされており、*プラットフォーム型* と呼ばれている。この型に対してのNullチェックは緩和され、安全保証はJavaの場合と同じになる（下記参照）。

次の例を考えてみよう。

```kotlin
val list = ArrayList<String>() // nullでない (コンストラクタの結果)
list.add("Item")
val size = list.size() // nullでない (プリミティブ型のint)
val item = list[0] // プラットフォーム型と推論される（普通のJavaオブジェクト）
```

プラットフォーム型の変数に対してメソッドを呼ぶ時、Kotlinはコンパイル時にnull可能性エラーを報告しない。しかしnullポインタ例外やnullの伝搬を防ぐためにKotlinが生成するアサーションによって、実行時に呼び出しが失敗するかもしれない。

```kotlin
item.substring(1) // 許可される。them == null で例外が投げられるかも。
```

プラットフォーム型は言語で明示的に書き下すことができないという意味で *表記できない* 。プラットフォーム型の値がKotlinの変数に代入されるとき、型推論（変数は上記例の *item* のようにプラットフォーム型と推論される）に頼るか、期待する型（nulllableもnullでない型も許される）を選ぶことができる[^1]。

[^1]: 安全なプログラムを書くためには、明示的にNullableを指定して、推論でプラットフォーム型にならないようにした方がいいと思う。

```kotlin
val nullable: String? = item // 許可されるし、常に動作する
val notNull: String = item   // 許可されるけど、実行時に失敗するかもしれない
```

nullでない型を選べば、コンパイラが代入前にアサーションを挿入する。これによりKotlinのnullでない型がnullを持つことを防ぐ。アサーションは、プラットフォーム型をnullでない型を期待する関数に渡すときなどにも挿入される。全体として、コンパイラはプログラムを通してnullが遠くに伝搬するのを防ぐようベストを尽くす（ジェネリクスがあるので完全に排除できないことがあるけれど）。

### プラットフォーム型の表記

上で言及した通り、プラットフォーム型はプログラム中で明示的に示すことはできない。つまり言語にそのための表記法はない。それでもコンパイラやIDEは時々それらを表示する必要がある（エラーメッセージやパラメータ情報など）。そのためこれらのための簡略表示法を用意している。

 - *T!* は "*TまたはT?* " を表す
 - *(Mutable)Collection&lt;T&gt;!* は「 *T* のJavaコレクションはmutableまたはそうでないかもしれず、nullableまたはそうでないかもしれない」を意味する。
 - *Array&lt;(out) T&gt;!* は「 *T* （または *T* のサブ型）のJava配列はnullableまたはそうでない」を意味する。

### Null可能性アノテーション

Null可能性アノテーションを持ったJava型は、プラットフォーム型ではなく実際のKotlinのnullableまたはnullでない型として表現される。今のところ、コンパイラは[JetBrains風のNull可能性アノテーション](https://www.jetbrains.com/idea/help/nullable-and-notnull-annotations.html)（*org.jetbrains.annotations* パッケージにある *@Nullable* と *@NotNull*）をサポートしている。

## マッピングされる型

Kotlinは幾つかのJava型を特別に扱う。これらの型はJavaから "そのまま" はロードされず、Kotlinの対応する型にマッピングされる。このマッピングはコンパイル時にだけ重要であり、実行時の表現は変化しないままである。Javaのプリミティブ型は対応するKotlin型にマッピングされる（プラットフォーム型のことは心に留めておいて）。

| Java型 | Kotlin型 |
|:-- |:-- |
| byte | kotlin.Byte |
| short | kotlin.Short |
| int | kotlin.Int |
| long | kotlin.Long |
| char| kotlin.Char |
| float | kotlin.Float |
| double | kotlin.Double |
| boolean | kotlin.Boolean |

幾つかのプリミティブでないビルトインクラスもマッピングされる。

| Java型 | Kotlin型 |
|:-- |:-- |
| java.lang.Object | kotlin.Any!
| java.lang.Cloneable | kotlin.Cloneable! |
| java.lang.Comparable | kotlin.Comparable! |
| java.lang.Enum | kotlin.Enum! |
| java.lang.Annotation | kotlin.Annotation! |
| java.lang.Deprecated | kotlin.Deprecated! |
| java.lang.Void | kotlin.Nothing! |
| java.lang.CharSequence | kotlin.CharSequence! |
| java.lang.String | kotlin.String! |
| java.lang.Number | kotlin.Number! |
| java.lang.Throwable | kotlin.Throwable! |

コレクション型はKotlinでは読み取り専用か可変のどちらかになる。なのでJavaコレクションは次のようにマッピングされる（この表のKotlin型は全て *kotlin*  パッケージにある）。

| Java型 | Kotlin読取専用型 | Kotlin可変型 | ロードされるプラットフォーム型 |
|:-- |:-- |:-- |:-- |
| Iterator&lt;T&gt; | Iterator&lt;T&gt; | MutableIterator&lt;T&gt; | (Mutable)Iterator&lt;T&gt;! |
| Iterable&lt;T&gt; | Iterable&lt;T&gt; | MutableIterable&lt;T&gt; | (Mutable)Iterable&lt;T&gt;! |
| Collection&lt;T&gt; | Collection&lt;T&gt; | MutableCollection&lt;T&gt; | (Mutable)Collection&lt;T&gt;! |
| Set&lt;T&gt; | Set&lt;T&gt; | MutableSet&lt;T&gt; | (Mutable)Set&lt;T&gt;! |
| List&lt;T&gt; | List&lt;T&gt; | MutableList&lt;T&gt; | (Mutable)List&lt;T&gt;! |
| ListIterator&lt;T&gt; | ListIterator&lt;T&gt; | MutableListIterator&lt;T&gt; | (Mutable)ListIterator&lt;T&gt;! |
| Map&lt;K, V&gt; | Map&lt;K, V&gt; | MutableMap&lt;K, V&gt; | (Mutable)Map&lt;K, V&gt;! |
| Map.Entry&lt;K, V&gt; | Map.Entry&lt;K, V&gt; | MutableMap.MutableEntry&lt;K,V&gt; | (Mutable)Map.(Mutable)Entry&lt;K, V&gt;! |

Java配列のマッピングについては後述する。

| Java型 | Kotlin型 |
|:-- |:-- | |
| int[] | kotlin.IntArray! |
| String[] | kotlin.Array<(out) String>! |

## KotlinでのJavaジェネリクス

KotlinのジェネリクスはJavaとは少し違っている（[ジェネリクス](http://qiita.com/k5n/items/18adb5c3503a54e96c22#%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AA%E3%82%AF%E3%82%B9)参照）。Java型をKotlinにインポートするとき、幾つかの変換が行われる。

 - Javaのワイルドカードは型投影に変換される
   - *Foo&lt;? extends Bar&gt;* は *Foo&lt;out Bar!&gt;!* になる
   - *Foo&lt;? super Bar&gt;* は *Foo&lt;in Bar!&gt;!* になる
 - Javaの原型(raw type)は星投影(star projection)に変換される
   - *List* は *List&lt;\*&gt;!* つまり *List&lt;out Any?&gt;!* になる

Javaと同様にKotlinのジェネリクスは実行時には保持されない。つまりオブジェクトはコンストラクタに渡された引数の実際の型情報を持ち運ばない。つまり *ArrayList&lt;Integer&gt;()* は *ArrayList&lt;Character&gt;()* と区別がつかない。これはジェネリクスを考慮した *is* チェックを不可能にする。Kotlinは星投影(star projection)されたジェネリック型に対してのみ *is* チェックを許している。

```kotlin
if (a is List<Int>) // Error: 本当にIntのリストかどうかチェックできない
// しかし
if (a is List<*>) // OK: リストの内容について何も保証しない
```

## Java配列

Kotlinでの配列はJavaと違って不変(invariant)である。これは *Array&lt;String&gt;* を *Array&lt;Any&gt;* に代入できないことを意味している。これにより実行時エラーを防ぐことができる。サブクラスの配列をスーパークラスの配列としてKotlinのメソッドに渡すことも禁止されている。しかしJavaのメソッドはこれを許可する（*Array&lt;(out) String&gt;!* の形のプラットフォーム型を通して）。

Javaプラットフォームではボクシングのコストを避けるため、プリミティブ型の配列が使われる。Kotlinはそれらの実装の詳細を隠すので、Javaコードのインターフェースに対しては回避方法が必要になる。こういう場合のためにプリミティブ型の配列にはそれぞれ特別なクラスが用意されている（*IntArray*, *DoubleArray*, *CharArray*などなど）。これらは *Array* クラスとの関係はなく、最大のパフォーマンスを発揮するJavaのプリミティブ配列にコンパイルされる。

intの配列を取るJavaメソッドがあるとしよう。

```kotlin
public class JavaArrayExample {

    public void removeIndices(int[] indices) {
        // code here...
    }
}
```

プリミティブ型の配列を渡すために、Kotlinでは次のようにできる。

```kotlin
val javaObj = JavaArrayExample()
val array = intArrayOf(0, 1, 2, 3)  // IntArrayを返す
javaObj.removeIndices(array)  // int[] をメソッドに渡す
```

JVMバイトコードにコンパイルされるとき、コンパイラは配列へのアクセスを最適化するので、オーバーヘッドは生じない。

```kotlin
val array = arrayOf(1, 2, 3, 4)
array[x] = array[x] * 2 // 実際にはget()やset()の呼び出しは生成されない
for (x in array) // イテレータは生成されない
  print(x)
```

インデックスをループで回すときでさえ、オーバーヘッドは生じない。

```kotlin
for (i in array.indices) // イテレータは生成されない
  array[i] += 2
```

最後に、*in* チェックもオーバーヘッドを生じない。

```kotlin
if (i in array.indices) { // (i >= 0 && i < array.size) と同じ
  print(array[i])
}
```

## Java可変長引数

Javaクラスはしばしば可変長引数(varargs)を使ってメソッドの引数を宣言している。

```kotlin
public class JavaArrayExample {

    public void removeIndices(int... indices) {
        // code here...
    }
}
```

こういう場合、*IntArray* を渡すのに展開演算子 * を使う必要がある。

```kotlin
val javaObj = JavaArray()
val array = intArrayOf(0, 1, 2, 3)
javaObj.removeIndicesVarArg(*array)
```

可変長引数として宣言されているメソッドにnullを渡すのは、今のところ不可能。

## 演算子

Kotlinの *operator* 修飾子のような、演算子として使うと分かるようにメソッドに印を付ける方法はJavaにはない。なのでKotlinは、Javaメソッドが正しい名前とシグネチャを持っていれば、演算子オーバーロードや他の変換ルール（*invoke()*など）に使うことを許す。接中辞記法でJavaメソッドを呼び出すことはできない。

## 検査例外

Kotlinでは全ての例外は検査されない。つまりコンパイラはどの例外もプログラマにキャッチすることを強制しない。なのでJavaで検査例外として宣言されているメソッドを呼び出す場合、Kotlinは何も強制しない。

```kotlin
fun render(list: List<*>, to: Appendable) {
  for (item in list)
    to.append(item.toString()) // JavaならIOExceptionをキャッチすることを要求するだろう
}
```

## オブジェクトメソッド

Java型がKotlinにインポートされるとき、全ての *java.lang.Object* 型の参照は *Any* になる。*Any* はプラットフォーム依存でないので、そのメンバとして *toString()*, *hashCode()* と *equals()* しか宣言していない。他の *java.lang.Object* のメンバを有効にするのに、Kotlinは拡張関数を使う。

### wait()/notify()

Effective Javaの69項は、wait()とnotify()よりもコンカレンシーユーティリティーを使うように提案している。それでこれらのメソッドは *Any* では有効になっていない。これらを本当に呼ぶ必要があるなら、*java.lang.Object* にキャストする。

```kotlin
(foo as java.lang.Object).wait()
```

### getClass()

オブジェクトから型情報を引き出すには、*javaClass* 拡張プロパティを利用する。

```kotlin
val fooClass = foo.javaClass
```

Javaの *Foo.class* の代わりに *Foo::class.java* を使う。

```kotlin
val fooClass = Foo::class.java
```

### clone()

*clone()* をオーバーライドするには、*kotlin.Cloneable* を実装する必要がある。

```kotlin
class Example : Cloneable {
  override fun clone(): Any { ... }
}
```

Effective Javaの第１１項「cloneを注意してオーバーライドする」を忘れないこと。

### finalize()

*finalize()* をオーバーライドするには、*override* キーワードなしで単に宣言するだけでいい。

```kotlin
class C {
  protected fun finalize() {
    // finalization logic
  }
}
```

Javaのルールに従い、*finalize()* は *private* であってはいけない。

## Javaクラスからの継承

最大１つのJavaクラス（と好きなだけの数のJavaインターフェース）がKotlinクラスのスーパー型になれる。

## staticメンバへのアクセス

Javaクラスのstaticメンバは "コンパニオンオブジェクト" の形になる。こういう "コンパニオンブジェクト" は値として渡すことはできない。しかしメンバに明示的にアクセスすることはできる。例えば以下のように。

```kotlin
if (Character.isLetter(a)) {
  // ...
}
```

## Javaリフレクション

JavaリフレクションはKotlinでも動作するし、その逆も同様。*java.lang.Class* を通してJavaリフレクションに入り込むのに、上述したように *instance.javaClass* や *ClassName::class.java* を利用できる。

他にもJavaのgetter/setterメソッドやKotlinプロパティのバッキングフィールドを獲得することもできる。Javaフィールドには *KProperty* 、Javaメソッドやコンストラクタには *KFunction* を使う。

## SAM変換

Java 8のように、KotlinはSAM[^2]変換をサポートする。つまりKotlinの関数リテラルは、デフォルトでない１つだけのメソッドを持つJavaインターフェースの実装へと、自動的に変換される。インターフェースメソッドの引数の型とKotlin関数の引数の型が一致していれば。

[^2]: Single Abstract Method

SAMインターフェースのインスタンスをこんな風に作成できる。

```kotlin
val runnable = Runnable { println("This runs in a runnable") }
```

...で、メソッド呼び出しではこんな感じ。

```kotlin
val executor = ThreadPoolExecutor()
// Javaでのシグネチャ: void execute(Runnable command)
executor.execute { println("This runs in a thread pool") }
```

もしJavaクラスが別のSAMインターフェースを取る複数のメソッドを持つなら、ラムダを指定SAM型に変換するアダプタ関数を使ってどれを使うか選択する。これらのアダプタ関数も必要に応じてコンパイラが生成する。

```kotlin
// Runnable以外のSAMインターフェースを取るexecuteがあるので、
// アダプタ関数 Runnable を使って、Rnnnableを取るexecuteを指定。
executor.execute(Runnable { println("This runs in a thread pool") })
```

SAM変換はインターフェースに対してしか働かないことに注意。たとえ１つの抽象メソッドしか持たなかったとしても、抽象クラスには働かない。

またこの機能はJavaとの相互運用でしか働かないことにも注意。Kotlinはちゃんとした関数型を持ってるので、関数からKotlinインターフェースへの自動変換は必要ないし、だからサポートされていない。

# JavaからKotlinのコードを呼ぶ

KotlinのコードはJavaから簡単に呼び出すことができる。

## プロパティ

プロパティのgetterはget-メソッドに、setterはset-メソッドになる。

## パッケージレベルの関数

パッケージ *org.foo.bar* 内の *example.kt* ファイルで宣言された全ての関数とプロパティは、*org.foo.bar.ExampleKt* という名前のJavaクラスに所属する。

```kotlin:example.kt
package demo

class Foo

fun bar() {
}
```

```java
// Java
new demo.Foo();
demo.ExampleKt.bar();
```

生成されるJavaクラスの名前は *@JvmName* アノテーションで変更することができる。

```kotlin
@file:JvmName("DemoUtils")

package demo

class Foo

fun bar() {
}
```

```java
// Java
new demo.Foo();
demo.DemoUtils.bar();
```

同じJavaクラス名（同じパッケージで同じ名前または同じ@JvmNameアノテーション）で生成されるファイルが複数ある場合、通常はエラーになる。しかしコンパイラにはそれらを１つにまとめたファサードクラスを生成する機能がある。これを有効にするには全てのファイルに *@JvmMultifileClass* アノテーションを付ける。

```kotlin:oldutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass

package demo

fun foo() {
}
```

```kotlin:newutils.kt
@file:JvmName("Utils")
@file:JvmMultifileClass

package demo

fun bar() {
}
```

```java
// Java
demo.Utils.foo();
demo.Utils.bar();
```

## フィールド

もしKotlinのプロパティをJavaのフィールドとして外に出す必要があるなら、*@JvmField* アノテーションを付ける。そのフィールドのアクセス制限はプロパティと同じになる。このアノテーションを付けられるのは、バッキングフィールドを持ち、privateでなく、*open* でも *override* でも *const* でもなく、デリテートされたプロパティでもない場合。

```kotlin
class C(id: String) {
    @JvmField val ID = id
}
```

```java
// Java
class JavaClient {
    public String getID(C c) {
        return c.ID;
    }
}
```

## staticなメソッドとフィールド

上述したように、Kotlinはパッケージレベルの関数をstaticメソッドとして生成する。またコンパニオンオブジェクトや名前付きオブジェクトに定義された関数に *@JvmStatic* アノテーションが付けられた場合も、staticメソッドとして生成する。例を挙げよう。

```kotlin
class C {
  companion object {
    @JvmStatic fun foo() {}  // コンパニオンオブジェクトの関数に@JvmStatic指定
    fun bar() {}
  }
}
```

これで *foo()* はJavaでstaticになる。*bar()*はならない。

```java
C.foo(); // うまく動作する
C.bar(); // error: staticメソッドでない
```

名前付きオブジェクトも同じ。

```kotlin
object Obj {
    @JvmStatic fun foo() {}
    fun bar() {}
}
```

Javaからこう呼び出せる。

```java
Obj.foo(); // うまくいく
Obj.bar(); // error
Obj.INSTANCE.bar(); // 動作する。シングルトンインスタンスを通して呼び出す。
Obj.INSTANCE.foo(); // 同様に動作する。
```

またオブジェクトやコンパニオンオブジェクトに定義されたpublicプロパティも、*const* 修飾されたトップレベルプロパティと同様に、Javaではstaticフィールドになる。

```kotlin:example.kt
object Obj {
  val CONST = 1
}

const val MAX = 239
```

Javaからこう呼び出せる。

```java
int c = Obj.CONST;
int d = ExampleKt.MAX;
```
## @JvmNameによるシグネチャ衝突の回避

ときどきKotlinで、バイトコードでは異なるJVM名が必要な名前付き関数を持つことがある。典型的な例は *型消去* によって起こる。

```kotlin
fun List<String>.filterValid(): List<String>
fun List<Int>.filterValid(): List<Int>
```

これら２つの関数は一緒には定義できない。なぜならこれらのJVMシグネチャは同じ(*filterValid(Ljava/util/List;)Ljava/util/List;*)だから。もしKotlinで本当にこれらを同じ名前にしたいなら、片方（または両方）に *@JvmName* アノテーションで異なるJVM名を付けてやる付けてやる。

```kotlin
fun List<String>.filterValid(): List<String>

// こっちはKotlinでは同じ名前で使うけど、JVMバイトコードではfilterValidIntって名前にする
@JvmName("filterValidInt")
fun List<Int>.filterValid(): List<Int>
```

これでKotlinからはどちらも同じ名前 *filterValid* でアクセスできる。けどJavaからは*filterValid* と *filterValidInt* になる。

同じトリックは *getX()* があるのにプロパティ *x* が必要な時にも使える。

```kotlin
// getX()があるので、何も指定しないとxのgetterと名前が衝突する
val x: Int
  @JvmName("getX_prop")  // getterのJVM名に別の名前を指定する
  get() = 15

fun getX() = 10
```

## オーバーロードの生成

デフォルト値を持ったKotlinのメソッドを書く場合、通常Javaからは全てのパラメータを持った１つのメソッドとして見える。もしJavaから複数のオーバーロードとして見えるようにしたいなら、*@JvmOverloads* アノテーションが使える。

```kotlin
@JvmOverloads fun f(a: String, b: Int = 0, c: String = "abc") {
    ...
}
```

デフォルト値を持つそれぞれのパラメータに対して、そのパラメータの右側にあるパラメータを除いたオーバーロードを１つずつ生成する。この例では、次のメソッドが生成される。

```java
// Java
void f(String a, int b, String c) { }
void f(String a, int b) { }
void f(String a) { }
```

このアノテーションはコンストラクタやstaticメソッドなどに対しても使える。インターフェースに定義されたものも含めて抽象メソッドに対しては使えない。

[コンストラクタ](http://qiita.com/k5n/items/35e76d79ee9de4effb89#%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF )で記述したように、全てのコンストラクタ引数がデフォルト値を持つクラスでは、publicな引数なしコンストラクタが生成されることに注意。これは *@JvmOverloads* を指定しなくてもそうなる。

## 検査例外

前述した通り、Kotlinに検査例外はない。なので通常Kotlin関数のJavaシグネチャは例外を投げるとは宣言されない。こんなKotlinの関数があるとする。

```kotlin:example.kt
package demo

fun foo() {
  throw IOException()
}
```

それをJavaから呼んで例外をキャッチしたいとする。

```java
try {
  demo.Example.foo();
}
catch (IOException e) { // error: foo()は検査例外IOExceptionをthrowsリストの中に宣言していない
  // ...
}
```

*foo()* は *IOException* を宣言していないので、Javaコンパイラからエラーメッセージを受け取る。この問題に対処するには、Kotlin側で *@Throws* アノテーションを使う。

```kotlin
@Throws(IOException::class)
fun foo() {
    throw IOException()
}
```
## Null安全

JavaからKotlinの関数を呼ぶとき、nullでないパラメータにnullを渡せてしまう。なのでKotlinの方で、nullでないことを期待する全てのpublic関数に実行時チェックを挿入している。これによってJavaコードは即座に *NullPointerException* を受け取ることになる。

## ジェネリクスの変性

Kotlinのクラスが宣言側変性を使うとき、Javaコードから見える利用方法には２つのオプションがある。次のクラスとそれを使う２つの関数を見てみよう。

```kotlin
// T型の値を格納する箱。Tを返すメソッドしか持たないので <out T> にできる。
// コンストラクタ引数にvalを付けているので、読み取り専用プロパティvalueが自動生成される。
class Box<out T>(val value: T)

// Boxに入れる型として、Baseインターフェースを実装したDerivedクラスを用意
interface Base
class Derived : Base

// Defived型の値をBoxに入れて返す
fun boxDerived(value: Derived): Box<Derived> = Box(value)
// BoxからBase型（Derivedじゃないよ）の値を取り出す
fun unboxBase(box: Box<Base>): Base = box.value
```

これらをJavaに翻訳する自然な方法はこうなるだろう。

```java
Box<Derived> boxDerived(Derived value) { ... }
Base unboxBase(Box<Base> box) { ... }
```

問題はKotlinでは *unboxBase(boxDerived("s"))* と書けても[^3]、Javaでは書けないということ。なぜならJavaではBoxは型Tに対して *不変(invariant)* だから。つまり *Box&lt;Derived&gt;* は *Box&lt;Base&gt;* のサブ型ではない。これをJavaで動作させるには *unboxBase* を次のように定義しなければならない。

[^3]: Boxが宣言側変性でoutを指定しているから、Box&lt;Derived&gt;はBox&lt;Base&gt;のサブ型として扱える。難しく言うならBoxはTに対して共変(covariant)。

```java
Base unboxBase(Box<? extends Base> box) { ... }
```

ここでは宣言側変性を利用側変性でエミュレートするために、Javaのワイルドカード( *? extends Base* )を使っている。だってJavaにはこれしかないから。

KotlinのAPIをJavaで動作させるために、パラメータとして現れる場所で、共変として定義された *Box*  に対して *Box&lt;Super&gt;* を *Box&lt;? extends Super&gt;* として生成している。戻り値に対してワイルドカードは生成しない。そうしないとJavaクライアントがそれらを扱わないといけなくなるから（そしてJavaのコーディングスタイルに反する）。そんなわけで、先ほどの例は実際は次のように翻訳される。

```java
// 戻り値の型 - ワイルドカードは使わない
Box<Derived> boxDerived(Derived value) { ... }
 
// パラメータ - ワイルドカードを使う
Base unboxBase(Box<? extends Base> box) { ... }
```

注：パラメータの型がfinalの場合[^4]、通常はワイルドカードを生成する箇所はない。なのでそれを取る場所に関係なく *Box&lt;String&gt;* は常に *Box&lt;String&gt;* になる。

[^4]: つまり継承できない。

デフォルトでは生成されない場所にワイルドカードが必要なら、*@JvmWildcard* アノテーションが使える。

```kotlin
fun boxDerived(value: Derived): Box<@JvmWildcard Derived> = Box(value)
// これは次のように翻訳される
// Box<? extends Derived> boxDerived(Derived value) { ... }
```

逆に生成される場所でワイルドカードがいらない場合は、*@JvmSuppressWirldcard* が使える。

```kotlin
fun unboxBase(box: Box<@JvmSuppressWildcards Base>): Base = box.value
// これは次のように翻訳される
// Base unboxBase(Box<Base> box) { ... }
```

### Nothing型の翻訳

*Nothing* 型[^5]は特別で、Javaには自然に対応するものがない。実際、*java.lang.Void* を含む全てのJava型の参照は値としてnullを受け入れるが、*Nothing* はそれさえも受け入れない。なのでこの型はJavaの世界では正確に表現することはできない。これが引数の型に *Nothing* を使う場所でKotlinが原型(raw type)を生成する理由である。

[^5]: 「決して存在しない」ことを表す型で、インスタンスを持たない。関数の戻り値がこの型なら、関数が戻らない（常に例外を投げる）ことを意味する。

```kotlin
fun emptyList(): List<Nothing> = listOf()
// これは次のように翻訳される
// List emptyList() { ... }
```