¿Por qué el método principal de Java estático?

La firma de método de un método Java main () es:

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

¿Hay alguna razón para que este método sea estático?

El método es estático porque de lo contrario habría ambigüedad: ¿a qué constructor se debería llamar? Especialmente si tu clase se ve así:

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

¿Debería la JVM llamar a una new JavaClass(int) ? ¿Qué debería pasar para x ?

Si no es así, ¿la instancia de JVM debe JavaClass sin ejecutar ningún método de constructor? Creo que no debería, porque eso será un caso especial para toda la clase: a veces tienes una instancia que no se ha inicializado, y debes verificarla en todos los métodos que se puedan llamar.

Hay demasiados casos extremos y ambigüedades para que tenga sentido que la JVM tenga que instanciar una clase antes de que se llame al punto de entrada. Es por eso que main es estático.

No tengo idea de por qué main siempre es marcado public .

Esto es solo una convención. De hecho, incluso el nombre main () y los argumentos pasados ​​son puramente convencionales.

Cuando ejecuta java.exe (o javaw.exe en Windows), lo que realmente está sucediendo es un par de llamadas Java Native Interface (JNI). Estas llamadas cargan la DLL que es realmente la JVM (es correcto, java.exe NO es la JVM). JNI es la herramienta que utilizamos cuando tenemos que unir el mundo de las máquinas virtuales y el mundo de C, C ++, etc. Lo contrario también es cierto: no es posible (al menos que yo sepa) obtener un JVM ejecutándose sin usar JNI.

Básicamente, java.exe es una aplicación C súper simple que analiza la línea de comandos, crea una nueva matriz String en la JVM para contener esos argumentos, analiza el nombre de clase que especificó como que contiene main (), usa llamadas JNI para encontrar el El método main () en sí mismo, luego invoca el método main (), pasando el conjunto de cadenas recientemente creado como un parámetro. Esto es muy, muy parecido a lo que haces cuando usas la reflexión de Java, simplemente usa llamadas de funciones nativas confusas.

Sería perfectamente legal para usted escribir su propia versión de java.exe (la fuente se distribuye con el JDK) y hacer que haga algo completamente diferente. De hecho, eso es exactamente lo que hacemos con todas nuestras aplicaciones basadas en Java.

Cada una de nuestras aplicaciones Java tiene su propio lanzador. Principalmente hacemos esto para obtener nuestro propio nombre de icono y proceso, pero ha sido útil en otras situaciones en las que queremos hacer algo además de la llamada a main () regular para poner en marcha las cosas (por ejemplo, en un caso estamos haciendo Interoperabilidad COM, y realmente pasamos un manejador COM en main () en lugar de una matriz de cadenas.

Entonces, largo y corto: la razón por la cual es estática es b / c que es conveniente. La razón por la que se llama ‘main’ es que tenía que ser algo, y main () es lo que hacían en los viejos tiempos de C (y en aquellos días, el nombre de la función era importante). Supongo que java.exe podría haberle permitido especificar un nombre de método principal completamente calificado, en lugar de solo la clase (java com.mycompany.Foo.someSpecialMain), pero eso hace que sea más difícil para los IDE detectar automáticamente el ‘ clases “lanzables” en un proyecto.

El método main () en C ++, C # y Java son estáticos porque el motor de tiempo de ejecución los puede invocar sin tener que instanciar una instancia de la clase padre.

¿Por qué public static void main (String [] args)?

Así es como se diseña Java Language y se diseña y escribe Java Virtual Machine.

Oracle Java Language Specification

Consulte la Ejecución del Capítulo 12 – Sección 12.1.4 Invocar Test.principal :

Finalmente, después de completar la inicialización para la Prueba de clase (durante la cual puede haber ocurrido otra carga consecuente, vinculación e inicialización), se invoca el método principal de Prueba.

El método main debe declararse público, estático y nulo. Debe aceptar un solo argumento que sea una matriz de cadenas. Este método se puede declarar como

 public static void main(String[] args) 

o

 public static void main(String... args) 

Especificación de máquina virtual de Oracle Java

Consulte el Capítulo 2 Conceptos del lenguaje de progtwigción Java – Sección 2.17 Ejecución :

La máquina virtual Java inicia la ejecución invocando el método main de alguna clase especificada y pasándole un único argumento, que es una matriz de cadenas. Esto ocasiona que la clase especificada sea cargada (§2.17.2), enlazada (§2.17.3) a otros tipos que utiliza e inicializada (§2.17.4). El método main debe declararse público, estático y nulo.

Oracle OpenJDK Source

Descargue y extraiga el jar de origen y vea cómo se escribe JVM, revise ../launcher/java.c , que contiene el código C nativo detrás del 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); ... ... 

