Stand: 2017-03-25

Java-Kotlin-Spickzettel

Java und Kotlin mit Code-Beispielen im direkten Vergleich nebeneinander

Inhalt

Anwendung definieren

JavaKotlin
public class MyApplication {
    public static void main(String... args) {
        ...
    }
}
fun main(args: Array<String>) {
    ...
}

In Kotlin können Funktionen direkt auf Paketebene, also außerhalb einer Klasse oder eines Objekts, definiert werden. Deshalb ist für die main-Methode auch keine nutzlose Klasse erforderlich.

Text ausgeben

JavaKotlin
System.out.println("Hallo Welt!");
println("Hallo Welt!")

Variablen und Werte definieren

JavaKotlin
int x = 5;
var x: Int = 5
var x = 5
final int y = 1;
val y: Int = 1
val y = 1

Variablen in Strings

JavaKotlin
String message = 
        String.format("a: %s, x: %s", a, b.x);

String message = “a: " + a + “x: " + b.x;

val message = “a: $a, x: ${b.x}“

In Kotlin können Variablen mit vorangestelltem $ direkt in Strings eingebettet werden; komplexe Ausdrücke wie b.x benötigen zusätzlich geschweifte Klammern.

Dokumentation: String Templates

Collections

JavaKotlin
String[] array = { "a", "b", "c"};
val array = arrayOf("a", "b", "c")
final List<String> list = 
    Arrays.asList("a", "b", "c");
val list = mutableListOf("a", "b", "c")
String item = list.get(1);
val item = list[1]
list.set(0, "x");
list[0] = "x"
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
val set = mutableSetOf("a", "b")
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
val map = mutableMapOf("a" to 1, "b" to 2)
Integer a = map.get("a");
val a = map["a"]
map.put("a", 9);
map["a"] = 9
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
Map<String, Integer> unmodifiableMap = 
    Collections.unmodifiableMap(map);
val unmodifiableMap = mapOf("a" to 1, "b" to 2)

Dokumentation: Collections

Streams

JavaKotlin
list.stream()
    .filter(it -> it.length() == 1)
    .map(String::toUpperCase)
    .collect(Collectors.toSet());
list
    .filter { it.length == 1 }
    .map(String::toUpperCase)
list.stream()
    .collect(Collectors.joining(", "));
list.joinToString(", ")
positions.stream()
    .mapToInt(Position::price)
    .sum();
list.sumBy { it.price }

Weitere Beispiele bei Stackoverflow.com

Bedingungen mit if

JavaKotlin
final String filename;
if (!args.isEmpty())
    filename = args.get(0);
else
    filename = "default.txt"
val filename = 
    if (!args.isEmpty) args[0] 
    else "default.txt"
String a = x < 1 ? "red" : "green";
val a = if (x < 1) "red" else "green"

Dokumentation: if

for-Schleife

JavaKotlin
for (MyItem item : collection) { ... }
for (item in collection) { ... }
for (int i = 0; i < array.size; i++) {
    System.out.println(array[i]);
}
for (i in array.indices) {
    println(array[i])
}
for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}
for (i in 1..10) {
    println(i)
}

Dokumentation: for

Schlüssel-Wert-Paare einer Map durchlaufen

JavaKotlin
for (Map.Entry<K,V> entry : map.entrySet()) {
  K key = entry.getKey();
  V value = entry.getValue();
  ...
}
for ((key, value) in map) {
   ... 
}

// oder map.forEach { (key, value) -> … }

Durch sogenannte “desctructuring declarations”, kann in Kotlin ein Map-Eintrag in Schlüssel und Wert zerlegt werden.

switch und when

JavaKotlin
  final Color color;
  switch (value) {
    case 0:
      color = Color.RED;
      break;
    case 1:
    case 2:
      color = Color.YELLOW;
      break;
    case 3:
      color = Color.GREEN;
      break;
    default:
    color = Color.GREY;
  }
val color = when(value) {
    0 -> Color.RED
    1, 2 -> Color.YELLOW
    3 -> Color.GREEN
    else -> Color.GREY
}

Dokumentation: when

Gleichheit

JavaKotlin
a.equals(b);
a == b
a == b;
a === b

Dokumentation: Equality

Methoden und Funktionen

JavaKotlin
public int calculate(final int a, final int b) {
    return a + b;
}
fun calculate(a: Int, b: Int) = a + b

fun calculate(a: Int, b: Int): Int { return a + b }

public void show(final String a) {
    System.out.println(a);
}
fun show(a: String) {
    println(a)
}

fun show(a: String): Unit { println(a) }

public void perform(String... args) { 
    ... 
}
fun perform(vararg args: String) {
    ...
}

Dokumentation: Functions

Lambdaausdrücke

