Perché il metodo principale Java è statico?

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

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

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

Il metodo è statico perché altrimenti ci sarebbe ambiguità: quale costruttore dovrebbe essere chiamato? Soprattutto se la tua class ha questo aspetto:

 public class JavaClass{ protected JavaClass(int x){} public void main(String[] args){ } } 

La JVM dovrebbe chiamare la new JavaClass(int) ? Cosa dovrebbe passare per x ?

In caso contrario, la JVM dovrebbe istanziare JavaClass senza eseguire alcun metodo di costruzione? Penso che non dovrebbe, perché sarà il caso speciale dell’intera class – a volte hai un’istanza che non è stata inizializzata, e devi controllarla in tutti i metodi che potrebbero essere chiamati.

Ci sono troppi casi limite e ambiguità perché sia ​​logico che JVM debba istanziare una class prima che venga chiamato il punto di ingresso. Ecco perché il main è statico.

Non ho idea del perché il main sia sempre contrassegnato come public .

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 utilizziamo quando dobbiamo colbind il mondo delle macchine virtuali e il mondo di C, C ++, ecc. È vero anche il contrario – non è ansible (almeno per quanto ne so io) ottenere effettivamente un 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 class 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 fare qualcosa di completamente diverso. In realtà, 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” è che doveva essere qualcosa, e main () è ciò che hanno fatto ai 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 class (java com.mycompany.Foo.someSpecialMain) – ma questo rende solo più difficile sugli IDE il rilevamento automatico del ‘ classi “lavorabili” in un progetto.

Il metodo main () in C ++, C # e Java sono statici perché possono essere richiamati dal motore di runtime senza dover istanziare un’istanza della class genitore.

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 class (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 class e passandogli un singolo argomento, che è una matrice di stringhe. Questo fa sì che la class specificata venga 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); ... ... 

Facciamo semplicemente finta, che static non sarebbe richiesta come il punto di ingresso dell’applicazione.

