Perché il metodo principale Java è statico?



14 Answers

Questa è solo una convenzione. Infatti, anche il nome main () e gli argomenti passati sono puramente convenzionali.

Quando si esegue java.exe (o javaw.exe su Windows), ciò che realmente sta accadendo è un paio di chiamate JNI (Java Native Interface). Queste chiamate caricano la DLL che è realmente la JVM (è vero - java.exe NON è la JVM). JNI è lo strumento che usiamo quando dobbiamo fare il ponte tra il mondo della macchina virtuale e il mondo di C, C ++, ecc ... È vero anche il contrario - non è possibile (almeno per quanto ne so io) ottenere effettivamente una JVM in esecuzione senza utilizzare JNI.

Fondamentalmente, java.exe è un'applicazione C super semplice che analizza la riga di comando, crea un nuovo array String nella JVM per contenere quegli argomenti, analizza il nome della classe che hai specificato come contenente main (), usa le chiamate JNI per trovare il main () stesso metodo, quindi richiama il metodo main (), passando l'array di stringhe appena creato come parametro. Questo è molto, molto simile a quello che fai quando usi Reflection da Java, ma usa semplicemente chiamate di funzioni native chiamate in modo confuso.

Sarebbe perfettamente legale scrivere la tua versione di java.exe (l'origine è distribuita con JDK), e farlo fare qualcosa di completamente diverso. In effetti, questo è esattamente ciò che facciamo con tutte le nostre app basate su Java.

Ciascuna delle nostre app Java ha il proprio launcher. Facciamo questo principalmente in modo da ottenere il nostro nome e il nome del processo, ma è utile in altre situazioni in cui vogliamo fare qualcosa oltre alla normale chiamata main () per far funzionare le cose (ad esempio, in un caso stiamo facendo Interoperabilità COM, e in realtà passiamo un handle COM in main () invece di un array di stringhe).

Quindi, lungo e corto: il motivo per cui è statico è b / c che è conveniente. Il motivo per cui è chiamato 'main' è perché doveva essere qualcosa, e main () è ciò che hanno fatto nei vecchi tempi di C (e in quei giorni, il nome della funzione era importante). Suppongo che java.exe ti abbia permesso di specificare solo un nome di metodo principale completo, invece della sola classe (java com.mycompany.Foo.someSpecialMain) - ma questo rende solo più difficile sugli IDE il rilevamento automatico del ' classi "lavorabili" in un progetto.

Question

La firma del metodo di un metodo main () Java è:

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

C'è un motivo per cui questo metodo è statico?




It is just a convention as we can see here:

The method must be declared public and static , it must not return any value, and it must accept a String array as a parameter. By default, the first non-option argument is the name of the class to be invoked. A fully-qualified class name should be used. If the -jar option is specified, the first non-option argument is the name of a JAR archive containing class and resource files for the application, with the startup class indicated by the Main-Class manifest header.

http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html#description




Perché public static void main (String [] args)?

Questo è il modo in cui Java Language è progettato e Java Virtual Machine è progettato e scritto.

Oracle Java Language Specification

Consulta Capitolo 12 Esecuzione - Sezione 12.1.4 Invoca Test.main :

Infine, dopo il completamento dell'inizializzazione per il test di classe (durante il quale potrebbero essersi verificati altri carichi, collegamenti e inizializzazioni consequenziali), viene richiamato il metodo principale di Test.

Il metodo principale deve essere dichiarato pubblico, statico e vuoto. Deve accettare un singolo argomento che è una matrice di stringhe. Questo metodo può essere dichiarato come uno

public static void main(String[] args)

o

public static void main(String... args)

Specifica Java Virtual Machine Oracle

Scopri Capitolo 2 Concetti sul linguaggio di programmazione Java - Sezione 2.17 Esecuzione :

La Java virtual machine avvia l'esecuzione invocando il metodo main di una determinata classe e passandogli un singolo argomento, che è una matrice di stringhe. Questo fa sì che la classe specificata sia caricata (§2.17.2), collegata (§2.17.3) ad altri tipi che usa e inizializzata (§2.17.4). Il metodo principale deve essere dichiarato pubblico, statico e vuoto.

Oracle OpenJDK Source

Scarica ed estrai il jar sorgente e vedi come viene scritta JVM, controlla ../launcher/java.c , che contiene il codice C nativo dietro il comando 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);