JavaKotlin
IntToDoubleFunction square = 
      (int a) -> a * a;
val square =  { a: Int -> a * a }

val square: (Int) -> Int = { a: Int -> a * a }

Consumer<String> printer = 
      (String a) -> System.out.println(a);
val printer = { a: String -> println(a) }

val printer: (String) -> Unit = { a: String -> println(a) }

Consumer<String> printerWithMethodRef = 
      System.out::println;
val printerWithMethodRef = ::println

val printerWithMethodRef: (String) -> Unit = ::println

Runnable writer = () -> {
    System.out.println("start");
    System.out.println("end");
};
val writer: () -> Unit = {
    println("start")
    println("end")
}
public static void perform(
        IntToDoubleFunction square,
        Consumer printer,
        Runnable writer) {
    square.applyAsDouble(3);
    printer.accept("hi");
    writer.run();
}
fun perform(
        square: (Int) -> Int,
        printer: (String) -> Unit,
        writer: () -> Unit) {
    square(3)
    printer("hi")
    writer()
}

Dokumentation: Lambdas

Exception Handling

JavaKotlin
try {
    ...
} 
catch (SomeExcetion e) {
    ...        
}
finally {
    ...
}
try {
    ...
} 
catch (e: SomeExcetion) {
    ...        
}
finally {
    ...
}
final String a;
try {
    Path path = Paths.get("test.txt");
    a = Files.readAllLines(path).get(0);
} catch (final IOException e) {
    a = "default";
}
val a = try {
    val path = Paths.get("test.txt")
    Files.readAllLines(path)[0]
} catch (e: IOException) {
    "default"
}

Dokumentation: Exceptions

Sichtbarkeit

Dokumentation: Visibility Modifiers

Klassen

Deklaration und Vererbung

JavaKotlin
final class Square {}
class Square
class Square {}
open class Square
public class Square extends Shape {}
class Square : Shape()
public class Square implements Drawable
class Square : Drawable
public class Square extends Shape
        implements Drawable
class Square : Shape(), Drawable

Dokumentation: Classes and Inheritance

Konstruktoren

JavaKotlin
public class Square {
private final int length;
private final int area;

public Square(int length) {
    checkArgument(length > 0);
    this.length = length;
    this.area = length * length;
}

public int getLength() {
    return length;
}

public int getArea() {
    return area;
}

}

class Square(val length: Int) {

init {
    require(length > 0)
}

val area = length * length

}

JavaKotlin
public class Square extends Shape 
    implements Drawable {
private int length;
private int area;

public Square(int length) {
    checkArgument(length > 0);
    this.length = length;
    this.area = length * length;
}

public Square() {
    this(1);
}

public Square(Square blueprint) {
    this(blueprint.length);
}

public int getLength() {
    return length;
}

public int getArea() {
    return area;
}

}

class Square(val length: Int) :
Drawable, Shape() {

val area = length * length

constructor() : this(1)

constructor(blueprint: Square) : 
    this(blueprint.length)

init {
    require(length >= 0)
}

}

JavaKotlin
public class Square extends Shape {
    public Square(int length, Color color) {
        super(color);
    }
}
class Square(val length: Int, color: Color) : 
        Shape(color)
JavaKotlin
    class Service {
        private final Repository repository;
    @Inject
    public Service(Repository repository) {
        this.repository = repository;
    }
}</code></pre></td>
<td><pre><code>class Service @Inject constructor(
val repository: Repository)</code></pre></td>

Instantiierung

JavaKotlin
Square s = new Square(2);
val s = Square(2)

Objekte werden in Kotlin ohne das Schlüsselwort new erzeugt.

Getter/Setter und Properties

JavaKotlin
private String name = "nobody";

public void setName(final String name) { this.name = name; }

public String getName() { return name; }

var name = “nobody"
private String name = "nobody";

public String getName() { return name; }

val name = “nobody"
public boolean isEmpy() {
    return size == 0;
}
val isEmpty: Boolean
    get() = size == 0
public void setLength(int length) {
    if (length < 0)
        length = 0;
    else 
        this.length = length;
}

public int getLength() { if (length > MAX) return MAX; return length; }

var length: Int
get() = if (length > MAX) MAX else length
set(value) {
if (value < 0)
field = 0
else
field = value
}

Dokumentation: Properties

Statische Elemente

JavaKotlin
public class Rectangle {
    ...
    public static Rectangle createSquare(int l) {
        return new Rectangle(l, l);
    }
}
class Rectangle(
         val width: Int, val height: Int) {
    companion object {
        fun createSquare(l: Int) = 
            Rectangle(l, l)
    }
}
public class Math {
    public static int max(int a, int b) {
        return a > b ? a : b;
    }
}
fun max(a: Int, b: Int) = 
    if (a > b) a else b

