Pourquoi la méthode principale Java est-elle statique?
30 réponses
la méthode est statique car sinon il y aurait ambiguïté: quel constructeur devrait être appelé? Surtout si votre classe ressemble à ceci:
public class JavaClass{
protected JavaClass(int x){}
public void main(String[] args){
}
}
la JVM devrait-elle appeler new JavaClass(int)
? Que devrait-il passer pour x
?
dans la négative, la JVM devrait-elle instancier JavaClass
sans utiliser de méthode de constructeur? Je pense qu'il ne devrait pas, parce que ce sera spécial-cas votre classe entière - parfois, vous avez une instance qui n'a pas été initialisé, et vous devez les vérifier dans chaque méthode qui pourrait être appelé.
il y a tout simplement trop de cas de bord et d'ambiguïtés pour qu'il soit logique que la JVM doive instancier une classe avant que le point d'entrée ne soit appelé. C'est pourquoi main
est statique.
Je ne sais pas pourquoi main
est toujours marqué public
cependant.
C'est juste une convention. En fait, même le nom main(), et les arguments passés en sont purement convention.
quand vous utilisez java.exe (ou javaw dans.exe sur Windows), ce qui se passe vraiment est un couple D'appels Java Native Interface (JNI). Ces appels chargent la DLL qui est vraiment le JVM (c'est vrai-java.exe n'est pas la JVM). JNI est l'outil que nous utilisons quand nous avons à faire le pont entre le monde de la machine virtuelle, et le monde du C, C++, etc... L'inverse est également vrai - il n'est pas possible (du moins à ma connaissance) de faire fonctionner une JVM sans utiliser JNI.
en gros, java.exe est une application c super simple qui analyse la ligne de commande, crée un nouveau tableau de chaînes de caractères dans la JVM pour contenir ces arguments, analyse le nom de classe que vous avez spécifié comme contenant main (), utilise les appels JNI pour trouver la méthode main() elle-même, puis invoque la méthode main (), en passant dans le tableau de chaînes de caractères nouvellement créé comme paramètre. C'est très, très similaire à ce que vous faites lorsque vous utilisez reflection à partir de Java - il utilise juste des appels de fonction natifs nommés de façon confusante à la place.
Il serait parfaitement légal pour vous d'écrire votre propre version de java.exe (la source est distribué avec le JDK) et de le faire faire quelque chose d'entièrement différent. En fait, c'est exactement ce que nous faisons avec toutes nos applications Java.
chacune de nos applications Java possède son propre lanceur. Nous faisons principalement cela afin que nous obtenions notre propre icône et le nom du processus, mais il est devenu pratique dans d'autres situations où nous voulons faire quelque chose en plus de l'appel main() régulier pour mettre les choses en route (par exemple, dans un cas nous faisons de L'interopérabilité COM, et nous passons en fait une poignée COM dans main() au lieu d'un tableau de chaînes de caractères).
, et Donc, à long et court: la raison pour laquelle il est statique est b/c qui est pratique. La raison pour laquelle on l'appelle 'main' est qu'il devait y avoir quelque chose, et main() est ce qu'ils faisaient dans les vieux jours de C (et dans ces jours-là, le nom de la fonction était important). Je suppose que java.exe aurait pu vous permettre de juste spécifier un nom de méthode principale entièrement qualifié, au lieu de juste la classe (java com.mycompany.Foo.someSpecialMain)-mais cela rend juste plus difficile sur IDEs pour auto-détecter les classes "lancables" dans un projet.
la méthode main() En C++, C# et Java sont statiques car elles peuvent alors être invoquées par le moteur d'exécution sans avoir à instancier une instance de la classe mère.
Why public static void main (String[] args) ?
C'est ainsi que le langage Java est conçu et que la machine virtuelle Java est conçue et écrite.
Oracle Java Language Specification
Check out , Chapitre 12 l'Exécution de l'Article 12.1.4 Invoquer Test.main :
enfin, après achèvement de l'initialisation pour l'essai de classe (au cours de laquelle d'autres opérations de chargement, de liaison et d'initialisation peuvent avoir eu lieu), la méthode principale de L'essai est invoquée.
La méthode main doit être déclarée public, statique, et non avenu. Il doit accepter un seul argument qui est un tableau de chaînes. Cette méthode peut être déclarée comme
public static void main(String[] args)
ou
public static void main(String... args)
Oracle Java Virtual Machine Specification
Check out Chapitre 2 le Langage de Programmation Java Concepts - Section 2.17 Exécution :
la machine virtuelle Java commence l'exécution en invoquant la méthode main d'une classe spécifiée et en lui passant un seul argument, qui est un tableau de chaînes. Cela provoque la classe spécifiée à charger (§2.17.2), lié (§2.17.3) à d'autres types qu'il utilise, et initialisé (§2.17.4). La méthode principale doit être déclaré public, statique, et nul.
Oracle OpenJDK Source
télécharger et extraire le pot source et voir comment JVM est écrit, Vérifiez ../launcher/java.c
, qui contient le code C natif derrière la commande java [-options] class [args...]
:
/*
* Get the application's main class.
* ... ...
*/
if (jarfile != 0) {
mainClassName = GetMainClassName(env, jarfile);
... ...
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
... ...
/* Get the application's main method */
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
... ...
{ /* Make sure the main method is public */
jint mods;
jmethodID mid;
jobject obj = (*env)->ToReflectedMethod(env, mainClass,
mainID, JNI_TRUE);
... ...
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
ReportExceptionDescription(env);
goto leave;
}
/* Invoke main method. */
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
... ...
disons simplement que static
ne serait pas requis comme point d'entrée de la demande.
une classe d'application ressemblerait alors à ceci:
class MyApplication {
public MyApplication(){
// Some init code here
}
public void main(String[] args){
// real application code here
}
}
la distinction entre le code de constructeur et la méthode main
est nécessaire parce que dans OO parler un constructeur doit seulement s'assurer, qu'une instance est initialisé correctement. Après l'initialisation, l'instance peut être utilisée pour le "service." Mettre le code d'application complet dans le constructeur le gâcherait.
ainsi cette approche forcerait trois contrats différents sur la demande:
- Il y doit être un constructeur par défaut. Dans le cas contraire, la JVM ne saurait pas quel constructeur appeler et quels paramètres devraient être fournis.
- il doit être un
main
méthode 1 . Ok, ce n'est pas surprenant. - la classe ne doit pas être
abstract
. Dans le cas contraire, la JVM ne pourrait pas l'instancier.
par contre, l'approche static
n'exige que un contrat:
- il doit y avoir une
main
méthode 1 .
ici, ni abstract
ni les constructeurs multiples ne comptent.
depuis Java a été conçu pour être un langage simple pour l'utilisateur il n'est pas surprenant que le point d'entrée de l'application a également été conçu d'une manière simple en utilisant un contrat et non d'une manière complexe en utilisant trois contrats indépendants et fragiles.
S'il vous plaît noter: cet argument est pas à propos de la simplicité à l'intérieur de la JVM ou à l'intérieur de la JRE. Cet argument est sur la simplicité pour le utilisateur .
1 dans ce cas, la signature complète ne compte que pour un seul contrat.
si ce n'était pas le cas, quel constructeur devrait être utilisé s'il y en a plus d'un?
il y a plus d'informations sur l'initialisation et l'exécution des programmes Java disponibles dans le Java Language Specification .
parce que sinon, il faudrait une instance de l'objet à exécuter. Mais il doit être appelé à partir de zéro, sans construire d'abord l'objet, car c'est habituellement la tâche de la fonction main () (bootstrap), de parser les arguments et de construire l'objet, habituellement en utilisant ces arguments/paramètres de programme.
avant que la méthode principale ne soit appelée, aucun objet n'est instancié. Avoir le mot-clé statique signifie que la méthode peut être appelée sans créer d'objets en premier.
que signifie public static void main(String args[])
?
-
public
est un spécificateur d'accès qui signifie que n'importe qui peut y accéder/l'invoquer comme jvm(Java Virtual Machine. -
static
permet d'appelermain()
avant qu'un objet de la classe ait été créé. C'est nécessaire carmain()
est appelé par la JVM avant que tout objet ne soit fabriqué. Depuis qu'il est statique, il peut être directement invoquée par la classe.class demo { private int length; private static int breadth; void output(){ length=5; System.out.println(length); } static void staticOutput(){ breadth=10; System.out.println(breadth); } public static void main(String args[]){ demo d1=new demo(); d1.output(); // Note here output() function is not static so here // we need to create object staticOutput(); // Note here staticOutput() function is static so here // we needn't to create object Similar is the case with main /* Although: demo.staticOutput(); Works fine d1.staticOutput(); Works fine */ } }
de même, nous utilisons parfois des méthodes statiques pour des méthodes définies par l'utilisateur de sorte que nous n'ayons pas besoin de faire des objets.
-
void
indique que la méthodemain()
est déclarée ne retourne pas de valeur. -
String[] args
spécifie le seul paramètre de la méthodemain()
.args
- un paramètre qui contient un tableau d'objets du type de classeString
.
permettez-moi d'expliquer ces choses d'une manière beaucoup plus simple:
public static void main(String args[])
toutes les applications Java, sauf les applets, commencent leur exécution à partir de main()
.
Le mot-clé public
est un modificateur d'accès qui permet au membre d'être appelé de l'extérieur de la classe.
static
est utilisé parce qu'il permet d'appeler main()
sans avoir à instancier une instance particulière de cette classe.
void
, indique que main()
ne retourne aucune valeur.
Applets, midlets, servlets et haricots de divers types sont construits et ont ensuite des méthodes de cycle de vie fait appel à eux. Invoquant principal est tout ce qui est jamais fait à la classe principale, donc il n'est pas nécessaire pour qu'un état soit tenu dans un objet qui est appelé plusieurs fois. Il est tout à fait normal d'épingler main sur une autre classe (bien que ce ne soit pas une bonne idée), ce qui entraverait l'utilisation de la classe pour créer l'objet principal.
C'est juste une convention, mais probablement plus pratique que l'autre. Avec un main statique, tout ce que vous devez savoir pour invoquer un programme Java est le nom et l'emplacement d'une classe. Si ce n'était pas statique, vous auriez aussi à savoir instancier cette classe, ou exiger que la classe ait un constructeur vide.
Si la méthode ne serait pas statique, vous devez créer un objet de votre classe principale de l'extérieur du programme. Comment tu voudrais faire ça?
lorsque vous exécutez la machine virtuelle Java (JVM) avec la commande java
,
java ClassName argument1 argument2 ...
lorsque vous exécutez votre application, vous spécifiez son nom de classe comme argument à la commande java, comme ci-dessus
la JVM tente d'invoquer la méthode principale de la classe que vous spécifiez
- à ce point, aucun objet de la classe n'a été créé.
déclarant
main
comme statiqueallows
la JVM àinvoke
principalwithout
création uninstance
de la classe.
revenons à la commande
ClassName
est un command-line argument
pour la JVM qui lui indique quelle classe exécuter. Suivant le nom de la classe, vous pouvez également spécifier un list of Strings
(séparé par des espaces) comme argument de ligne de commande que la JVM passera à votre application. - De tels arguments pourraient être utilisés pour spécifiez les options (par exemple, un nom de fichier) pour exécuter l'application - c'est pourquoi il y a un paramètre appelé String[] args
dans le main
, Les Références: Java™ Comment Le Programme (Début Objets), La Dixième Édition De
je pense que le mot-clé 'static' fait de la méthode principale une méthode de classe, et les méthodes de classe ont seulement une copie de celui-ci et peuvent être partagés par tous, et aussi, il ne nécessite pas un objet de référence. Ainsi, lorsque la classe driver est compilée, la méthode principale peut être invoquée. (Je suis juste dans l'alphabet, niveau de java, désolé si je me trompe)
main () est statique parce que; à ce point dans le cycle de vie de l'application, la pile de l'application est de nature procédurale en raison de l'absence d'objets encore instanciés.
C'est une ardoise propre. Votre application est en cours d'exécution à ce point, même sans aucun objet déclaré (rappelez-vous, Il ya des procédures et des modèles de codage OO). Vous, en tant que développeur, transformez l'application en une solution orientée objet en créant des instances de vos objets et en fonction de le code compilé à l'intérieur.
orienté objet est grand pour des millions de raisons évidentes. Cependant, le temps où la plupart des développeurs de VB utilisaient régulièrement des mots-clés comme "goto" dans leur code est révolu. "goto" est une commande de procédure en VB qui est remplacée par son pendant OO: l'invocation de méthode.
vous pouvez aussi considérer le point d'entrée statique (main) comme une pure liberté. Si Java avait été assez différent pour instancier un objet et ne présenter que cette instance pour vous en cours, vous n'auriez pas d'autre choix que d'écrire une application de procédure. Aussi inimaginable que cela puisse paraître pour Java, il est possible qu'il existe de nombreux scénarios qui nécessitent des approches procédurales.
c'est probablement une réponse très obscure. Rappelez-vous, "classe" est seulement une collection de code inter-liés. "Instance" est une génération autonome isolée, vivante et respirante de cette classe.
le prototype public static void main(String[])
est une convention définie dans le JLS :
la méthode main doit être déclarée publique, statique et nulle. Il doit spécifier un paramètre formel (§8.4.1) dont le type déclaré est array of String.
dans la spécification JVM 5.2. Démarrage d'une Machine virtuelle nous pouvons lire:
la machine virtuelle Java démarre par la création d'une classe initiale, qui est spécifiée de manière dépendante de l'implémentation, en utilisant le chargeur de classe bootstrap (§5.3.1). La machine virtuelle Java relie alors la classe initiale, l'initialise et invoque la méthode de classe publique void main(String[]) . L'invocation de cette méthode entraîne toute exécution ultérieure. L'exécution des instructions de la machine virtuelle Java constituant la méthode principale peut causer la liaison (et par conséquent la création) de classes et interfaces, ainsi que l'invocation de méthodes supplémentaires.
chose drôle, dans la spécification JVM il n'est pas mentionné que la méthode principale doit être statique. Mais la spécification dit aussi que la machine virtuelle Java effectuer 2 étapes avant :
- relie la classe initiale ( 5.4. Linking )
- l'initialise ( 5.5. Initialisation )
L'initialisation d'une classe ou d'une interface consiste à exécuter sa méthode d'initialisation de classe ou d'interface.
Dans 2.9. Méthodes Spéciales :
Un de la classe ou de l'interface de l'initialisation de la méthode est défini :
une classe ou une interface a au plus une méthode d'initialisation de classe ou d'interface et est initialisée (§5.5) en invoquant cette méthode. La méthode d'initialisation d'une classe ou d'une interface a le nom spécial
<clinit>
, ne prend aucun argument, et est nulle.
et une méthode d'initialisation de classe ou d'interface est différente d'une méthode d'initialisation d'instance définie comme suit:
Au niveau de la machine virtuelle Java, chaque constructeur écrit en Java le langage de programmation (JLS §8.8) apparaît comme une méthode d'initialisation d'instance qui a le nom spécial
<init>
.
ainsi la JVM initialise une méthode d'initialisation de classe ou d'interface et non une méthode d'initialisation d'instance qui est en fait un constructeur. Ils n'ont donc pas besoin de mentionner que la méthode principale doit être statique dans le spec JVM parce qu'il est implicite par le fait qu'aucune instance ne sont créé avant d'appeler la méthode principale.
récemment, une question similaire a été posée aux programmeurs.SE
- pourquoi une méthode principale statique en Java et C#, plutôt qu'un constructeur?
recherchant une réponse définitive à partir 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 une instance d'une classe
Application
, avec le point d'entrée étant un constructeur approprié?
TL;DR une partie de la accepté réponse est,
en Java, la raison de
public static void main(String[] args)
est que
- Gosling wanted
- le code écrit par quelqu'un expérimenté en C (pas en Java)
- à exécuter par quelqu'un utilisé pour exécuter PostScript sur Nouvelles
Pour le C#, le raisonnement est transitivement similaires pour ainsi dire. Les concepteurs de langage ont gardé la syntaxe du point d'entrée du programme familière pour les programmeurs venant de Java. Comme l'architecte Anders Hejlsberg le dit ,...notre approche avec C# a simplement été d'offrir une alternative... aux programmeurs Java...
...
C'est juste une convention. La JVM aurait certainement pu traiter de méthodes principales non statiques si cela avait été la convention. Après tout, vous pouvez définir un initialiseur statique sur votre classe, et d'instancier un tas d'objets avant même d'arriver à votre méthode main ().
le point d'entrée véritable de toute application est une méthode statique. Si le langage Java supporte une méthode d'instance comme "point d'entrée", alors l'exécution devra l'implémenter en interne comme une méthode statique qui construit une instance de l'objet suivie d'appeler la méthode d'instance.
cela dit, j'examinerai la raison d'être du choix d'une des trois options suivantes:
- A
static void main()
comme nous le voyons aujourd'hui. - Une méthode d'instance
void main()
appelé fraîchement objet construit. - en utilisant le constructeur d'un type comme point d'entrée (par exemple, si la classe d'entrée était appelée
Program
, alors l'exécution se composerait effectivement denew Program()
).
ventilation:
static void main()
- appelle le constructeur statique de la classe englobante.
- appelle la méthode statique
main()
.
void main()
- désigne le constructeur statique de la classe enveloppante.
- construit une instance de la classe enveloppante en appelant effectivement
new ClassName()
. - appelle la méthode d'instance
main()
.
new ClassName()
- désigne le constructeur statique de la classe enveloppante.
- Construit une instance de la classe (puis ne fait rien avec elle et retourne simplement).
Justification:
j'irai dans l'ordre inverse pour celui-ci.
gardez à l'esprit que L'un des objectifs de conception de Java était de mettre l'accent (exiger lorsque possible) de bonnes pratiques de programmation orientée objet. Dans ce contexte, l' constructeur d'un objet initialise l'objet, mais ne devrait pas être responsable du comportement de l'objet. Par conséquent, une spécification qui donne un point d'entrée de new ClassName()
pourrait créer de la confusion pour les nouveaux développeurs Java en forçant une exception à la conception d'un constructeur "idéal" sur chaque application.
en faisant de main()
une méthode d'instance, le problème ci-dessus est certainement résolu. Toutefois, il crée de la complexité en exigeant la spécification pour lister la signature du constructeur de la classe d'entrée ainsi que la signature de la méthode main()
.
en résumé, spécifier un static void main()
crée une spécification avec le moins de complexité tout en adhérant au principe de placer le comportement dans les méthodes . Considérant à quel point il est simple d'implémenter une méthode main()
qui elle-même construit une instance d'une classe et appelle une méthode d'instance, il y a aucun avantage réel à spécifier main()
comme méthode d'instance.
le mot-clé public
est un modificateur d'accès, qui permet au programmeur de contrôler
la visibilité des membres de la classe. Lorsqu'un membre de la classe est précédé par public
, alors que
le membre peut être accédé par code en dehors de la classe dans laquelle il est déclaré.
le contraire de public
est private
, ce qui empêche un membre d'être utilisé par un code défini à l'extérieur de sa classe.
dans ce cas, main()
doit être déclaré public
, car il doit être appelé
par code en dehors de sa classe lorsque le programme est démarré.
le mot-clé static
permet
main()
d'être appelé sans avoir à instancier une instance particulière de la classe. Ceci est nécessaire car main()
est appelé par L'interpréteur Java avant que tout objet ne soit créé.
le mot-clé void
indique simplement au compilateur que main()
ne renvoie pas de valeur.
statique-lorsque le JVM fait appel à la méthode principale, il n'y a pas d'objet qui existe pour la classe étant appelée, il doit donc avoir une méthode statique pour permettre l'invocation de la classe.
Je ne sais pas si la JVM appelle la méthode principale avant que les objets ne soient instanciés... Mais il y a une raison beaucoup plus puissante pour laquelle la méthode principale() est statique... Quand JVM appelle la méthode principale de la classe (par exemple, personne). il l'invoque par personne.main () ". Vous voyez, le JVM l'invoque par le nom de classe. C'est pourquoi la méthode main() est censée être statique et publique afin qu'elle puisse être utilisée par la JVM.
J'espère que ça a aidé. Si il n', laissez-moi savoir en commentant.
les méthodes statiques ne nécessitent aucun objet. Il fonctionne directement donc principal s'exécute directement.
le mot clé statique dans la méthode principale est utilisé parce qu'il n'y a aucune instanciation qui a lieu dans la méthode principale. Mais l'objet est construit plutôt que l'invocation comme résultat nous utilisons le mot clé statique dans la méthode principale. Dans le contexte jvm, la mémoire est créée lorsque la classe s'y Charge.Et tous les membres statiques sont présents en mémoire. si nous rendons le principal statique maintenant, il sera en mémoire et peut être accessible à jvm (class.principal.(.)) de sorte que nous pouvons appeler la méthode principale sans besoin de même le besoin de tas a été créé.
C'est juste une convention comme nous pouvons le voir ici:
La méthode doit être déclarée publique et statique , il ne doit pas retourner tout valeur, et il doit accepter un tableau de Chaîne comme paramètre. Par défaut, le premier non-argument est le nom de la classe à être invoqué. Un nom de classe complet doit être utilisé. Si l'-jar option est spécifié, le premier argument non-option est le nom d'une archive JAR contenant de la classe et des fichiers de ressources pour l'application, à l' classe de démarrage indiquée par l'en-tête manifeste de la classe principale.
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html#description
les mots-clés publics statiques signifient que L'interpréteur Java virtual machine (JVM) peut appeler la méthode principale du programme pour démarrer le programme (public) sans créer d'instance de la classe (static), et que le programme ne renvoie pas de données à L'interpréteur Java VM (void) lorsqu'il se termine.
Source: Essentials, Partie 1, Leçon 2: Création D'Applications
Fondamentalement, nous rendons les membres de données et les fonctions de membre comme statiques qui n'accomplissent aucune tâche liée à un objet. Et dans le cas de la méthode principale, nous la faisons comme statique parce qu'elle n'a rien à voir avec l'objet, car la méthode principale tourne toujours que nous créions un objet ou non.
toute méthode déclarée comme statique en Java appartient à la classe elle-même .
Là encore, la méthode statique d'une classe particulière n'est accessible qu'en se référant à la classe comme Class_name.method_name();
ainsi une classe n'a pas besoin d'être instanciée avant d'accéder à une méthode statique.
ainsi la méthode main() est déclarée comme static
de sorte qu'elle puisse être accessible sans créer un objet de cette classe.
puisque nous sauvons le programme avec le nom de la classe dans laquelle la méthode principale est présente( ou à partir de laquelle le programme doit commencer son exécution, applicable aux classes sans méthode main()
() (niveau élevé)). Ainsi, par la voie mentionnée ci-dessus:
Class_name.method_name();
la méthode principale est accessible.
en bref quand le programme est compilé il recherche la méthode main()
ayant String
arguments comme: main(String args[])
dans la classe mentionnée(c.-à-d. par le nom de la programme), et puisque au début il n'y a pas de possibilité d'instancier cette classe, ainsi la méthode main() est déclarée comme statique.
il y a la raison simple derrière cela qui est parce que l'objet n'est pas nécessaire d'appeler la méthode statique , si elle était la méthode non-statique, la machine virtuelle java crée d'abord l'objet puis appelle la méthode main() qui conduira au problème de l'allocation de mémoire supplémentaire.