~/blog/2010/02/von-csharp-zu-java.md

Von C# zu Java: Was zuerst auffällt

3 min
Titelbild: Von C# zu Java: Was zuerst auffällt

Keine Zeit? Hier die Kurzversion in 30 Sekunden.

  • Die Syntax ist C# so ähnlich, dass man sich in den ersten Stunden fast zu Hause fühlt.
  • Properties, Delegates und LINQ gibt es in Java 6 nicht, dafür Getter/Setter, Interfaces und Schleifen.
  • Checked Exceptions zwingen zum Behandeln, Generics werden zur Laufzeit gelöscht (Type Erasure).
  • Pakete entsprechen Ordnern, Eclipse und Maven/Ant ersetzen Visual Studio und MSBuild.

Ich komme aus der PHP- und C#-Ecke und muss mich gerade in Java einarbeiten. Ein paar Dinge sind mir in den ersten Wochen aufgefallen, und weil ich das Gefühl habe, dass es anderen mit C#-Hintergrund ähnlich geht, schreibe ich sie mal auf. Vorweg: Das hier ist kein „Java ist schlechter“-Text. Es ist einfach anders, und manches ist erst mal ungewohnt.

Die Syntax: fast wie zu Hause

Eine Klasse mit main, geschweifte Klammern, Semikolons, for, if, try/catch. Wer C# kann, liest Java-Code vom ersten Tag an. Kleine Unterschiede gibt es trotzdem: string heißt String (und ist eine normale Klasse), bool heißt boolean, foreach ist ein for mit Doppelpunkt, und using für Namespaces heißt import.

for (String name : namen) {
    System.out.println(name);
}

Properties gibt es nicht

In C# 3.0 schreibe ich einfach das hier:

public string Name { get; set; }

In Java 6 gibt es dafür nichts Vergleichbares. Man schreibt ein privates Feld und zwei Methoden:

private String name;

public String getName() {
    return name;
}

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

Das ist mehr Tipparbeit. Eclipse generiert die Methoden per Menü, und es ist eine Konvention, die praktisch alle Bibliotheken kennen. Trotzdem vermisse ich die kurze Schreibweise.

Keine Delegates, kein LINQ

Das war für mich die größte Umstellung. Wo ich in C# einen Delegate oder ein Lambda übergebe, nimmt Java ein Interface und eine anonyme innere Klasse:

Collections.sort(namen, new Comparator<String>() {
    public int compare(String a, String b) {
        return a.length() - b.length();
    }
});

Für so eine Zeile Sortierung ist das ziemlich viel Text. Und LINQ? Gibt es nicht. Filtern, Gruppieren und Summieren schreibt man mit Schleifen und Hilfsvariablen aus, so wie ich es vor C# 3.0 auch gemacht habe. Man hört, dass in einer der nächsten Java-Versionen Closures kommen könnten, aber ob und wann, weiß ich nicht. Bis dahin lebe ich mit den inneren Klassen.

Checked Exceptions

In C# kann jede Methode jede Exception werfen, ohne dass der Compiler etwas sagt. In Java muss man bestimmte Exceptions entweder fangen oder mit throws deklarieren:

public String lese(String pfad) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(pfad));
    try {
        return reader.readLine();
    } finally {
        reader.close();
    }
}

Anfangs hat mich das genervt, weil man ständig try/catch schreibt. Andererseits sieht man an der Signatur sofort, was schiefgehen kann. Ich bin noch unentschlossen, ob mir das gefällt. Das finally entspricht übrigens dem, was ich in C# mit using mache, nur eben von Hand.

Generics und Type Erasure

Java hat Generics seit Version 5, aber sie funktionieren anders als in .NET. Die Typinformation wird nach dem Kompilieren gelöscht (Type Erasure). Zur Laufzeit ist eine List<String> einfach eine List. Konsequenzen: Man kann kein new T() schreiben, kein List<int> (nur List<Integer>) und auch kein x instanceof List<String>. In .NET sind Generics echte Typen, das ist eleganter, aber Java muss eben abwärtskompatibel bleiben.

Pakete, Werkzeuge, Build

Pakete sind in Java nicht nur ein Namensraum, sondern müssen der Ordnerstruktur entsprechen: de.beispiel.shop.Warenkorb liegt in de/beispiel/shop/Warenkorb.java, und pro Datei gibt es eine öffentliche Klasse. Das ist streng, aber man findet alles sofort.

Als Entwicklungsumgebung nutze ich Eclipse statt Visual Studio. Die Refactorings sind gut, und es kostet nichts. Ein bisschen eckiger fühlt es sich an, vor allem bei den vielen Fenstern („Perspektiven“). Gebaut wird mit Ant oder mit Maven. Ant ist eine XML-Datei mit Schritten, so ähnlich wie MSBuild-Skripte. Maven geht einen anderen Weg: Man beschreibt Projekt und Abhängigkeiten in der pom.xml, und die Bibliotheken werden automatisch geladen. Das gefällt mir bisher, auch wenn die Lernkurve steil ist.

Wie war es bei euch beim Umstieg? Welche Stolpersteine hattet ihr? Schreibt es in die Kommentare!

Beitragsbild: eigene Collage mit Logos von Wikimedia Commons (.NET Framework logo from 2002: Microsoft, gemeinfrei; Apache Maven logo: Apache Software Foundation, gemeinfrei); die Marken gehören ihren Inhabern.

$ whoami
Christian Ackermann

Softwareentwickler (C++, C, Java, C#) aus der Oberpfalz, bloggt seit 2001 über Linux, Technik und Kochen.