17 points par GN⁺ 2025-09-18 | 5 commentaires | Partager sur WhatsApp
  • Désormais, le premier programme Java ne commence plus forcément par public static void main(String[] args), et peut être écrit avec la syntaxe simplifiée void main()
  • Avec cette nouvelle syntaxe, de simples appels comme IO.readln et IO.println suffisent pour gérer les entrées/sorties, ce qui rend le code bien plus intuitif
  • Les formulations verbeuses comme new Scanner(System.in) ou System.out.println ne sont plus nécessaires
  • Ce désagrément est « enfin terminé » : la structure de base de Java devient plus légère, ce qui devrait abaisser la barrière d’entrée et améliorer nettement l’accessibilité à l’apprentissage

  • Traditionnellement, Java exigeait la longue déclaration public static void main(String[] args) pour démarrer un programme
  • Mais à la date du 16 septembre 2025, la déclaration complexe de la fonction main, longtemps considérée comme le tout premier exemple en Java, est remplacée par une nouvelle forme simplifiée
  • Ancienne manière :
    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);  
        }  
    }  
    
  • Nouvelle manière :
    void main() {  
        var name = IO.readln("What is your name? ");  
        IO.println("Hello, " + name);  
    }  
    
  • Cette syntaxe était souvent critiquée comme inutilement verbeuse pour les débutants, au point de devoir être mémorisée comme une « formule magique »
  • L’inconvénient et l’opacité de l’ancienne déclaration sont ainsi levés ; l’introduction d’une syntaxe concise améliore la lisibilité du code et abaisse fortement la barrière d’entrée pour débuter en Java
    • Les exemples de base n’utilisent plus la création d’objets et les appels complexes comme Scanner ou System.out.println

Good Fucking Riddance = « Enfin débarrassés. Bon débarras. »

5 commentaires

 
kayws426 2025-09-22

On dirait que dire qu’une nouvelle méthode est apparue revient à dire que l’ancienne est morte.
Est-il vraiment vrai qu’on ne peut plus utiliser la méthode existante et qu’il faut absolument utiliser la nouvelle ?

 
jhk0530 2025-09-19

Waouh

 
jwh926 2025-09-18

Faut que je réapprenne Java...

 
carnoxen 2025-09-18