Simplemente pretendemos que no se requeriría static como punto de entrada de la aplicación.

Una clase de aplicación se vería así:

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

La distinción entre código de constructor y método main es necesaria porque en OO hablar un constructor solo se asegurará de que una instancia se inicialice correctamente. Después de la inicialización, la instancia se puede usar para el “servicio” deseado. Poner el código de la aplicación completa en el constructor estropearía eso.

Entonces este enfoque obligaría a tres contratos diferentes sobre la aplicación:

  • Debe haber un constructor predeterminado. De lo contrario, la JVM no sabría a qué constructor llamar y qué parámetros deberían proporcionarse.
  • Debe haber un método main 1 . Ok, esto no es sorprendente.
  • La clase no debe ser abstract . De lo contrario, la JVM no podría instanciarlo.

El enfoque static , por otro lado, solo requiere un contrato:

  • Debe haber un método main 1 .

Aquí no importa ni los constructores abstract ni los múltiples.

Como Java fue diseñado para ser un lenguaje simple para el usuario, no es de extrañar que también el punto de entrada de la aplicación haya sido diseñado de una manera simple utilizando un contrato y no de una manera compleja utilizando tres contratos independientes y frágiles.

Tenga en cuenta que este argumento no se trata de simplicidad dentro de la JVM o dentro de JRE. Este argumento es acerca de la simplicidad para el usuario .


1 Aquí la firma completa cuenta como un solo contrato.

Si no fuera así, ¿qué constructor debería usarse si hay más de uno?

Hay más información sobre la inicialización y ejecución de progtwigs Java disponibles en la Especificación del lenguaje Java .

Antes de llamar al método principal, no se crean instancias de objetos. Tener la palabra clave estática significa que el método se puede llamar sin crear ningún objeto primero.

Porque de lo contrario, necesitaría una instancia del objeto para ser ejecutado. Pero debe llamarse desde cero, sin construir primero el objeto, ya que normalmente es la tarea de la función main () (bootstrap), analizar los argumentos y construir el objeto, generalmente usando estos argumentos / parámetros del progtwig.

¿Cuál es el significado de public static void main(String args[]) ?

  1. public es un especificador de acceso que significa que cualquiera puede acceder / invocarlo, como JVM (Java Virtual Machine).
  2. static permite que se llame a main() antes de que se haya creado un objeto de la clase. Esto es necesario porque la JVM llama a main() antes de crear cualquier objeto. Como es estático, se puede invocar directamente a través de la clase.

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

    Del mismo modo, usamos estática en algún momento para los métodos definidos por el usuario para que no tengamos que hacer objetos.

  3. void indica que el método main() que se está declarando no devuelve un valor.

  4. String[] args especifica el único parámetro en el método main() .

    args – un parámetro que contiene una matriz de objetos del tipo de clase String .

Permítanme explicar estas cosas de una manera mucho más simple:

 public static void main(String args[]) 

Todas las aplicaciones Java, excepto los applets, comienzan su ejecución desde main() .

La palabra clave public es un modificador de acceso que permite llamar al miembro desde fuera de la clase.

static se usa porque permite llamar a main() sin tener que instanciar una instancia particular de esa clase.

void indica que main() no devuelve ningún valor.

Se construyen applets, midlets, servlets y beans de varios tipos y luego se les solicitan los métodos del ciclo de vida. Invocar main es todo lo que se hace en la clase principal, por lo que no es necesario que se retenga un estado en un objeto que se llama varias veces. Es bastante normal pinchar main en otra clase (aunque no es una gran idea), lo que interferiría en el uso de la clase para crear el objeto principal.

Es solo una convención, pero probablemente más conveniente que la alternativa. Con un main estático, todo lo que necesita saber para invocar un progtwig Java es el nombre y la ubicación de una clase. Si no fuera estático, también tendrías que saber cómo crear una instancia de esa clase, o requerir que la clase tenga un constructor vacío.

Si el método principal no fuera estático, necesitaría crear un objeto de su clase principal desde fuera del progtwig. ¿Cómo querrías hacer eso?

