プログラミング言語Kotlinについて少し勉強したので、自分の備忘の為にもJavaとの比較付きでまとめています。
情報は適宜修正・追加する予定です。
*Kotlinのバージョンは1.1+、Javaのバージョンは7とします。
変数
Kotlin | Java |
---|---|
var a = 123 | int a = 123; |
Kotlinは型推論する言語です。明示的に型を付けるときは、
var a: Int = 123
のように変数名の後に:型
と書きます。
定数
Kotlin | Java |
---|---|
val NUM_MAX = 123 | final int NUM_MAX = 123; |
定数も変数と同様に型を省略できます。
Number
Kotlin | Java | bit | |
---|---|---|---|
Byte | byte | 8 | 123 |
Short | short | 16 | 123 |
Int | int | 32 | 123 |
Long | long | 64 | 123L |
Float | float | 32 | 123.4f, 123.4F |
Double | double | 64 | 123.4 |
2進数表記: 0b00001011
16進数表記: 0x0F
Boolean
Kotlin | Java |
---|---|
var b: Boolean = false | boolean b = false; |
true | true |
false | false |
&& | && |
|| | || |
! | ! |
String
Kotlin | Java |
---|---|
val str: String = "Hello" | String str = "Hello"; |
ビット演算子
Kotlin | Java |
---|---|
shl | << |
shr | >> |
ushr | >>> |
and | & |
or | | |
xor | ^ |
inv | ~ |
制御構文
if-else
Kotlin
var max: Int
if (a > b)
max = a
else
max = b
Java
int max;
if (a > b)
max = a;
else
max = b;
三項演算子
Kotlin
Kotlinには三項演算子はありません。が、if-elseを使って下記のように書けます。
val a = if (n > 0) x else y
上記は、
val a = if (n > 0) {
x
} else {
y
}
と書くこともできます。これはKotlinのif文は{}ブロックの最後の行の値を返す式として働くためのようです。
Java
int a = n > 0 ? x : y;
when
Kotlin
val x = 2
when (x) {
1 -> println("one")
2 -> println("two")
else -> println("otherwise")
}
// => "two"
val y = 2
when (y) {
1,2 -> println("one or two")
else -> println("otherwise")
}
// => "one or two"
Javaで言うところのswitch文。この他にもKotlin特有の書き方があります。
Java
int x = 2;
switch (x) {
case 1:
System.out.println("one");
break;
case 2:
System.out.println("two");
break;
default:
System.out.println("otherwise");
}
// => "two"
int y = 2;
switch (y) {
case 1:
case 2:
System.out.println("one or two");
break;
default:
System.out.println("otherwise");
}
// => "one or two"
for
Kotlin
for (i in 0..5) {
Log.d("TEST", "$i")
}
// => 0
// => 1
// => 2
// => 3
// => 4
// => 5
Java
for (int i = 0; i <= 5; ++i) {
Log.d("TEST", "" + i);
}
// => 0
// => 1
// => 2
// => 3
// => 4
// => 5
Kotlin
デクリメントの場合はdownTo
というちょっと馴染みのないキーワードを使います。
for (i in 5 downTo 0) {
Log.d("TEST", "$i")
}
// => 5
// => 4
// => 3
// => 2
// => 1
// => 0
Java
for (int i = 5; i >= 0; --i) {
Log.d("TEST", "" + i);
}
// => 5
// => 4
// => 3
// => 2
// => 1
// => 0
関数
Kotlin
fun add(a: Int, b: Int): Int {
return a + b
}
Java
int add(int a, int b) {
return a + b;
}
クラス
Kotlin
class User {
...
}
Java
class User {
...
}
コンストラクタ
Kotlin
class User(name: String) {
private val name = name
}
上記は以下のように書いても同義です。
class User(private val name: String) {
}
Java
class User {
private String name;
public User(String name) {
this.name = name;
}
}
上記の例はメンバ変数に値をセットするだけでしたが、コンストラクタ内で何か処理もしたい時はinit
を使います。
Kotlin
class User(private val firstName: String, private val lastName: String) {
private val fullName: String
init {
this.fullName = StringBuilder()
.append(firstName)
.append(" ")
.append(lastName)
.toString()
}
}
この場合は更に以下のように簡潔に書けます。
class User(private val firstName: String, private val lastName: String) {
private val fullName: String = StringBuilder()
.append(firstName)
.append(" ")
.append(lastName)
.toString()
}
Java
class User {
private String firstName;
private String lastName;
private String fullName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = new StringBuilder()
.append(firstName)
.append(" ")
.append(lastName)
.toString();
}
}
セカンダリコンストラクタ
2つ以上のコンストラクタを持つ場合は下記のように書けます。
Kotlin
class User(private val name: String) {
private var age:Int = 0
constructor(name:String, age:Int) : this(name) {
this.age = age
}
}
Java
class User {
private String name;
private int age;
public User(String name) {
this.name = name;
}
public User(String name, int age) {
this(name);
this.age = age;
}
}
抽象クラス
Kotlin
abstract class AbsPerson {
abstract fun setName(name: String)
}
class Person : AbsPerson() {
override fun setName(name: String) {
...
}
}
Java
abstract class AbsPerson {
abstract public void setName(String name);
}
class Person extends AbsPerson {
public Person() {
super();
}
@Override
public void setName(String name) {
...
}
}
継承
Kotlin
open class A {
open fun v() {}
}
class B() : A() {
override fun v() {}
}
Kotlinではデフォルトでfinal
クラス扱いになるようで、継承を可能にするためにはopen
キーワードを付ける必要があります。
また、メソッドをオーバーライド可能にするためにもopen
キーワードが必要です。
Java
class A {
void v() {}
}
class B extends A {
@Override
void v() {}
}
インタフェース
Kotlin
interface IChangeListener {
fun onChanged(newValue: Int)
}
Java
interface IChangeListener {
void onChanged(int newValue);
}
無名クラス (匿名クラス)
Kotlin
val hoge = Hoge()
hoge.setOnChangeListener(object : IChangeListener {
override fun onChanged(newValue: Int) {
// Something to do
}
})
class Hoge {
private var listener: IChangeListener? = null
fun setOnChangeListener(l: IChangeListener?) {
listener = l
}
}
Java
Hoge hoge = new Hoge();
hoge.setOnChangeListener(new IChangeListener() {
@Override
public void onChanged(int newValue) {
// Something to do
}
});
class Hoge {
private IChangeListener listener = null;
public void setOnChangeListener(IChangeListener l) {
listener = l;
}
}
アクセス修飾子
Kotlin | Java | 相違点 |
---|---|---|
public | public | - |
protected | protected | Kotlin: 継承していないと同一package内でも参照できない。 Java: 継承していなくても、同一packageなら参照可能。 |
private | private | Kotlin: インナークラスのprivate変数が参照できない。 java: インナークラスのprivate変数も参照できる。 |
internal | - | Kotlin: パッケージが違っても同じモジュール内なら参照可能。 |
アクセス修飾子を省略 | アクセス修飾子を省略 | Kotlin: publicと同じ。 Java: 同じパッケージ内なら参照可能。 |
Kotlinにおけるモジュールとは公式サイトから引用すると下記の通りです。
The internal visibility modifier means that the member is visible with the same module. More specifically, a module is a set of Kotlin files compiled together:
- an IntelliJ IDEA module;
- a Maven or Gradle project;
- a set of files compiled with one invocation of the Ant task.
クラスメソッド
Kotlin
Kotlinではstaticメソッドはありません。Companion Objectsという仕組みを使えば実現できますが、公式では下記のようにpackage-level functionで書くことを推奨しています。
package hoge.foo
// package-level function
fun doA() {
...
}
import hoge.foo.doA
class B {
fun doB() {
doA()
}
}
*staticメンバ変数も同様にpackage-levelに書くかCompanion Objectsを使います。
Java
package hoge.foo;
class A {
public static doA() {
...
}
}
import hoge.foo.A;
class B {
public void doB() {
A.doA();
}
}
Companion Objects
Companion Objectsは下記例のようにcompanion object {}
でメソッドや変数・定数を囲みます。
Kotlin
class Settings private constructor() {
var useTutorial = false
companion object {
private const val KEY_USE_TUTORIAL = "com.your.domain.USE_TUTORIAL"
private val instance = Settings()
fun getInstance(context: Context): Settings {
val sharedPref = PreferenceManager.getDefaultSharedPreferences(context)
instance.useTutorial = sharedPref.getBoolean(KEY_USE_TUTORIAL, true)
return instance
}
}
}
// 利用例
if (Settings.getInstance(context).useTutorial) {
...
}
Java
final class Settings {
private static final boolean KEY_USE_TUTORIAL = "com.your.domain.USE_TUTORIAL";
private static Settings instance = new Settings();
public boolean useTutorial = false;
private Settings() {
}
public static Settings getInstance(Context context) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
instance.useTutorial = sharedPref.getBoolean(KEY_USE_TUTORIAL, true);
return instance;
}
}
// 利用例
if (Settings.getInstance(context).useTutorial) {
...
}
列挙型(Enum)
Kotlin
enum class MessageLevel {
DEBUG, INFO, WARNING, ERROR
}
Java
enum MessageLevel {
DEBUG, INFO, WARNING, ERROR
}
Additional
ここからは、アレってKotlinではどうやって書くんだ? というTips的なものを書いていきます。
Class.class
Kotlin
MainActivity::class.java
Java
MainActivity.class
Activity.this
Kotlin
this@MainActivity
Java
MainActivity.this
BufferedReader
BufferedReaderクラスを使ってテキストを読み込む例です。
Kotlinではwhile ((line = reader.readLine()) != null)
のような記述ができないため、以下のようにすると良いです。
Kotlin
val reader = BufferedReader(InputStreamReader(inputStream))
val builder = StringBuilder()
try {
reader.readLines().forEach { builder.append(it) }
val str = builder.toString()
}
catch (e: IOException) {
}
Java
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
try {
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
String str = builder.toString();
}
catch (IOException e) {
}