Dienstag, 22. Mai 2012

Elefanten auf Java: Hallo Welt!

Eine einfache Ausgabe eines kurzen Textes, meist "Hallo Welt" ist der Klassiker um jede Sprache kurz vorzustellen.

Sehen wir uns das Beispiel aus dem letzten Beitrag an, dann stellen wir fest, dass Java viel mehr Code als PHP benötigt. Aber genaugenommen ist unser Beispiel auch unpassend.
Java ist eine sehr stark objektorientierte Sprache und wollen wir uns als PHP-Entwickler Java nähern, müssen wir genauso von objektorientiertem, nicht aber prozeduralem Code ausgehen.

Bauen wir ein solches “Hallo Welt” objektorientiert mit einer einfachen Klasse auf. Wir erschaffen ein Objekt davon, übergeben ein freudiges “Hallo Elefant” und rufen eine Methode des Objekts auf, die unseren Text ausgibt.

Um unseren Weg zu Java an dieser Stelle bewusst zu vereinfachen und uns von dem bekannten PHP-Code weiter an Java anzunähern, benennen wir den Konstruktor in PHP mit dem Namen der Klasse und nicht mit “__construct”, was zumindest aktuell in PHP ja noch erlaubt ist. Auch ist echo mit Klammern geschrieben, das ist nicht notwendig, aber genauso erlaubt.

<?php
/*
 * Der “Anfangsblock”:
 * Wir erschaffen ein neues Objekt und uebergeben einen 
 * Elefanten (wenigstens als Text) an dessen Konstruktor.
 * Dann lassen wir unser Objekt den Text ausgeben.
 */
$meinObjekt = new Ausgabe("Hallo Elefant");
$meinObjekt->ausgeben();

class Ausgabe
{
  //eine Objektvariable, als private nur im Objekt sichtbar
  private $nachricht = "";
  
  //der Konstruktor speichert den uebergebenen Text ab
  public function Ausgabe($wert) {
    $this->nachricht = $wert;
  }

  //eine einfache Ausgabe
  public function ausgeben() {
        echo($this->nachricht);
  }
}
?>

Sehen wir uns jetzt das gleiche in Java an. Auch hier machen wir einen Kunstgriff um uns PHP optisch stärker anzunähern: In Java werden Variablen eigentlich nicht mit einem “$” eingeleitet, es ist erlaubt, wird aber nicht gerne gesehen und sollte vermieden werden. In der wunderbaren Welt der Beispiele sei uns das aber dieses eine (und versprochen einzige) mal erlaubt.

public class Ausgabe {
 /*
  * Der “Anfangsblock”:
  * Wir erschaffen ein neues Objekt und uebergeben einen 
  * Elefanten (wenigstens als Text) an dessen Konstruktor.
  * Dann lassen wir unser Objekt den Text ausgeben.
  */
  public static void main(String[] $args) {
    Ausgabe $meinObjekt = new Ausgabe("Hallo Elefant");
    $meinObjekt.ausgeben();
  }
  
  //eine Objektvariable, als private nur im Objekt sichtbar
  private String $nachricht = new String();

  //der Konstruktor speichert den uebergebenen Text ab
  //KEIN void beim Konstruktor! Beliebte Fehlerquelle
  public Ausgabe(String $wert){
    this.$nachricht = $wert;
  }
  
  //eine einfache Ausgabe
  public void ausgeben(){
      System.out.println(this.$nachricht); 
  }
}
Das sieht doch ganz gut aus? Die Unterschiede zu objektorientiertem PHP sind relativ gering, auch wenn wir ein ganz klein wenig nachgeholfen haben.
In beiden Fällen haben wir die Objektvariable “$nachricht” als “private” deklariert. Dies hat keinen zwingenden Grund, dient mehr der Veranschaulichung für verschiedenen Code.

Unterschiede

Sehen wir uns nun die auffälligsten Unterschiede an, ohne sie an dieser Stelle erschöpfend zu behandeln.

Bei PHP werden die Methoden und Attribute eines Objekts mit “->” geschrieben, in Java genügt ein einfacher Punkt “.”. Das sollte leicht zu merken sein. Variablen werden in PHP mit einem “$” eingeleitet, in Java ist das syntaktisch zwar erlaubt, wird aber wie gesagt eigentlich nicht gemacht: Für Java vergessen wir das “$” also ab sofort, der entsprechende Java-Code ist zur Ansicht noch einmal korrekt am Ende des Beitrags zu sehen.

Variablen und Objekte müssen in Java vor einer Verwendung zwingend deklariert werden und zwar mit der expliziten Angabe ihres Typs, eine nachträgliche Änderung ist nicht mehr möglich. Da wir Variablen aber in einem eigenen Beitrag behandeln, belassen wir es vorerst damit.