... ...



Basically we make those DATA MEMBERS and MEMBER FUNCTIONS as STATIC which are not performing any task related to an object. And in case of main method, we are making it as an STATIC because it is nothing to do with object, as the main method always run whether we are creating an object or not.




Lascia che ti spieghi queste cose in un modo molto più semplice:

public static void main(String args[])

Tutte le applicazioni Java, eccetto le applet, iniziano la loro esecuzione da main() .

La parola chiave public è un modificatore di accesso che consente al membro di essere chiamato dall'esterno della classe.

static è usato perché permette a main() di essere chiamato senza dover istanziare una particolare istanza di quella classe.

void indica che main() non restituisce alcun valore.




Quando esegui Java Virtual Machine (JVM) con il comando java ,

java ClassName argument1 argument2 ...

Quando si esegue l'applicazione, si specifica il nome della classe come argomento per il comando java, come sopra

la JVM tenta di richiamare il metodo principale della classe specificata

-in questo punto, non sono stati creati oggetti della classe.

La dichiarazione di main come static allows JVM di invoke main without creare instance della classe.

torniamo al comando

ClassName è un command-line argument per JVM che indica quale classe eseguire. Seguendo il ClassName, puoi anche specificare un list of Strings (separate da spazi) come argomenti da riga di comando che la JVM passerà alla tua applicazione. -Questi argomenti potrebbero essere usati per specificare le opzioni (es. Un nome di file) per eseguire l'applicazione - questo è il motivo per cui esiste un parametro chiamato String[] args nel

Riferimenti: Java ™ How To Program (Early Objects), Decima edizione




Recentemente, una domanda simile è stata pubblicata su Programmers.SE

  • Perché un metodo principale statico in Java e C #, piuttosto che un costruttore?

    Alla ricerca di una risposta definitiva da una fonte primaria o secondaria per il motivo per cui (in particolare) Java e C # decidono di avere un metodo statico come loro punto di ingresso - piuttosto che rappresentare un'istanza dell'applicazione da un'istanza di una classe Application , con il punto di ingresso un costruttore appropriato?

TL;DR parte della risposta accettata è,

In Java, la ragione del public static void main(String[] args) è quella

  1. Voleva Gosling
  2. il codice scritto da qualcuno esperto in C (non in Java)
  3. da eseguire da qualcuno abituato a eseguire PostScript su NeWS


Per C #, il ragionamento è transitoriamente simile per così dire. I progettisti di linguaggi hanno mantenuto nota la sintassi del punto di ingresso del programma per i programmatori provenienti da Java. Come dice l' architetto C # Anders Hejlsberg ,

... il nostro approccio con C # è stato semplicemente quello di offrire un'alternativa ... ai programmatori Java ...

...




È solo una convenzione, ma probabilmente più conveniente dell'alternativa. Con una statica principale, tutto ciò che devi sapere per invocare un programma Java è il nome e la posizione di una classe. Se non fosse statico, dovresti anche sapere come istanziare quella classe, o richiedere che la classe abbia un costruttore vuoto.




Perché altrimenti, avrebbe bisogno di un'istanza dell'oggetto da eseguire. Ma deve essere richiamato da zero, senza prima costruire l'oggetto, dato che di solito è l'attività della funzione main () (bootstrap), per analizzare gli argomenti e costruire l'oggetto, solitamente usando questi parametri argomento / programma.




The public keyword is an access modifier, which allows the programmer to control the visibility of class members. When a class member is preceded by public , then that member may be accessed by code outside the class in which it is declared.

The opposite of public is private , which prevents a member from being used by code defined outside of its class.

In this case, main() must be declared as public , since it must be called by code outside of its class when the program is started.

The keyword static allows main() to be called without having to instantiate a particular instance of the class. This is necessary since main() is called by the Java interpreter before any objects are made.

The keyword void simply tells the compiler that main() does not return a value.




there is the simple reason behind it that is because object is not required to call static method , if It were non-static method, java virtual machine creates object first then call main() method that will lead to the problem of extra memory allocation.




