Question Pourquoi la méthode principale de Java est-elle statique?


La signature de méthode d'un Java principale() La méthode est:

public static void main(String[] args){
    ...
}

Y a-t-il une raison pour que cette méthode soit statique?


440


origine


Réponses:


La méthode est statique car sinon il y aurait une 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){
  }
}

L'appel JVM devrait-il new JavaClass(int)? Que devrait-il passer pour x?

Si non, l'instanciation de la JVM JavaClass sans exécuter de méthode constructeur? Je pense que ce ne devrait pas être le cas, parce que cela s'appliquera à toute la classe - parfois vous avez une instance qui n'a pas été initialisée, et vous devez la vérifier dans toutes les méthodes qui pourraient être appelées.

Il y a juste trop de cas et d'ambiguïtés pour que la JVM ait besoin d'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 bien que.


296



Ceci est juste la convention. En fait, même le nom main () et les arguments transmis sont purement conventionnels.

Lorsque vous exécutez java.exe (ou javaw.exe sous Windows), ce qui se passe réellement est un couple d'appels Java Native Interface (JNI). Ces appels chargent la DLL qui est vraiment la JVM (c'est vrai - java.exe n'est pas la JVM). JNI est l'outil que nous utilisons lorsque nous devons relier 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) d'obtenir réellement un JVM en cours d'exécution sans utiliser JNI.

Fondamentalement, java.exe est une application C super simple qui analyse la ligne de commande, crée un nouveau tableau String 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 le La méthode main () elle-même, puis appelle la méthode main (), en transmettant le tableau de chaînes nouvellement créé en tant que paramètre. C'est très, très semblable à ce que vous faites lorsque vous utilisez la réflexion de Java - il utilise simplement des appels de fonctions natives nommées de manière confuse.

Il serait parfaitement légal pour vous d'écrire votre propre version de java.exe (la source est distribuée avec le JDK) et de faire quelque chose de complètement différent. En fait, c'est exactement ce que nous faisons avec toutes nos applications basées sur Java.

Chacune de nos applications Java possède son propre lanceur. Nous faisons cela principalement pour obtenir notre propre icône et nom de processus, mais cela est utile dans d'autres situations où nous voulons faire autre chose que l'appel principal main () pour faire avancer les choses (par exemple, dans un cas nous faisons Interopérabilité COM, et nous passons en fait un handle COM dans main () au lieu d'un tableau de chaînes).

Donc, long et court: la raison pour laquelle il est statique est b / c c'est pratique. La raison pour laquelle ça s'appelle 'main' est que ça doit être quelque chose, et main () c'est ce qu'ils faisaient dans l'ancien temps de C (et à cette époque, le nom de la fonction était important). Je suppose que java.exe aurait pu vous permettre de spécifier simplement un nom de méthode principal complet, au lieu de juste la classe (java com.mycompany.Foo.someSpecialMain) - mais cela rend plus difficile pour les IDEs de détecter automatiquement les ' classes de lancement dans un projet.


350



La méthode main () en C ++, C # et Java est statique car ils peuvent être invoqués par le moteur d'exécution sans avoir à instancier une instance de la classe parente.


172



Pourquoi le principal vide statique public (String [] args)?

Voici comment Java Language est conçu et Java Virtual Machine est conçu et écrit.

Oracle Java Langage Spécification

Check-out Chapitre 12 Exécution - Section 12.1.4 Invoke Test.main:

Enfin, après l'achèvement de l'initialisation pour le test de classe (au cours duquel d'autres opérations de chargement, de liaison et d'initialisation consécutives peuvent avoir eu lieu), la méthode main of Test est invoquée.

La méthode main doit être déclarée publique, statique et vide. Il doit accepter un seul argument qui est un tableau de chaînes. Cette méthode peut être déclarée soit

public static void main(String[] args)

ou

public static void main(String... args)

Spécification Oracle Java Virtual Machine

Check-out Chapitre 2 Concepts du langage de programmation Java - Section 2.17 Exécution:

La machine virtuelle Java démarre l'exécution en invoquant la méthode main d'une classe spécifiée et en lui passant un argument unique, qui est un tableau de chaînes. Ceci entraîne le chargement de la classe spécifiée (§2.17.2), son rattachement (§2.17.3) aux autres types qu'elle utilise et son initialisation (§2.17.4). La méthode main doit être déclarée publique, statique et vide.

Oracle OpenJDK Source

Téléchargez et extrayez le fichier source et voyez comment est écrite la machine virtuelle Java, consultez ../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);