Ach und nicht vergessen, die Datei muss bei Java analog dem Klassennamen zwingend "Ausgabe.java" benannt sein.

Das “public static void main(String[] args)”-Konstrukt

Für die einen ist es die normalste Sache der Welt, für die anderen zumindest ein Hindernis zum schnellen Verständnis: Java erlaubt keinen Code außerhalb von Klassen wie man es in der Welt der Skriptsprachen gewohnt ist. Man hat also das Problem, sich (vermeintlich) nirgends ein neues Objekt seiner Klassen erschaffen zu können.

Dafür gibt es den optionalen, statischen “main”-Block, der bei einem direkten Aufruf der Klasse [also einem Programmstart] angesprungen wird, ohne dass zuvor ein Objekt initialisiert wurde. In diesem “main”-Block kann man sich seine Objekte erschaffen - auch von der eigenen Klasse selbst.

Ein Umstand, der zumindest bei manchem Anfänger für etwas Stirnrunzeln sorgt. Natürlich gibt es viele, die das gut finden, schließlich kann man sich an alles gewöhnen, sogar an zu enge Schuhe. Immerhin steht Java in diesem Punkt nicht allein und sogar begründen kann man diese Vorgehensweise, was ich aber gerne anderen überlasse.

Abschließende Anmerkung zu “main”

Um bei einem Programmstart direkt aufgerufen werden zu können ist die “main” Funktion öffentlich und statisch [kann also ohne zuvor erschaffenes Objekt aufgerufen werden].
Der Part “String[] args” macht nichts anderes als alle eventuellen Kommandozeilenparameter entgegenzunehmen und in einem String-Array zur Verfügung zu stellen. Der Name “args” ist übrigens frei wählbar, auch wenn es gefühlt kein Programm auf dieser Erde gibt, das hier tatsächlich einen anderen Namen wählt.

Und “void”?

Jede Methode in Java, abgesehen von dem Konstruktor (bitte drei mal laut sprechen!), muss auf einen Rückgabetyp festgelegt werden. Dies hängt mit der strengen Typisierung von Java zusammen. An dieser Stelle sei nur so viel gesagt: “void” gibt an, dass die Methode gar keinen Wert, egal welchen Typs zurückliefert - manchmal muss man eben sogar das Nichtstun ankündigen.

Fazit

Elefanten sind dick und objektorientierte Elefanten bringen immer noch ein paar Kilo mehr auf die Waage. Wer sich von PHP kommend mit Java beschäftigt, muss natürlich von objektorientiertem PHP ausgehen, alles andere ist unsinnig. Wer objektorientiert in PHP programmiert, für den sind die Unterschiede zu Java erst einmal gar nicht mehr so groß. Die Betonung liegt auf “erst einmal”, denn es folgen ja noch einige Beiträge.

Wer das “$” vor den Variablen oder “__construct()” noch nie mochte, der wird sich in Java heimisch fühlen. Etwas wundern wird er sich vermutlich in Java über das Hilfskonstrukt der “main()”-Methode innerhalb der Klassen, die zum Starten des Programms vorgesehen sind und der strenge Umgang mit Variablen und Objekten.

Und hier wie versprochen noch einmal der vollständige, korrekte Java-Code:

public class Ausgabe {
  public static void main(String[] args) {
    Ausgabe meinObjekt = new Ausgabe("Hallo Elefant");
    meinObjekt.ausgeben();
  }

  private String nachricht = new String();

  public Ausgabe(String wert){
    this.nachricht = wert;
  }

  public void ausgeben(){
      System.out.println(this.nachricht); 
  }
}

...um noch zu danken

Ich möchte mich ganz herzlich bei Jan [Jan Bogutzki] und Daniel [Daniel Sentker] für die Durchsicht und die Kritik bedanken. Beide haben mich übrigens - sicher nicht ganz zu Unrecht - gewarnt die “Kunstgriffe” im Code von Java und PHP zu verwenden. Auch gab es nach Ihrer Durchsicht noch etliche Änderungen, so dass eventuelle Fehler oder Unstimmigkeiten von beiden gar nicht in aller Gänze gefunden werden konnten.

Wer sich übrigens als PHP-Entwickler noch einmal (oder erstmalig) mit der OOP unter PHP auseinandersetzen möchte, der sei als Tipp auf Daniels 3-teilige Einführung zu diesem Thema verwiesen.

1 Kommentar:

  1. Du könntest - um den Java Code mehr an PHP anzugleichen - auch noch ein static import für println verwenden. Dann ist der Unterschied zum echo noch etwas kleiner.
    Interessant ist übrigens das this in Java. Es gibt Entwickler die das immer benutzen, wenn sie auf ein Klassenattribute zugreifen und andere verzichten bewusst darauf, da Java das ja selbst korrekt auflösen kann (wenn man keine lokale Variable so nennt).

    AntwortenLöschen