Static methods don't require any object. It runs directly so main runs directly.




main () è statico perché; a quel punto nel ciclo di vita dell'applicazione, lo stack dell'applicazione è di natura procedurale poiché non vi sono oggetti ancora istanziati.

È una lavagna pulita. La tua applicazione è in esecuzione a questo punto, anche senza che vengano dichiarati oggetti (ricorda, ci sono schemi procedurali e di codifica OO). Tu, come sviluppatore, trasforma l'applicazione in una soluzione orientata agli oggetti creando istanze dei tuoi oggetti e in base al codice compilato all'interno.

Orientato agli oggetti è grande per milioni di ragioni ovvie. Tuttavia, sono passati i giorni in cui la maggior parte degli sviluppatori di VB utilizzava regolarmente parole chiave come "goto" nel loro codice. "goto" è un comando procedurale in VB che viene sostituito dalla sua controparte OO: invocazione del metodo.

Potresti anche considerare il punto di ingresso statico (principale) come pura libertà. Se Java fosse stato abbastanza diverso da istanziare un oggetto e presentasse solo quell'istanza durante l'esecuzione, non avresti altra scelta MA scrivere un'app procedurale. Per quanto inimmaginabile possa sembrare per Java, è possibile che ci siano molti scenari che richiedono approcci procedurali.

Questa è probabilmente una risposta molto oscura. Ricorda, "classe" è solo una raccolta di codice correlato. "Istanza" è una generazione autonoma isolata, vivente e che respira di quella classe.




Il vero punto di ingresso per qualsiasi applicazione è un metodo statico. Se il linguaggio Java supportava un metodo di istanza come "punto di ingresso", allora il runtime avrebbe bisogno di implementarlo internamente come metodo statico che costruiva un'istanza dell'oggetto seguito chiamando il metodo di istanza.

Con quello fuori mano, esaminerò la logica per la scelta di uno specifico delle seguenti tre opzioni:

  1. Un static void main() come lo vediamo oggi.
  2. Un metodo di istanza void main() chiamato su un oggetto appena costruito.
  3. Utilizzando il costruttore di un tipo come punto di ingresso (ad esempio, se la classe di voce era chiamata Program , l'esecuzione sarebbe effettivamente costituita dal new Program() ).

Abbattersi:

static void main()

  1. Chiama il costruttore statico della classe che include.
  2. Chiama il metodo statico main() .

void main()

  1. Chiama il costruttore statico della classe che include.
  2. Costruisce un'istanza della classe che racchiude chiamando in modo efficace il new ClassName() .
  3. Chiama il metodo di istanza main() .

new ClassName()

  1. Chiama il costruttore statico della classe che include.
  2. Costruisce un'istanza della classe (quindi non fa nulla con essa e semplicemente restituisce).

Fondamento logico:

Andrò in ordine inverso per questo.

Tieni presente che uno degli obiettivi di progettazione di Java era quello di enfatizzare (richiedono quando possibile) buone pratiche di programmazione orientata agli oggetti. In questo contesto, il costruttore di un oggetto inizializza l'oggetto, ma non dovrebbe essere responsabile del comportamento dell'oggetto. Pertanto, una specifica che forniva un entry point del new ClassName() confondeva la situazione dei nuovi sviluppatori Java forzando un'eccezione alla progettazione di un costruttore "ideale" su ogni applicazione.

Rendendo main() un metodo di istanza, il problema di cui sopra è certamente risolto. Tuttavia, crea complessità richiedendo la specifica per elencare la firma del costruttore della classe entry e la firma del metodo main() .

In sintesi, specificando un static void main() crea una specifica con la minore complessità mentre si aderisce al principio di collocare il comportamento in metodi . Considerando quanto sia semplice implementare un metodo main() che costruisce essa stessa un'istanza di una classe e chiama un metodo di istanza, non vi è alcun reale vantaggio nello specificare main() come metodo di istanza.




Se non lo fosse, quale costruttore dovrebbe essere usato se ce ne sono più di uno?

Sono disponibili ulteriori informazioni sull'inizializzazione e l'esecuzione dei programmi Java disponibili nella specifica del linguaggio Java .




Related