Le main est mort. Vive le main !

 
GN⁺ 2025-09-18
Avis Hacker News
  • Avec le temps, je pense que ce processus par lequel on finit peu à peu par comprendre ce genre de code étrange va me manquer. Quand j’ai d’abord appris Python puis que je suis passé à Java, je trouvais fascinant de ne pas savoir ce que signifiaient des types comme void ou String[]. Puis j’ai appris les types et j’ai compris, ensuite les concepts de classe et d’objet, puis pourquoi main existe comme méthode static. En allant plus loin, j’ai aussi appris quand cette classe est appelée, et ce code qui me semblait au départ n’être qu’un simple boilerplate a commencé à avoir du sens. Un développeur Java expérimenté lirait sans doute encore plus de sens dans cette seule ligne que moi. Cela dit, je suis quand même soulagé que ça disparaisse enfin

    • Vraiment soulagé. Depuis 30 ans, l’enseignement du logiciel apprend aux développeurs, au nom de l’« ingénierie », à produire une complexité inutile. Par exemple, le développeur A crée des classes pour tout ce dont il a besoin, point d’entrée, callback, interface, etc. Résultat, on se retrouve avec des classes. Le développeur B ajoute des variables d’instance et rend l’ensemble mutable, ce qui crée un « bourbier d’implémentation ». Ensuite, un autre développeur ajoute de l’héritage pour réutiliser le code, ce qui introduit encore plus de complexité et des cauchemars de dispatch dynamique. Au final, on se retrouve avec des cycles de références qui emmêlent les relations entre objets. Avec le temps, le refactoring devient de plus en plus difficile et pénible, si bien qu’on finit par tout jeter et recommencer de zéro

    • Je me souviens que quand j’ai appris à programmer à l’université, en voyant ce code, le professeur m’avait dit : « Normalement je vous expliquerais tout le code, mais pour cette partie, acceptez-la d’abord telle quelle. » Plus tard, quand j’ai réalisé que je comprenais entièrement ce code, ça avait été une expérience assez satisfaisante. Mais maintenant que l’époque change, ça me soulage aussi

    • En réalité, les méthodes de classe static relèvent presque du déni de réalité : le point d’entrée unique d’un programme n’a pas forcément à être lié à une classe. Des langages comme C++, mais aussi Python ou Ruby, reconnaissent cette réalité procédurale ; Java donne plutôt l’impression de bander les yeux de l’utilisateur pour le forcer dans un « monde OOP parfait »

    • Ayant connu l’ancienne approche basée sur les classes, le nouveau style (comme les unnamed classes de Java 21) me soulève encore plus de questions. Je me demande si cela revient vraiment à transformer Java, supposé être un langage où « tout est objet », en langage procédural. Et si on a besoin d’arguments en ligne de commande, comment fait-on ? J’ai surtout évité Java donc je ne connais pas bien, mais c’est une vraie question

  • À l’époque de Java 1.2, on lisait l’entrée standard comme ceci. La classe Scanner m’est encore peu familière

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String input = in.readLine();
  • J’ai eu une expérience similaire. J’avais fait du Java il y a longtemps, donc le schéma public static void main m’était familier, mais l’usage de Scanner me paraissait étrange et je n’en comprenais pas exactement la raison

  • D’après mon expérience, comme je travaille depuis des décennies sur de gros projets, la façon dont la fonction main est écrite n’a absolument aucun impact sur mon quotidien ni sur ma carrière. Je me demande dans quelle mesure ce genre de changement a un impact réel pour vous

    • En tant que développeur Android, la notion même de main n’existait pas. Honnêtement, je ne pense pas que le fait qu’une implémentation triviale de Hello World soit laide soit un bon indicateur de la capacité du langage à bien gérer tout le reste

    • Beaucoup de gens ont débuté la programmation avec Java et ont tapé main des dizaines de fois sans avoir la moindre idée de ce que cela signifiait

    • Pour les développeurs en activité, l’impact est faible, mais pour les débutants c’est important. J’ai enseigné Java autrefois, et avant même d’afficher « Hello, World », le fait de devoir mémoriser cette formule magique de boilerplate constituait une barrière à l’entrée pour les étudiants

    • Cela peut avoir un impact si l’on crée une interface en ligne de commande, mais il n’est pas si fréquent de faire des CLI en Java

    • Ces cinq dernières années, je n’ai pas souvenir d’avoir vu main dans une codebase. Et plutôt que de créer directement de nouvelles classes, on implémente ou on étend le plus souvent des classes spécifiques à un framework

  • JEP 445: Unnamed Classes and Instance Main Methods est sorti avec Java 21
    https://openjdk.org/jeps/445

    • C’est dommage que cette fonctionnalité ait été conçue pour ne fonctionner qu’avec des programmes en un seul fichier. Si on avait permis des méthodes au niveau du package ou plusieurs classes/records dans un fichier, Java y aurait probablement gagné. Mais manifestement, ils ne voulaient pas d’impact sur « la manière générale d’écrire du code Java »
  • Il est étonnant de voir Java évoluer enfin, après 30 ans, en un langage plutôt correct

    • J’ai écrit beaucoup de code uniquement en Java et en C++, sans framework, et à cette époque il y avait bien moins de boilerplate et c’était beaucoup plus simple. Le moment où j’ai vraiment ressenti un gain de confort, c’était il y a une dizaine d’années avec l’ajout des lambdas. Après leur introduction, le volume de code a diminué et l’expérience est devenue bien plus agréable. Pendant longtemps, Java a été excessivement explicite, avec beaucoup de répétitions inutiles, comme si l’intérêt se limitait à vérifier les fautes de frappe sur des détails mineurs. C’était l’ambiance jusqu’à l’essor de Kotlin, puis avec les lambdas et les classes anonymes, l’expérience de développement s’est nettement améliorée

    • Dire que Java était un langage affreux est très exagéré

    • À l’inverse, je trouve qu’un langage comme Python reste encore inconfortable même après 30 ans

    • J’en déduis soit que vous n’avez jamais vraiment connu de très mauvais langages, soit que votre seuil pour « pas affreux » est extrêmement élevé

    • Malgré tout, Java reste impressionnant par son excellente compatibilité ascendante et son système de gestion de paquets

  • C’est un point déjà évoqué dans un commentaire précédent, mais en tant que développeur Java, Python me paraît au contraire plus étrange, sans que je trouve pour autant l’approche actuelle mauvaise. En revanche, se lancer directement dans la programmation sans comprendre les bases de l’abstraction n’en fait peut-être pas un bon choix pour une « introduction à la programmation ». Quand un outil est conçu avec une orientation but, paradigme, etc., il peut parfois pousser l’abstraction à l’extrême. Java a été conçu autour de l’OOP, donc une manière de penser en blocs comme les interfaces y vient naturellement. Les modificateurs d’accès des méthodes et des classes sont eux aussi clairement distingués selon leur destinataire (public, protected, défaut, private, etc.). Autrement dit, commencer avec Java, c’est commencer par l’exposition d’une interface vers l’utilisateur, c’est-à-dire le programmeur. Cela peut sembler étrange, mais au moins c’est cohérent

    • La lourdeur de la syntaxe n’a pas de lien direct avec l’OOP. Aucune définition de l’OOP antérieure à l’arrivée de Java ne disait que « les fonctions ne peuvent exister qu’à l’intérieur d’une classe ». Sun a longtemps refusé l’idée de fonctions autonomes (static import en Java 5, closures en Java 8, fichiers source compacts / instance main seulement maintenant), si bien que toutes les fonctions restent encore dans des classes — pour des raisons pratiques et de compatibilité, pas philosophiques. Ils ont voulu s’accrocher à l’idée que « tout est objet », tout en introduisant paradoxalement des valeurs primitives. Il n’y a aucun avantage pratique à imposer que les fonctions vivent dans des classes. Il aurait même été préférable de pouvoir définir des méthodes sur des valeurs comme les entiers. À titre de comparaison, dans un langage de « pure OOP » comme Smalltalk, on peut définir librement des fonctions hors des classes et exécuter directement du code dans un REPL
      Lien connexe

    • L’intérêt de Hello World, c’est qu’il permet de montrer en même temps le boilerplate nécessaire à l’exécution d’un programme et le vrai code qui affiche quelque chose. Et du point de vue de la configuration des outils de build, une partie de ce qu’on appelle « boilerplate » relève en fait d’une procédure de mise en place pour l’exercice ou l’outillage. Ce n’est pas un gros problème si on l’explique dès le départ

  • Si ce n’est qu’une astuce du compilateur qui génère une classe en interne, alors ce n’est qu’un changement cosmétique. Si les autres fonctions top-level restent interdites, cela ne reste qu’un cas particulier et c’est donc toujours maladroit

    • Depuis C# 9.0, C# prend en charge les top level statements, mais au final ils sont transformés en méthode statique en interne. Plusieurs fonctions top-level fonctionnent de façon similaire. Exemple concret : C# decompiled example
      Ce genre d’astuce est en réalité un exemple utile de transformation opérée par le compilateur (closures, machine à états async, etc.). Ce changement s’inscrit dans la même logique

    • En C/C++, le fait que return 0 soit implicite uniquement dans main() paraît lui aussi bizarre d’une manière similaire

    • Si seule main était autorisée comme fonction top-level, sans rien d’autre, je ne trouverais pas non plus que ce soit une très bonne évolution

  • Je ne comprends pas pourquoi, dans les exemples de code Java, on omet les lignes import. Si l’objectif est de montrer la complexité du boilerplate, il faudrait forcément afficher aussi les import

    • En général, l’IDE gère automatiquement les import, donc on n’y prête pas attention. Pour les classes liées aux entrées/sorties, dans un exemple compact, il n’y a de toute façon pas besoin d’import, donc le code fonctionne réellement tel quel

    • La plupart des IDE Java gèrent automatiquement les import

  • Si on abstrait le point d’entrée public static void main(String[] args) avec un paradigme de top-level statements comme en C#, on réduirait le boilerplate et le code serait plus concis. Je me demande pourquoi ils n’ont pas choisi cette voie

    • Voir le document Paving the on-ramp

    • Si le point d’entrée existe comme une exception spéciale, cela revient déjà à reconnaître les limites de l’OOP. Dans ce cas, ne vaudrait-il pas mieux assumer cela franchement et concevoir une nouvelle alternative ?

  • J’aime bien l’idée qu’avec l’approche des unnamed classes, il devienne plus facile d’implémenter des variables globales, de faire du hot reload, tout en simplifiant la syntaxe. En revanche, comme les fichiers Java doivent porter le même nom que la public class, on aurait peut-être simplement pu rendre la partie public class X { } optionnelle et ne l’écrire qu’en cas de besoin. Je ne comprends pas très bien pourquoi il fallait introduire des classes anonymes
    Le compilateur continue de toute façon à convertir cela en une classe comme HelloWorld.class, donc ce nom n’est qu’un détail d’implémentation et ne peut pas être utilisé directement dans le code source
    https://openjdk.org/jeps/445