17 Punkte von GN⁺ 2025-09-18 | 5 Kommentare | Auf WhatsApp teilen
  • Javas erstes Programm beginnt nun nicht mehr mit public static void main(String[] args), sondern kann mit der vereinfachten Syntax void main() geschrieben werden
  • In der neuen Syntax lassen sich Ein- und Ausgaben schon mit einfachen Aufrufen wie IO.readln und IO.println erledigen, wodurch der Code deutlich intuitiver wird
  • Bisher ausführliche Konstrukte wie new Scanner(System.in) oder System.out.println werden damit überflüssig
  • Das bisherige Ärgernis ist „endlich vorbei“; durch die leichtere Grundstruktur von Java werden die Einstiegshürde gesenkt und die Lernfreundlichkeit deutlich verbessert

  • Traditionell verlangte Java für den Programmstart die lange Deklaration public static void main(String[] args)
  • Mit Stand vom 16. September 2025 wird die komplexe Deklaration der main-Funktion, die als allererstes Java-Beispiel galt, durch eine neue einfache Form ersetzt
  • Bisherige Variante:
    public class Main {  
        public static void main(String[] args) {  
            Scanner scanner = new Scanner(System.in);  
            System.out.print("What is your name? ");  
            String name = scanner.nextLine();  
            System.out.println("Hello, " + name);  
        }  
    }  
    
  • Neue Variante:
    void main() {  
        var name = IO.readln("What is your name? ");  
        IO.println("Hello, " + name);  
    }  
    
  • Die Syntax stand lange in der Kritik, für Einsteiger unnötig ausführlich zu sein und wie ein „magischer Spruch“ auswendig gelernt werden zu müssen
  • Durch die Beseitigung der Umständlichkeit und Schwerfälligkeit der bisherigen Deklaration und die Einführung einer kompakten Syntax steigt die Lesbarkeit des Codes, und die Einstiegshürde für Java sinkt deutlich
    • Grundlegende Beispiele verwenden nicht länger komplexe Objekterzeugung und Aufrufe wie Scanner oder System.out.println

Good Fucking Riddance = „Endlich ist der Mist weg. Tschüss und weg damit.“

5 Kommentare

 
kayws426 2025-09-22

Es klingt so, als würde man sagen, die bisherige Methode sei tot, nur weil es nun eine neue Alternative gibt.
Stimmt es wirklich, dass die bisherige Methode nicht mehr verwendet werden kann und man zwingend die neue Methode nutzen muss?

 
jhk0530 2025-09-19

Wow

 
jwh926 2025-09-18

Muss ich Java wieder neu lernen …

 
carnoxen 2025-09-18