Una class di applicazione sarebbe quindi simile a questa:

 class MyApplication { public MyApplication(){ // Some init code here } public void main(String[] args){ // real application code here } } 

La distinzione tra codice costruttore e metodo main è necessaria perché in OO un costruttore deve solo assicurarsi che un’istanza sia inizializzata correttamente. Dopo l’inizializzazione, l’istanza può essere utilizzata per il “servizio” previsto. Mettere il codice completo dell’applicazione nel costruttore lo rovinerebbe.

Quindi questo approccio costringerebbe tre diversi contratti sull’applicazione:

  • Ci deve essere un costruttore predefinito. In caso contrario, la JVM non saprebbe quale costruttore chiamare e quali parametri dovrebbero essere forniti.
  • Ci deve essere un metodo main 1 . Ok, questo non è sorprendente.
  • La class non deve essere abstract . In caso contrario, la JVM non è stata in grado di creare un’istanza.

L’approccio static invece richiede solo un contratto:

  • Ci deve essere un metodo main 1 .

Qui non contano né i costruttori abstract né quelli multipli.

Poiché Java è stato progettato per essere un linguaggio semplice per l’utente , non sorprende che anche il punto di ingresso dell’applicazione sia stato progettato in modo semplice utilizzando un contratto e non in modo complesso utilizzando tre contratti indipendenti e fragili.

Nota: questo argomento non riguarda la semplicità all’interno della JVM o all’interno di JRE. Questo argomento riguarda la semplicità per l’ utente .


1 Qui la firma completa conta come un solo contratto.

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 .

Prima che venga chiamato il metodo principale, nessun object viene istanziato. Avere la parola chiave static significa che il metodo può essere chiamato senza creare prima alcun object.

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

Qual è il significato di public static void main(String args[]) ?

  1. public è un identificatore di accesso che significa che chiunque può accedervi / invocarlo come JVM (Java Virtual Machine.
  2. static consente a main() di essere chiamato prima che un object della class sia stato creato. Questo è necessario perché main() viene chiamato dalla JVM prima che vengano creati tutti gli oggetti. Poiché è statico, può essere richiamato direttamente tramite la class.

     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 */ } } 

    Allo stesso modo, usiamo statico qualche volta per i metodi definiti dall’utente, così non abbiamo bisogno di creare oggetti.

  3. void indica che il metodo main() dichiarato non restituisce un valore.

  4. String[] args specifica l’unico parametro nel metodo main() .

    args – un parametro che contiene una matrice di oggetti di tipo String .

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 class.

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

void indica che main() non restituisce alcun valore.

Applet, midlet, servlet e bean di vario tipo vengono costruiti e quindi richiamati dai metodi del ciclo di vita. Invocare main è tutto ciò che viene fatto alla class principale, quindi non c’è bisogno di tenere uno stato in un object chiamato più volte. È abbastanza normale pin principale su un’altra class (anche se non è una grande idea), che potrebbe intralciare l’uso della class per creare l’object principale.

È 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 class. Se non fosse statico, dovresti anche sapere come istanziare quella class, o richiedere che la class abbia un costruttore vuoto.

Se il metodo principale non fosse statico, avresti bisogno di creare un object della tua class principale al di fuori del programma. Come vorresti farlo?

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

 java ClassName argument1 argument2 ... 

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

la JVM tenta di richiamare il metodo principale della class specificata

-In questo punto, non sono stati creati oggetti della class.

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

torniamo al comando

ClassName è un command-line argument per JVM che indica quale class 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

Penso che la parola chiave ‘static’ renda il metodo principale un metodo di class, ei metodi di class ne abbiano solo una copia e possano essere condivisi da tutti, e inoltre, non richiede un object di riferimento. Pertanto, quando viene compilata la class del driver, è ansible richiamare il metodo principale. (Sono solo al livello di alfabeto di java, scusa se ho torto)

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 object e presentasse solo quell’istanza durante l’esecuzione, non avresti altra scelta MA scrivere un’app procedurale. Per quanto inimmaginabile possa sembrare per Java, è ansible che ci siano molti scenari che richiedono approcci procedurali.

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

Il protoipo public static void main(String[]) è una convenzione definita in JLS :

Il metodo principale deve essere dichiarato pubblico, statico e vuoto. Deve specificare un parametro formale (§8.4.1) il cui tipo dichiarato è array di String.

Nella specifica JVM 5.2. Start-up della macchina virtuale possiamo leggere:

La Java virtual machine si avvia creando una class iniziale, specificata in modo dipendente dall’implementazione, utilizzando il caricatore di class bootstrap (§5.3.1). La Java virtual machine collega quindi la class iniziale, la inizializza e richiama il metodo public class void main (String []) . L’invocazione di questo metodo guida tutte le ulteriori esecuzioni. L’esecuzione delle istruzioni della macchina virtuale Java che costituiscono il metodo principale può causare il collegamento (e conseguentemente la creazione) di classi e interfacce aggiuntive, nonché l’invocazione di metodi aggiuntivi.

Cosa buffa, nelle specifiche JVM non è detto che il metodo principale debba essere statico. Ma le specifiche dicono anche che la macchina virtuale Java esegue 2 passaggi prima:

  • collega la class iniziale ( 5.4 Collegamento )
  • Inizializza ( 5.5 Inizializzazione )

L’inizializzazione di una class o di un’interfaccia consiste nell’eseguire il suo metodo di inizializzazione della class o dell’interfaccia.

Nel 2.9. Metodi speciali :

Viene definito un metodo di inizializzazione di class o interfaccia :

Una class o un’interfaccia ha al massimo un metodo di inizializzazione di class o interfaccia ed è inizializzato (§5.5) invocando quel metodo. Il metodo di inizializzazione di una class o di un’interfaccia ha il nome speciale , non accetta argomenti ed è nullo.

E un metodo di inizializzazione di class o interfaccia è diverso da un metodo di inizializzazione dell’istanza definito come segue:

A livello della Java virtual machine, ogni costruttore scritto nel linguaggio di programmazione Java (JLS §8.8) appare come un metodo di inizializzazione dell’istanza con il nome speciale .

Quindi la JVM inizializza un metodo di inizializzazione di class o interfaccia e non un metodo di inizializzazione dell’istanza che è in realtà un costruttore. Quindi non c’è bisogno di menzionare che il metodo principale deve essere statico nelle specifiche JVM perché è implicito dal fatto che nessuna istanza viene creata prima di chiamare il metodo principale.

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 class 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

http://i.stack.imgur.com/qcmzP.png

Per C #, il ragionamento è transitoriamente simile per così dire. I progettisti di linguaggi hanno mantenuto nota la syntax 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. La JVM potrebbe certamente trattare con i metodi principali non statici se questa fosse stata la convenzione. Dopo tutto, puoi definire un inizializzatore statico sulla tua class e creare un’istanza di un object zillion prima di arrivare al tuo metodo main ().

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’object 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 object appena costruito.
  3. Utilizzando il costruttore di un tipo come punto di ingresso (ad esempio, se la class di voce era chiamata Program , l’esecuzione sarebbe effettivamente costituita dal new Program() ).

Abbattersi:

static void main()

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

void main()

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

new ClassName()

  1. Chiama il costruttore statico della class che include.
  2. Costruisce un’istanza della class (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 ansible) buone pratiche di programmazione orientata agli oggetti. In questo contesto, il costruttore di un object inizializza l’object, ma non dovrebbe essere responsabile del comportamento dell’object. 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 class 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 class e chiama un metodo di istanza, non vi è alcun reale vantaggio nello specificare main() come metodo di istanza.

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.

static – When the JVM makes a call to the main method there is no object that exists for the class being called therefore it has to have static method to allow invocation from class.

I don’t know if the JVM calls the main method before the objects are instantiated… But there is a far more powerful reason why the main() method is static… When JVM calls the main method of the class (say, Person). it invokes it by ” Person.main() “. You see, the JVM invokes it by the class name. That is why the main() method is supposed to be static and public so that it can be accessed by the JVM.

Hope it helped. If it did, let me know by commenting.

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

The static key word in the main method is used because there isn’t any instantiation that take place in the main method. But object is constructed rather than invocation as a result we use the static key word in the main method. In jvm context memory is created when class loads into it.And all static members are present in that memory. if we make the main static now it will be in memory and can be accessible to jvm (class.main(..)) so we can call the main method with out need of even need for heap been created.

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

The public static void keywords mean the Java virtual machine (JVM) interpreter can call the program’s main method to start the program (public) without creating an instance of the class (static), and the program does not return data to the Java VM interpreter (void) when it ends.

Source: Essentials, Part 1, Lesson 2: Building Applications

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.

Any method declared as static in Java belongs to the class itself . Again static method of a particular class can be accessed only by referring to the class like Class_name.method_name();

So a class need not to be instantiated before accessing a static method.

So the main() method is declared as static so that it can be accessed without creating an object of that class.

Since we save the program with the name of the class where the main method is present( or from where the program should begin its execution, applicable for classs without a main() method()(Advanced Level)). So by the above mentioned way:

 Class_name.method_name(); 

the main method can be accessed.

In brief when the program is compiled it searches for the main() method having String arguments like: main(String args[]) in the class mentioned(ie by the name of the program), and since at the the beginning it has no scope to instantiate that class, so the main() method is declared as static.

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.