... ...

35



Faisons simplement semblant que static ne serait pas requis comme point d’entrée de l’application.

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 code constructeur et main Une méthode est nécessaire car dans OO, 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" souhaité. Mettre le code d'application complet dans le constructeur gâcherait cela.

Donc, cette approche forcerait Trois différents contrats lors de la demande:

  • doit être un constructeur par défaut. Sinon, la machine virtuelle Java ne saurait pas quel constructeur appeler et quels paramètres devraient être fournis.
  • doit être un main méthode1. Ok, ce n'est pas surprenant.
  • La classe ne doit pas être abstract. Sinon, la JVM ne pourrait pas l'instancier.

le static approche d'autre part ne nécessite que un Contrat:

  • Il doit y avoir un main méthode1.

Ici non plus abstract Ni les constructeurs multiples ne comptent.

Depuis que 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 ait été conçu de manière simple un contrat et non d'une manière complexe en utilisant Trois contrats indépendants et fragiles.

Veuillez noter: Cet argument est ne pas à propos de la simplicité à l'intérieur de la JVM ou à l'intérieur du JRE. Cet argument concerne la simplicité pour le utilisateur.


1Ici, la signature complète compte comme un seul contrat.


29



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 Spécification du langage Java.


13



Avant d'appeler la méthode principale, aucun objet n'est instancié. Avoir le mot-clé static signifie que la méthode peut être appelée sans créer d'abord d'objets.


11



Parce que sinon, il aurait besoin d'une instance de l'objet à exécuter. Mais il doit être appelé de toutes pièces, sans avoir à construire l'objet en premier, puisqu'il revient généralement à la fonction main () (bootstrap) d'analyser les arguments et de construire l'objet, généralement en utilisant ces arguments / paramètres du programme.


11



Quel est le sens de public static void main(String args[])?

  1. public est un spécificateur d'accès qui signifie que n'importe qui peut y accéder / l'invoquer, par exemple JVM (Java Virtual Machine).
  2. static permet main() être appelé avant qu'un objet de la classe ait été créé. C'est nécessaire parce que main() est appelée par la JVM avant que des objets ne soient créés. Comme il est statique, il peut être directement appelé via 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 les méthodes définies par l’utilisateur afin de ne pas avoir à créer d’objets.

  3. void indique que le main() méthode étant déclarée ne renvoie pas de valeur.

  4. String[] args spécifie le seul paramètre dans le main() méthode.

    args - un paramètre qui contient un tableau d'objets de type classe String.


9



Laissez-moi vous expliquer ces choses d'une manière beaucoup plus simple:

public static void main(String args[])

Toutes les applications Java, à l'exception des applets, démarrent leur exécution à partir de main().

Le mot-clé public est un modificateur d'accès qui permet d'appeler le membre de l'extérieur de la classe.

static est utilisé parce qu'il permet main() être appelé sans avoir à instancier une instance particulière de cette classe.

void indique que main() ne renvoie aucune valeur.


8



Les applets, les midlets, les servlets et les haricots de divers types sont construits et sont ensuite soumis à des méthodes de cycle de vie. L'invocation de main est tout ce qui est fait à la classe principale, donc il n'est pas nécessaire qu'un état soit maintenu dans un objet appelé plusieurs fois. Il est tout à fait normal d'épingler le main sur une autre classe (bien que ce ne soit pas une bonne idée), ce qui gênerait l'utilisation de la classe pour créer l'objet principal.


6