Die main ist tot. Lang lebe die main!

 
GN⁺ 2025-09-18
Hacker-News-Kommentare
  • Ich werde wohl vermissen, wie man mit der Zeit solche zunächst fremdartigen Codeschnipsel immer besser versteht. Als ich zuerst Python lernte und dann zu Java wechselte, fand ich es faszinierend, dass ich nicht wusste, was Typen wie void oder String[] eigentlich bedeuten. Als ich dann Typen gelernt hatte, verstand ich es, und danach kamen die Konzepte von Klassen und Objekten dazu sowie die Frage, warum main als statische Methode existiert. Als ich noch tiefer eingestiegen bin, lernte ich auch, wann diese Klasse überhaupt aufgerufen wird, und so ergab Code, der anfangs nur wie Boilerplate wirkte, nach und nach Sinn. Vermutlich kann ein erfahrener Java-Entwickler aus dieser einen Zeile noch viel mehr Bedeutung herauslesen als ich. Trotzdem bin ich erleichtert, dass das jetzt weg ist.

    • Ich bin wirklich erleichtert. In den letzten 30 Jahren hat die Softwareausbildung Entwicklern unter dem Etikett „Ingenieurswesen“ beigebracht, unnötige Komplexität zu erzeugen. Zum Beispiel erstellt Entwickler A je nach Bedarf Klassen für Entry Points, Callbacks, Interfaces oder was auch immer. Das Ergebnis: Wir haben Klassen. Entwickler B fügt Instanzvariablen hinzu und macht damit das Ganze veränderlich, wodurch ein „Morast der Implementierung“ entsteht. Danach fügt ein anderer Entwickler Vererbung hinzu, um Code wiederzuverwenden, was noch mehr Komplexität und Albträume mit dynamischem Dispatch erzeugt. Am Ende entstehen Referenzzyklen, und die Beziehungen zwischen Objekten verheddern sich. Mit der Zeit wird Refactoring immer schwieriger und lästiger, bis man den Code am Ende löscht und neu anfängt.

    • Ich erinnere mich, dass ich beim ersten Programmierkurs an der Uni diesen Code gesehen habe und der Professor sagte: „Normalerweise würde ich euch den ganzen Code erklären, aber diesen Teil müsst ihr erst mal einfach so akzeptieren.“ Später war es ein ziemlich cooles Gefühl, als mir klar wurde, dass ich diesen Code inzwischen vollständig verstehe. Trotzdem fühlt es sich gut an, dass sich die Zeiten jetzt offenbar ändern.

    • Tatsächlich kommen statische Klassenmethoden der Verweigerung gleich, die Realität anzuerkennen, dass ein einzelner Entry Point eines Programms nicht zwingend an eine Klasse gebunden sein muss. Es gibt ja nicht nur C++, sondern auch Sprachen wie Python und Ruby, die die prozedurale Realität akzeptieren. Java wirkt dagegen so, als würde man den Nutzern die Augen verbinden und sie in eine „perfekte OOP-Welt“ drängen.

    • Aus der Sicht von jemandem, der die alte klassenbasierte Art kennt, wirft der neue Stil (wie unnamed classes in Java 21) eher noch mehr Fragen auf. Ich frage mich wirklich, ob man das Java, in dem „alles ein Objekt“ ist, jetzt in eine prozedurale Sprache verwandelt hat. Wie macht man das denn, wenn man Kommandozeilenargumente braucht? Ich habe Java meist eher gemieden und kenne mich damit nicht besonders aus, aber das ist eine ernst gemeinte Frage.

  • Zu Zeiten von Java 1.2 hat man Standardeingaben so eingelesen. Die Scanner-Klasse ist für mich neu und ungewohnt.

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String input = in.readLine();
  • Ich hatte eine ähnliche Erfahrung. Da ich vor langer Zeit mit Java gearbeitet habe, war mir das Muster public static void main vertraut, aber die Verwendung von Scanner fühlte sich seltsam an, sodass ich nie ganz verstanden habe, warum.

  • Meiner Erfahrung nach arbeite ich seit Jahrzehnten in großen Projekten, daher hat es für meinen Alltag oder meine Karriere überhaupt keinen Einfluss, wie die main-Funktion geschrieben ist. Mich würde interessieren, wie stark sich so eine Änderung in der Praxis tatsächlich auswirkt.

    • Als Android-Entwickler gab es das Konzept von main für mich ohnehin nicht. Ehrlich gesagt glaube ich nicht, dass die Hässlichkeit einer trivialen Hello-World-Implementierung ein Maßstab dafür ist, wie gut eine Sprache alles andere behandelt.

    • Viele Leute sind mit Java ins Programmieren eingestiegen und haben main Dutzende Male getippt, ohne auch nur im Geringsten zu wissen, was das eigentlich bedeutet.

    • Für Praktiker im Beruf hat das keinen großen Einfluss, aber für Anfänger ist es ein wichtiges Thema. Ich habe früher Java unterrichtet, und die „magische Beschwörungsformel“ (Boilerplate), die man auswendig lernen musste, bevor man überhaupt „Hello, World“ ausgeben konnte, war für Studierende eine echte Einstiegshürde.

    • Wenn man eine Kommandozeilenschnittstelle baut, könnte es Auswirkungen haben, aber so oft baut man CLIs in Java auch nicht.

    • Ich habe in den letzten etwa fünf Jahren in keiner Codebase mehr main gesehen. Und statt selbst neue Klassen anzulegen, implementiert oder erweitert man meist eher frameworkspezifische Klassen.

  • JEP 445: Unnamed Classes and Instance Main Methods wurde in Java 21 veröffentlicht.
    https://openjdk.org/jeps/445

    • Schade ist nur, dass dieses Feature nur für Einzeldatei-Programme nutzbar ist. Wenn man Methoden auf Paketebene oder mehrere Klassen/Records in einer Datei erlauben würde, wäre Java wohl noch besser geworden. Aber offenbar wollte man ohnehin keinen Einfluss auf „die übliche Art, Java-Code zu schreiben“.
  • Es ist erstaunlich zu sehen, wie sich Java nach 30 Jahren endlich zu einer ziemlich ordentlichen Sprache entwickelt.

    • Ich habe viel Code ganz ohne Frameworks nur mit Java und C++ geschrieben, und damals war die Boilerplate deutlich geringer und einfacher. Wirklich bequem wurde es für mich erst, als vor etwa zehn Jahren Lambdas hinzukamen. Seit ihrer Einführung ist der Code kürzer geworden, und das Arbeiten fühlt sich deutlich angenehmer an. Java war lange Zeit extrem explizit, mit viel unnötiger Wiederholung, die selbst bei Kleinigkeiten wirkte, als würde sie nur Tippfehler prüfen. So war die Stimmung, bis Kotlin aufkam; danach haben Lambdas und anonyme Klassen das Entwicklungserlebnis stark verbessert.

    • Die Behauptung, Java sei eine schreckliche Sprache gewesen, ist stark übertrieben.

    • Andererseits finde ich, dass Sprachen wie Python selbst nach 30 Jahren noch unbequem sind.

    • Ich vermute, du hast entweder noch nie wirklich schlechte Sprachen erlebt, oder deine Schwelle für „nicht schrecklich“ liegt extrem hoch.

    • Trotzdem ist es beeindruckend, dass Java eine hervorragende Abwärtskompatibilität und ein Paketmanagementsystem hat.

  • Das knüpft an einen früheren Kommentar an: Als Java-Entwickler finde ich Python eher seltsam, aber ich halte den aktuellen Ansatz nicht für schlecht. Wenn man jedoch direkt mit dem Programmieren beginnt, ohne die Grundlagen von Abstraktion zu verstehen, ist es vielleicht keine gute Wahl für den „Einstieg ins Programmieren“. Wenn ein Werkzeug zielorientiert, paradigmenorientiert usw. entworfen wird, kann es manchmal zu extremer Abstraktion kommen. Java wurde mit Fokus auf OOP entworfen, daher ist blockweises Denken mit Bausteinen wie Interfaces ganz natürlich. Auch die Zugriffsmodifikatoren von Methoden/Klassen sind klar danach getrennt, für wen sie gedacht sind (public, protected, default, private usw.). Anders gesagt beginnt der Einstieg in Java mit der Offenlegung einer Schnittstelle gegenüber dem Nutzer (Programmierer). Das mag seltsam wirken, aber zumindest ist es konsistent.

    • Schwere Syntax hat mit OOP nicht direkt etwas zu tun. Keine Definition von OOP vor dem Erscheinen von Java hat gesagt: „Funktionen dürfen nicht außerhalb von Klassen existieren.“ Sun hat das Konzept eigenständiger Funktionen lange abgelehnt (statische Imports kamen mit Java 5, Closures mit Java 8, kompakte Quelldateien/Instance Main erst jetzt), und deshalb befinden sich bis heute alle Funktionen innerhalb von Klassen — aus praktischen und Kompatibilitätsgründen, nicht aus philosophischen. Man wollte auf „alles ist ein Objekt“ bestehen, führte dann aber widersprüchlich primitive Werte ein. Es gibt keinen praktischen Vorteil daraus, dass Funktionen zwingend innerhalb von Klassen stehen müssen. Im Gegenteil: Es wäre besser gewesen, wenn man Methoden auf Werten wie Ganzzahlen hätte definieren können. Übrigens kann man in „reinen OOP“-Sprachen wie Smalltalk Funktionen frei außerhalb von Klassen definieren und Code auch direkt im REPL ausführen.
      Verwandter Link

    • Hello World ist deshalb wichtig, weil man daran gleichzeitig die Boilerplate für die Programmausführung und den eigentlichen Ausgabecode zeigen kann. Auch in Bezug auf die Konfiguration von Build-Tools ist ein Teil davon nicht bloß „Boilerplate“, sondern eher eine Vorgehensweise für Übung und Tool-Setup. Wenn man das von Anfang an erklärt, ist es kein großes Problem.

  • Wenn intern per Compiler-Trick eine Klasse erzeugt wird, ist das letztlich nur eine kosmetische Änderung. Wenn keine anderen top-level-Funktionen erlaubt sind, bleibt es am Ende nur ein Sonderfall und wirkt weiterhin seltsam.

    • C# unterstützt seit 9.0 top-level statements, aber intern wird das am Ende ebenfalls in statische Methoden umgewandelt. Mehrere top-level-Funktionen funktionieren ähnlich. Ein echtes Beispiel: C# decompiled example
      Solche Tricks sind tatsächlich Beispiele für nützliche Compiler-Transformationen, etwa bei Closures oder Async-State-Machines. Diese Änderung ist also in derselben Kategorie.

    • In C/C++ wirkt es ähnlich seltsam, dass nur in main() implizit return 0 gilt.

    • Wenn nur main als top-level-Funktion erlaubt ist und sonst nichts, halte ich auch das nicht für eine besonders gute Änderung.

  • Ich verstehe nicht, warum man in Java-Codebeispielen die import-Zeilen weglässt. Wenn man die Komplexität der Boilerplate zeigen will, müsste man die Imports doch unbedingt mit angeben.

    • Normalerweise verwaltet die IDE die Imports automatisch, deshalb achtet man kaum darauf. Bei IO-Klassen braucht man in kompakten Beispielen ohnehin keinen separaten Import, daher funktioniert der Code tatsächlich genau so.

    • Die meisten Java-IDEs verwalten Imports automatisch.

  • Wenn man den Entry Point public static void main(String[] args) wie in C# hinter einem top-level-statement-Paradigma abstrahieren würde, könnte man Boilerplate reduzieren und den Code knapper machen. Ich frage mich, warum man das nicht so gemacht hat.

    • Sieh dir das Dokument Paving the on-ramp an.

    • Wenn der Entry Point als spezieller Ausnahmefall existiert, ist das im Grunde schon ein Eingeständnis der Grenzen von OOP. Dann wäre es vielleicht besser, mutig eine neue Alternative zu entwerfen.

  • Ich finde gut, dass sich mit dem unnamed-class-Ansatz globale Variablen leichter umsetzen lassen, Hot Reload möglich wird und die Syntax knapper ist. Gleichzeitig gibt es in Java die Einschränkung, dass eine Java-Datei denselben Namen wie die public class tragen muss; eigentlich hätte es doch gereicht, den Teil public class X { } optional zu machen und nur bei Bedarf zu schreiben. Ich verstehe nicht ganz, warum man dafür anonyme Klassen einführen musste.
    Der Compiler wandelt das ohnehin weiterhin in eine Klasse wie HelloWorld.class um, der Name ist also nur ein Implementierungsdetail und kann im eigentlichen Quellcode nicht direkt verwendet werden.
    https://openjdk.org/jeps/445