Cuando ejecuta Java Virtual Machine (JVM) con el comando java ,

 java ClassName argument1 argument2 ... 

Cuando ejecuta su aplicación, especifica su nombre de clase como un argumento para el comando java, como se indicó anteriormente

la JVM intenta invocar el método principal de la clase que especifique

En este punto, no se han creado objetos de la clase.

Declarar main como static allows la JVM invoke main without crear una instance de la clase.

volvamos al comando

ClassName es un command-line argument para la JVM que le dice qué clase ejecutar. Después de ClassName, también puede especificar una list of Strings (separadas por espacios) como argumentos de línea de comandos que la JVM transferirá a su aplicación. – Es posible que se utilicen estos argumentos para especificar opciones (por ejemplo, un nombre de archivo) para ejecutar la aplicación; esta es la razón por la cual hay un parámetro llamado String[] args en el principal

Referencias: Java ™ How to Program (Early Objects), décima edición

Creo que la palabra clave “estática” hace que el método principal sea un método de clase, y los métodos de clase tienen solo una copia y pueden ser compartidos por todos, y además, no requieren un objeto como referencia. Entonces, cuando se comstack la clase de controlador, se puede invocar el método principal. (Estoy en el nivel del alfabeto de Java, lo siento si estoy equivocado)

main () es estático porque; en ese punto en el ciclo de vida de la aplicación, la stack de la aplicación es de naturaleza procedural debido a que no hay objetos aún instanciados.

Es un borrón y cuenta nueva. Su aplicación se está ejecutando en este punto, incluso sin declarar ningún objeto (recuerde, hay patrones de encoding Y OO de procedimiento). Usted, como desarrollador, convierte la aplicación en una solución orientada a objetos creando instancias de sus objetos y dependiendo del código comstackdo dentro.

Orientada a objetos es ideal para millones de razones obvias. Sin embargo, ya no están los días en que la mayoría de los desarrolladores de VB usaban regularmente palabras clave como “goto” en su código. “goto” es un comando de procedimiento en VB que se reemplaza por su homólogo OO: invocación de método.

También podría mirar el punto de entrada estático (principal) como libertad pura. Si Java hubiera sido lo suficientemente diferente como para instanciar un objeto y presentarle solo esa instancia en ejecución, no tendría opción, PERO para escribir una aplicación de procedimiento. Por inimaginable que parezca para Java, es posible que haya muchos escenarios que requieren enfoques de procedimiento.

Esta es probablemente una respuesta muy oscura. Recuerde, “clase” es solo una colección de código interrelacionado. “Instancia” es una generación autónoma aislada, que vive y respira de esa clase.

El protoype public static void main(String[]) es una convención definida en el JLS :

El método main debe declararse público, estático y nulo. Debe especificar un parámetro formal (§8.4.1) cuyo tipo declarado es una matriz de Cadena.

En la especificación de JVM 5.2. Encendido de la máquina virtual podemos leer:

La máquina virtual Java se inicia al crear una clase inicial, que se especifica de una manera dependiente de la implementación, utilizando el cargador de clases de arranque (§5.3.1). La máquina virtual Java luego vincula la clase inicial, la inicializa e invoca el método de clase pública void main (String []) . La invocación de este método impulsa toda la ejecución posterior. La ejecución de las instrucciones de la máquina virtual Java que constituyen el método principal puede provocar la vinculación (y consecuentemente la creación) de clases e interfaces adicionales, así como la invocación de métodos adicionales.

Lo curioso es que en la especificación de JVM no se menciona que el método principal debe ser estático. Pero la especificación también dice que la máquina virtual Java realiza 2 pasos antes:

  • vincula la clase inicial ( 5.4. Vinculación )
  • lo inicializa ( 5.5. Inicialización )

La inicialización de una clase o interfaz consiste en ejecutar su clase o método de inicialización de la interfaz.

En 2.9. Métodos especiales :

Se define un método de inicialización de clase o interfaz :

Una clase o interfaz tiene como máximo un método de inicialización de clase o interfaz y se inicializa (§5.5) invocando ese método. El método de inicialización de una clase o interfaz tiene el nombre especial , no toma argumentos y es nulo.

Y un método de inicialización de clase o interfaz es diferente de un método de inicialización de instancia definido como sigue:

