Je cherche une réponse définitive d'une source primaire ou secondaire pour savoir pourquoi (notamment) Java et C # ont décidé d'avoir une méthode statique comme point d'entrée, plutôt que de représenter une instance d'application par un instance d'une classe Application
(le point d'entrée étant un constructeur approprié).
Cela a déjà été demandé. Malheureusement, les réponses existantes sont simplement en posant la question . En particulier, les réponses suivantes ne me satisfont pas, car je les juge incorrectes:
Main
donc la même ambiguïté potentielle existe et est traitée.static
signifie qu'aucun objet ne peut être instancié avant donc l'ordre d'initialisation est clair. - Ceci est juste faux en fait, certains objets sont instanciés avant (par exemple dans un constructeur statique).Juste pour justifier davantage pourquoi je pense que c'est une question valable et intéressante:
De nombreux frameworks utilisent des classes pour représenter les applications et les constructeurs comme points d'entrée. Par exemple, le framework d'application VB.NET utilise une boîte de dialogue principale dédiée (et son constructeur) comme point d'entrée1.
Ni Java ni C # techniquement n'ont besoin d'une méthode principale. Eh bien, C # en a besoin d'une pour compiler, mais Java même pas cela. Et dans aucun cas, il n'est nécessaire pour l'exécution. Donc, cela ne semble pas être une restriction technique. Et, comme je l'ai mentionné dans le premier paragraphe, pour une simple convention, il semble étrangement inapproprié avec le principe de conception général de Java et C #.
Pour être clair, il n'y a pas d'inconvénient spécifique à avoir une méthode statique main
, c'est juste distinctement impair , ce qui m'a fait me demander s'il y avait une justification technique derrière cela.
Je suis intéressé par une réponse définitive d'une source primaire ou secondaire, pas de simples spéculations.
1 Bien qu'il y ait un rappel (Startup
) qui peut l'intercepter.
En Java, la raison de public static void main(String[] args)
est que
Pour C #, le raisonnement est transitoirement similaire pour ainsi dire. Les concepteurs de langage ont gardé la syntaxe point d'entrée du programme familière aux programmeurs venant de Java. Comme l'architecte C # Anders Hejlsberg le dit ,
... notre approche avec C # a simplement consisté à offrir une alternative ... aux programmeurs Java ...
étendre au-dessus et soutenu par des références ennuyeuses.
VM Spec, 2.17.1 Démarrage de la machine virtuelle
... La manière dont la classe initiale est spécifiée pour la machine virtuelle Java dépasse le cadre de cette spécification, mais il est typique, dans les environnements hôtes utilisant des lignes de commande, pour le nom complet de la classe à spécifier en tant qu'argument de ligne de commande et les arguments de ligne de commande suivants à utiliser comme chaînes à fournir comme argument de la méthode main. Par exemple, en utilisant le SDK Java 2 de Sun pour Solaris, la ligne de commande
Java Terminator Hasta la Vista Baby!
va démarrer une machine virtuelle Java en appelant la méthode main de la classe
Terminator
(une classe dans un package sans nom) et en lui passant un tableau contenant les quatre chaînes "Hasta", "la", "Vista" et "Baby!" ...
... voir aussi: Annexe: J'ai besoin de tes vêtements, de tes bottes et de ta moto
... qui permet d'éviter quelques fausses traces dans notre enquête.
Spécifications VM, 1.2 La machine virtuelle Java
La machine virtuelle Java ne sait rien du langage de programmation Java ...
J'ai remarqué ci-dessus en étudiant le chapitre précédent - 1.1 Histoire que je pensais être utile (mais qui s'est avéré inutile).
Sur la base de ce qui précède, j'ai commencé à rechercher sur le Web Historique JVM. N'a pas aidé, trop de déchets dans les résultats.
Ensuite, je me suis souvenu des légendes sur Gosling et j'ai restreint ma recherche à Historique de la JVM de Gosling.
Eureka! Comment les spécifications JVM sont apparues
Dans cette keynote du JVM Languages Summit 2008, James Gosling discute ... de la création de Java, ... d'un compromis entre le langage C et le langage de script ...
String[] args
static
et main
ne sont pas encore là, il faut creuser plus loin ...Remarquez en tapant ceci - connexion C, script et VM Spec 1.2 avec son rien de Java - je me sens comme quelque chose de familier, quelque chose ... orienté objet est lentement décès. Prends ma main et continue de bouger Ne ralentis pas, nous y sommes presque maintenant
Les diapositives des notes d'identification sont disponibles en ligne: 20_Gosling_keynote.pdf , très pratique pour copier des points clés.
page 3 La préhistoire de Java * Ce qui a façonné ma pensée page 9 NeWS * Système de fenêtres extensibles en réseau * Un système de fenêtres basé sur des scripts .... PostScript (!!) page 16 Un grand objectif (mais silencieux): Dans quelle mesure pourrais-je me rapprocher d'une sensation de "scripting" ... page 19 Le concept original * Il s'agissait de construire des réseaux de choses, orchestrés par un script langage * (Coques Unix, AppleScript, ...) page 20 Un loup en tenue de mouton * Syntaxe C pour rendre les développeurs Confortables
A-ha! Regardons de plus près syntaxe C.
L'exemple "bonjour le monde" ...
main() { printf("hello, world\n"); }
... une fonction nommée main est en cours de définition. La fonction main a une fonction particulière dans les programmes C; l'environnement d'exécution appelle la fonction principale pour commencer l'exécution du programme.
... La fonction principale a en fait deux arguments,
int argc
Etchar *argv[]
, Respectivement, qui peuvent être utilisés pour gérer les arguments de la ligne de commande ...
Sommes-nous en train de nous rapprocher? tu paries. Il vaut également la peine de suivre le lien "principal" de la citation ci-dessus:
la fonction principale est l'endroit où un programme commence son exécution. Il est responsable de l'organisation de haut niveau des fonctionnalités du programme et a généralement accès aux arguments de commande donnés au programme lors de son exécution.
main
.Class.main
EstLes lecteurs pensant que le point d'entrée de programme familier n'a pas d'importance sont aimablement invités à rechercher et vérifier les questions de débordement de pile où les gars venant de Java SE essaient d'écrire Bonjour tout le monde pour Java ME MIDP. Remarque point d'entrée MIDP n'a ni main
ni static
.
Sur la base de ce qui précède, je dirais que static
, main
et String[] args
Étaient aux moments de la création de [Java et C # les choix les plus raisonnables pour définir point d'entrée du programme .
Je dois admettre que la lecture de VM Spec 2.17.1 était très amusante.
... la ligne de commande
Java Terminator Hasta la Vista Baby!
va démarrer une machine virtuelle Java en appelant la méthode main de la classe
Terminator
(une classe dans un package sans nom) et en lui passant un tableau contenant les quatre chaînes "Hasta", "la", "Vista" et "Baby!".Nous décrivons maintenant les étapes que la machine virtuelle peut prendre pour exécuter
Terminator
, comme exemple des processus de chargement, de liaison et d'initialisation qui sont décrits plus loin dans les sections suivantes.La tentative initiale ... découvre que la classe
Terminator
n'est pas chargée ...Une fois que
Terminator
est chargé, il doit être initialisé avant que main puisse être invoqué, et un type (classe ou interface) doit toujours être lié avant d'être initialisé. La liaison (§2.17.3) implique la vérification, la préparation et (éventuellement) la résolution ...La vérification (§2.17.3) vérifie que la représentation chargée de
Terminator
est bien formée ...La résolution (§2.17.3) est le processus de vérification des références symboliques de la classe
Terminator
...
Références symboliques de Terminator
oh ouais.
Cela me semble vaguement abusif. Un constructeur est utilisé pour l'initialisation d'un objet: il configure un objet, qui est ensuite utilisé par le code qui l'a créé.
Si vous placez des fonctionnalités d'utilisation de base à l'intérieur du constructeur et que vous n'utilisez jamais réellement l'objet que le constructeur crée dans du code externe, vous violez les principes de la POO. Fondamentalement, faire quelque chose de vraiment bizarre sans raison apparente.
Pourquoi voudriez-vous faire cela de toute façon?
Pour Java je pense que le raisonnement est simple: lors du développement de Java, les développeurs savaient que la plupart des personnes apprenant le langage connaîtraient au préalable le C/C++.
Par conséquent Java ressemble non seulement beaucoup à C/C++ au lieu de dire Smalltalk, mais a également repris les idiosynchrasies de C/C++ (pensez simplement aux littéraux octaux entiers). Puisque c/c ++ utilisent tous deux un méthode principale, faire de même pour Java était logique de ce point de vue.
Je suis presque sûr de me souvenir de bloch ou de quelqu'un qui a dit quelque chose dans ce sens sur la raison pour laquelle ils ont ajouté des littéraux entiers octaux, je vais voir si je peux trouver des sources :)
Eh bien, il existe de nombreuses fonctions principales qui exécutent simplement une boucle infinie. Un constructeur travaillant de cette façon (avec un objet qui ne se construit jamais) est ce qui me semble étrange.
Il y a tellement de choses drôles sur ce concept. Votre logique qui court sur un objet à naître, des objets qui sont nés pour mourir (puisqu'ils font tout leur travail chez le constructeur), ...
Tous ces effets secondaires ne corrompraient-ils pas beaucoup plus le OO wagon qu'un simple public (car il doit être accessible par un inconnu)) statique (car aucune instance n'est nécessaire pour commencer) ) void main (parce que c'est le point d'entrée)?
Pour qu'un point d'entrée de fonction simple et simple existe en Java, public et statique seraient automatiquement requis. Bien qu'étant un méthode statique, cela se résume à ce que nous pouvons nous rapprocher d'une fonction simple pour accomplir ce que nous recherchons: un simple point d'entrée.
Si vous n'allez pas adopter un point d'entrée simple et simple comme point d'entrée. Quelle est la prochaine étape qui ne semble pas étrange en tant que constructeur qui n'est pas censé construire?
Vous pouvez rapidement exécuter des tests autonomes sur une classe, pendant le développement, en collant une main()
dans la classe que vous essayez de tester.
À ma connaissance, la raison principale est simple. Sun était une société Unix vendant des machines Unix et Unix est ce pour quoi le C "main (args)" convention pour invoquer un binaire a été conçu.
De plus Java a été explicitement conçu pour être facile à comprendre pour les programmeurs C et C++, il n'y avait donc aucune bonne raison de ne pas simplement se contenter de reprendre la convention C.
L'approche choisie où chaque classe peut avoir une méthode d'invocation est assez flexible, surtout en combinaison avec le Main-Class
line dans le fichier MANIFEST.MF dans un pot exécutable.
Vous devez commencer quelque part. Un environnement principal statique est l'environnement d'exécution le plus simple que vous puissiez avoir - aucune instance de quoi que ce soit (en dehors de la JVM et des paramètres de chaîne simples) ne doit être créée - afin qu'il puisse "arriver" avec un minimum de tracas (et une faible probabilité d'une erreur de codage empêchant le démarrage, etc.) et peut faire des choses simples sans beaucoup d'autres configurations.
Fondamentalement, une application de KISS.
[Et, bien sûr, la raison principale est: pourquoi pas?]