クラスの生成方法の違い
- インスタンス化時には、クラス名の前に
new
が必要
プリミティブ型
- BooleanやIntegerは、ラッパークラスであり、
null
が許容される - booleanやintは、プリミティブ型であり、
null
はコンパイルエラーとなる
拡張メソッド、プロパティが定義できない
- Kotlinで定義した拡張メソッド、プロパティをJavaから呼び出すことは可能
JavaSample2.java
public class JavaSample2 { }
JavaSample2Ext.kt// 拡張プロパティの定義 @get:DrawableRes val JavaSample2.iconResourceId: Int get() { return R.drawable.ic_launcher_background } // 拡張メソッドの定義 fun JavaSample2.sayHello(name: String) { // TODO: }
JavaSample.ktpublic class JavaSample { void say(String name) { JavaSample2 javaSample2 = new JavaSample2(); // 拡張プロパティの呼び出し Integer resId = JavaSample2ExtKt.getIconResourceId(javaSample2); // 拡張メソッドの呼び出し JavaSample2ExtKt.sayHello(javaSample2, name); } }
nullがコンパイル時にわからない
nullのアンラップが冗長になる
-
?:
や、?.
が使用できない
スコープ関数がない
-
let
,also
などが使用できない - 配列クラスの
.forEach
や.filter
は使用できる
デフォルト引数が定義できない
- 多く呼び出し箇所をもつメソッドに引数を追加したときに困る時がある
- 対処法
- 新たにメソッドを定義し、古いメソッドからそれを呼び出す(この時デフォルト値を渡す)
public class JavaSample2 { void methodOld() { methodNew("This is default value"); } void methodNew(String name) { // 元の処理 } }
sealedクラスが、switch文(when文)のパターンマッチに使用できない
- Java8では不可能。Java17から利用できる。
- このため、enumクラスを定義するなどして対応する必要がある
変数の定義方法
-
val
がない。final
が似た扱い。 - 型を先に書く
- 型に
?
を付けてなくても、基本的に全てnullable
になってしまう
関数の定義順序
-
fun
を書かない -
戻り値の型
関数名
の順 - 何も返さない場合でも、
void
が必要
クロージャーを引数に渡す方法の違い
- 戻り値が
Void
の場合に詰まった。return null
が必要SampleViewItem.ktclass SampleViewItem( val onItemTapped: (Int) -> Unit, ) { val index = 1 fun onTapped() { onItemTapped(1) } }
JavaSample.javapublic class JavaSample { void setUp() { SampleViewItem sampleViewItem = new SampleViewItem((index) -> { handleTap(index); return null; // これが必要 }); } void handleTap(Integer index) { // 処理 } }
コンストラクタの定義方法
- Javaでは
constructor()
ではなく、クラス名()
で定義する
companion objectがない
- Javaでは
static
修飾子を付けたものになる
知っとくと良いもの
- kotlin -> binary -> javaへのデコンパイル方法