En el nivel de la máquina virtual Java, cada constructor escrito en el lenguaje de progtwigción Java (JLS §8.8) aparece como un método de inicialización de instancia que tiene el nombre especial .

Entonces, la JVM inicializa un método de inicialización de clase o interfaz y no un método de inicialización de instancia que en realidad es un constructor. Por lo tanto, no es necesario mencionar que el método principal debe ser estático en la especificación de JVM porque está implícito en el hecho de que no se crea ninguna instancia antes de llamar al método principal.

Recientemente, una pregunta similar ha sido publicada en Programmers.SE

  • ¿Por qué un método principal estático en Java y C #, en lugar de un constructor?

    Buscando una respuesta definitiva de una fuente primaria o secundaria de por qué (notablemente) Java y C # deciden tener un método estático como punto de entrada, en lugar de representar una instancia de aplicación por una instancia de una clase de Application , con el punto de entrada un constructor apropiado?

TL; DR parte de la respuesta aceptada es,

En Java, la razón del public static void main(String[] args) es que

  1. Gosling quería
  2. el código escrito por alguien con experiencia en C (no en Java)
  3. para ser ejecutado por alguien acostumbrado a ejecutar PostScript en NeWS

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

Para C #, el razonamiento es transitivamente similar, por así decirlo. Los diseñadores de idiomas mantuvieron la syntax del punto de entrada del progtwig familiar para los progtwigdores provenientes de Java. Como lo plantea el arquitecto de C #, Anders Hejlsberg ,

… nuestro enfoque con C # ha sido simplemente ofrecer una alternativa … a los progtwigdores de Java …

Es solo una convención. La JVM ciertamente podría tratar con métodos principales no estáticos si esa hubiera sido la convención. Después de todo, puede definir un inicializador estático en su clase e instanciar un trillón de objetos antes de llegar a su método main ().

El verdadero punto de entrada a cualquier aplicación es un método estático. Si el lenguaje Java soportaba un método de instancia como el “punto de entrada”, entonces el tiempo de ejecución necesitaría implementarlo internamente como un método estático que construía una instancia del objeto seguido de llamar al método de instancia.

Con eso fuera del camino, examinaré los motivos para elegir una de las tres opciones siguientes:

  1. Un static void main() como lo vemos hoy.
  2. Un método de instancia void main() invoca un objeto recién construido.
  3. Usando el constructor de un tipo como punto de entrada (por ejemplo, si la clase de entrada se llamaba Program , entonces la ejecución consistiría efectivamente en un new Program() ).

Descompostura:

static void main()

  1. Llama al constructor estático de la clase adjunta.
  2. Llama al método estático main() .

void main()

  1. Llama al constructor estático de la clase adjunta.
  2. Construye una instancia de la clase new ClassName() llamando efectivamente a new ClassName() .
  3. Llama al método de instancia main() .

new ClassName()

  1. Llama al constructor estático de la clase adjunta.
  2. Construye una instancia de la clase (luego no hace nada con ella y simplemente regresa).

Razón fundamental:

Iré en orden inverso para este.

Tenga en cuenta que uno de los objectives de diseño de Java era enfatizar (requerir cuando sea posible) buenas prácticas de progtwigción orientadas a objetos. En este contexto, el constructor de un objeto inicializa el objeto, pero no debería ser responsable del comportamiento del objeto. Por lo tanto, una especificación que proporcionara un punto de entrada de new ClassName() confundiría la situación para los nuevos desarrolladores de Java al forzar una excepción al diseño de un constructor “ideal” en cada aplicación.

Al hacer que main() un método de instancia, el problema anterior ciertamente está resuelto. Sin embargo, crea complejidad al requerir que la especificación liste la firma del constructor de la clase de entrada así como también la firma del método main() .

En resumen, la especificación de un static void main() crea una especificación con la menor complejidad al tiempo que se adhiere al principio de colocar el comportamiento en los métodos . Teniendo en cuenta lo sencillo que es implementar un método main() que a su vez construye una instancia de una clase y llama a un método de instancia, no hay una ventaja real al especificar main() como un método de instancia.

La palabra clave public es un modificador de acceso que permite al progtwigdor controlar la visibilidad de los miembros de la clase. Cuando un miembro de la clase es precedido por public , se puede acceder a ese miembro por código fuera de la clase en la que se declara.

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.

Espero que haya ayudado. 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 classes 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.