はじめてのKotlin。Javaと比較してみた

  • 25
    いいね
  • 2
    コメント

プログラミング言語Kotlinについて少し勉強したので、自分の備忘の為にもJavaとの比較付きでまとめています。
情報は適宜修正・追加する予定です。
*Kotolinのバージョンは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"

関数

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 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();
  }
}

ここからは、アレって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 {
    for (line in reader.readLines()) {
        builder.append(line)
    }

    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) {

}

使ってみた感想

Javaで書いたコードもそのままKotlinで使えるので言語間の障壁はほとんどなく、Javaで書いた過去の資産も再利用できるのが良いです。IntelliJ IDEAを使えばJavaコードをKotlinソースへコピペするだけで自動変換してくれるのもなかなか強力でした。