Dokumentation: Companion Objects

Datenklassen

JavaKotlin
public final class Point {
private final int x;
private final int y;

public Point(int x, int y) {
    this.x = x;
    this.y = y;
}

public int getX() {
  return x;
}

public int getY() {
  return y;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) 
        return false;
    Point point = (Point) o;
    return x == point.x && y == point.y;
}

@Override
public int hashCode() {
    return Objects.hash(x, y);
}

}

data class Point(val x: Int, val y: Int)

Dokumentation: Data Classes

Enums

JavaKotlin
public enum Color {
    RED, YELLOW, GREEN
}
enum class Color {
    RED, YELLOW, GREEN
}
public enum Color {
RED(255, 0, 0),
YELLOW(255, 255, 0),
GREEN(0, 255, 0);

public final int r;
public final int g;
public final int b;

Color(int r, int g, int b) {
    this.r = r;
    this.g = g;
    this.b = b;
}

}

enum class Color(
val r: Int, val g: Int, val b: Int) {

RED(255, 0, 0),
YELLOW(255, 255, 0),
GREEN(0, 255, 0)

}

Dokumentation: Enum Classes

Annotationen

JavaKotlin
@Target(ElementType.TYPE)
@interface MyAnnotation {
    String value() default "";
    boolean enabled() default false;
}
@Target(AnnotationTarget.CLASS)
annotation class MyAnnoation(
        val value: String = "",
        val enabled: Boolean = false)
@MyAnnotation(value = "ok", enabled = true)
class Something { }
@MyAnnoation(value = "ok", enabled = true)
class Something

Dokumentation: Annotations

Schnittstellen

JavaKotlin
import static java.util.Arrays.stream;

public interface Something {

boolean canDo(String task);

void doIt(String task);

default void doForeach(
        final String ...tasks) {
    stream(tasks).forEach(this::doIt);
}

}

interface Something {

fun canDo(task: String): Boolean

fun doIt(task: String): Unit

fun doForeach(vararg tasks: String) {
    tasks.forEach { doIt(it) }
}

}

class SomethingConcrete implements Something {
@Override
public boolean canDo(String task) {
    ...
}

@Override
public void doIt(String task) {
    ...
}

}

class SomethingConcreteKt : SomethingKt {

override fun canDo(task: String): Boolean {
    ...
}

override fun doIt(task: String) {
    ...
}

}

Dokumentation: Interfaces

Delegation

JavaKotlin
public class Something implements SomeInterface {
private final SomeInterface part;

public Something(SomeInterface part) {
    this part = part;
}

public void show(String a) {
    part.show(a);
}

}

class Something(part: SomeInterface) :
SomeInterface by part

In Kotlin sorgt das Schlüsselwort by gefolgt von einer Referenz auf das Objekt, an das delegiert wird, dafür dass die nötigen Methoden erzeugt werden. Damit gibt es in Kotlin endlich eine komfortable Möglichkeit, um das Prinzip “composition over inheritance” umzusetzen.

Dokumentation: Delegation

Import

JavaKotlin
import java.nio.file.Paths;
import java.nio.file.Paths
import static java.util.Collections.max;
import java.util.Collections.max

Dokumentation: Packages

Typprüfung

JavaKotlin
a instanceof B
a is B

Dokumentation: is and !is Operartors

Typumwandlung (Cast)

JavaKotlin
B b = (B) a;
val b: B = a as B
final B b;
try {
    b = (B) a;
} catch (ClassCastException e) {
    // b bleibt null
}
val b: B? = a as? B

Dokumentation: Type Checks and Casts

null

JavaKotlin
public String a = null;
var a: String? = null
a.length();
a!!.length
int len = 0;
if (a != null)
    len =  a.length();
val len = if (a != null) a.length else 0

// oder val len = a?.length ?: 0

Dokumentation: Null Safety

Java automatisch in Kotlin konvertieren

IntelliJ IDEA kann Java auch automatisch in Kotlin konvertieren. Dazu kannst du im Menü “Code” den Eintrag “Konvert Java File to Kotlin File” auswählen.

Java automatisch in Kotlin konvertieren mit IntelliJ IDEA

In der Online-IDE, try.kotlinlang.org, gibt es am oberen Rand die Funktionalität “Convert from Java”, mit der sich mal schnell ein Code-Schnipsel übersetzen lässt.

Java online in Kotlin konvertieren auf try.kotlinlang.org

In jedem Fall sollte man aber noch mal einen kritischen Blick auf das Ergebnis werfen, denn bei sehr kompliziertem Code kann es auch schon mal zu kleinen Unstimmigkeiten kommen. Und manchmal kann man den erzeugten Kotlin-Code auch noch weiter vereinfachen.

Weitere Information