Help us understand the problem. What is going on with this article?

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

プログラミング言語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) {

}
hituziando
Android/iOS developer, Front-end engineer, Rails engineer
https://hituzi-ando.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした