Frischer Wind in Java – Scala und Java 8 – Part I: Datenstrukturen

Einführung

Mit Java 8 halten viele neue Funktionen Einzug in die Sprache. Davon kommt einem einiges bekannt vor, wenn man sich die JVM-basierte Sprache Scala (http://www.scala-lang.org/) ein bisschen näher anschaut – ein guter Grund für mich, sich mit den Grundlagen von Scala zu beschäftigen. In dieser Serie sollen einige grundlegende Sprachfeatures an praxisnahen Beispielen vorgestellt werden und die Unterschiede zwischen Java 7, Java 8 und Scala herausgestellt.

In Teil I der Serie fangen wir an mit der Erstellung einer einfachen Datenstruktur an: Ein Kunde mit einem Namen.

Umsetzung in Java

public class Customer {
	public String name;

	public Customer(String name) {
		this.name = name;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Customer other = (Customer) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return name;
	}
}

Dies ist der Code in Java für eine Klasse mit einem öffentlich Feld namens name und den sinnvollerweise überschriebenen Methoden hashCode, equals und toString (wie von Eclipse generiert).

Umsetzung in Scala

case class Customer(name: String) {
	override def toString = name
}

Wieso bewirken diese wenige Zeilen Scala das gleiche wie mehr als zehnmal so viele Zeilen Java?

  • Die Parameterliste hinter dem Klassennamen (name: String) dient gleichzeitig als Parameterliste des Konstruktors sowie als Deklaration der Felder, die in der Klasse zur Verfügung stehen.
  • Durch die Verwendung von (val name: String) würde der Parameter name auch nach außen hin als unveränderliches Feld sichtbar sein.
  • Durch die Verwendung von (var name:String) würde der Parameter name nach außen hin als veränderliches Feld sichtbar sein.
  • Die Deklaration der Klasse mit case bewegt den Compiler, uns eine Menge Arbeit abzunehmen. Unter anderem werden automatisch die Funktionen hashCode, equals und toString generiert. Außerdem wird implizit vor die Klassenparameter ein val gesetzt, so dass sie nach außen hin sichtbar sind. (Eigentlich macht das case noch viel mehr – siehe http://www.scala-lang.org/old/node/107).
  • Das Einzige, was wir noch selbst machen müssen, ist die toString-Methode mit einem Inhalt unserer Wahl zu überschreiben – in diesem Fall einfach nur der Kundenname. Auch dazu ist aufgrund der einfachen Syntax nur eine kurze Zeile Code notwendig. Alles, was der Compiler sich aus dem Kontext erschließen kann, muss nicht angegeben werden: Rückgabetyp, das Schlüsselwort return, die leere Parameterliste und die Blockklammern fallen weg.

Dies soll als erster Eindruck der Sprache Scala ausreichen. Wir haben gesehen, wie leicht man Datenstrukturen in Scala als Klassen abbilden kann. Das Ziel ist klar erkennbar, alles Überflüssige wegzulassen und Boilerplate-Code zu vermeiden.

In den folgenden Teilen sollen insbesondere Sprachfeatures wie Streams vorgestellt werden und wie diese in Scala und Java 8 umgesetzt wurden.

Interessante Links zum Thema

http://www.scalatutorial.de/topic151.html#caseclass
Scala Tutorial Case-Class

http://www.scala-lang.org/old/node/107
Scala Language Documentation Case-Class

http://www.codecommit.com/blog/scala/case-classes-are-cool
Blogeintrag zu den Vorteilen (und Nachteilen) von Case-Classes

Leave a Reply