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


505

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

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

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


1
en este caso, no deberíamos decir la firma del método , porque el término se refiere solo a los nombres de los métodos y sus parámetros
Andrew Tobilko

Java está deliberadamente diseñado para parecerle familiar a un programador en C. Esto está muy cerca de la convención C.
Thorbjørn Ravn Andersen

Respuestas:


337

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

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

¿Debería llamar la JVM new JavaClass(int)? ¿Para qué debería pasar x?

Si no, ¿debería crear una instancia de JVM JavaClasssin ejecutar ningún método de construcción? Creo que no debería ser así, porque eso hará un caso especial de toda su clase: a veces tiene una instancia que no se ha inicializado y debe verificarla en cada método que se pueda 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. Por eso maines estático.

Sin embargo, no tengo idea de por qué mainsiempre está marcado public.


44
Implementar una interfaz no resuelve el problema de creación de instancias.
Jacob Krall

26
Personalmente, me gusta que public static void mainsirva como marcador de un punto de entrada: un constructor público sin parámetros no grita "¡Este es probablemente un punto de entrada!" del mismo modo.
Jacob Krall

55
@EdwinDalorzo - ¿Qué se ganaría al forzar la instancia de la clase de punto de entrada? Llamar a un método estático coloca la menor cantidad de carga en la clase. Es gratis crear una instancia si eso tiene más sentido para su diseño.
David Harkness

18
"¿Qué constructor debería llamarse?" ¿Cómo es eso incluso un problema? El mismo "problema" existe para la decisión mainde llamar. Por extraño que parezca (para usted), la JVM maneja esto muy bien.
Konrad Rudolph

99
El método principal siempre es público porque el motor de tiempo de ejecución, JVM, debe acceder a él.
gthm

398

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 sucede es un par de llamadas de Java Native Interface (JNI). Estas llamadas cargan la DLL que realmente es la JVM (es cierto, java.exe NO es la JVM). JNI es la herramienta que utilizamos cuando tenemos que unir el mundo de la máquina virtual y el mundo de C, C ++, etc. Lo contrario también es cierto: no es posible (al menos que yo sepa) realmente obtener un JVM ejecutándose sin usar JNI.

Básicamente, java.exe es una aplicación C super simple que analiza la línea de comando, crea una nueva matriz de cadenas en la JVM para contener esos argumentos, analiza el nombre de clase que especificó como que contiene main (), usa llamadas JNI para encontrar el main () en sí mismo, luego invoca el método main (), pasando la matriz de cadenas recién creada como parámetro. Esto es muy, muy parecido a lo que haces cuando usas la reflexión de Java: en su lugar, solo usa llamadas a funciones nativas con nombres confusos.

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 ícono y nombre de proceso, pero ha sido útil en otras situaciones en las que queremos hacer algo además de la llamada main () regular para que todo funcione (por ejemplo, en un caso lo estamos haciendo Interoperabilidad COM, y de hecho pasamos un identificador COM a main () en lugar de una matriz de cadenas).

Entonces, largo y corto: la razón por la que es estático 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 hicieron en los viejos tiempos de C (y en esos 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 totalmente calificado, en lugar de solo la clase (java com.mycompany.Foo.someSpecialMain), pero eso hace que sea más difícil para los IDEs detectar automáticamente el ' Lanzables 'clases en un proyecto.


66
+1: Muy fascinante (especialmente la parte sobre cómo escribir una costumbre java.exe)
Adam Paynter

99
Interesante, no estoy de acuerdo con "Esto es solo una convención". Parte de la respuesta. La pregunta principal del OP fue la razón de la estática en la declaración. No creo que staticla main()declaración sea solo por convenio. Sin embargo, el hecho de que sea 'main ()' y no otra cosa es factible.
Jared

2
@David Así fue. En realidad, hubiera preferido una respuesta de una de las personas involucradas originalmente, pero esa fue una posibilidad muy remota. Lamentablemente, la mayoría de las otras respuestas son un ejercicio de razonamiento ad-hoc. Este da detalles bastante interesantes, además de tener la humildad de no inventar detalles técnicos incorrectos para razonar una causa (probablemente) no técnica.
Konrad Rudolph

2
@Jared: podrían haber requerido un constructor público sin argumentos y haber sido mainno estáticos y aún estar dentro de los límites del lenguaje. Sin tener noticias de los diseñadores, tendremos que aceptar no estar de acuerdo. :)
David Harkness

44
@BenVoigt Llama a LoadLibrary () para obtener el dll jvm. Luego llama a getprocaddress ("JNI_CreateJavaVM"), luego invoca la función JNI_CreateJavaVM ( docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/… ). Una vez que se carga la VM, utiliza llamadas JNI estándar para encontrar la clase correcta, carga el método principal estático e invoca. No hay mucho espacio para malas interpretaciones allí. JNI es absolutamente cómo carga la VM. Puede estar acostumbrado a escribir solo JNI del lado del cliente utilizando la palabra clave nativa, javah -jni, etc., pero eso es solo la mitad de JNI.
Kevin Day

188

El main()método está en C++, C#y Javaes estático.
Debido a que pueden ser invocados por el motor de tiempo de ejecución sin tener que instanciar ningún objeto, el código en el cuerpo de main()hará el resto.


1
Está bien, pero ¿no podría el tiempo de ejecución instanciar un objeto de la clase? ¿Y luego llamar al método Main? ¿Por qué?
Andrei Rînea

12
¿Cómo sabría la JVM a qué constructor llamar si su clase principal hubiera sobrecargado a los constructores? ¿Qué parámetros pasaría?
Jacob Krall

1
@Noah cuando dices clase padre, ¿te refieres a la clase que contiene el método principal? Porque si es así, el término "clase padre" es bastante confuso aquí, y de lo contrario no tendría sentido para mí. Además, si usamos por convención public static void main..., ¿por qué no podría ser que la clase de punto de entrada de la aplicación debería tener un constructor público predeterminado?
Edwin Dalorzo

2
@Jacob ¿Cómo sabría la JVM qué sobrecargado static void mainllamar? No es un problema en absoluto.
Konrad Rudolph

44
@Namratha: Sí, te estás perdiendo algo. Simplemente no es cierto que "el método estático no puede hacer referencia al método no estático". La declaración correcta es: "Todo método estático debe proporcionar un objeto cuando se utiliza cualquier método no estático". Y mira, staticmétodos como los que mainse usan newcon frecuencia para crear dicho objeto.
Ben Voigt

38

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

Especificación del lenguaje Oracle Java

Consulte el Capítulo 12 Ejecución - Sección 12.1.4 Invocar Test.main :

Finalmente, después de completar la inicialización para la prueba de clase (durante la cual pueden haberse producido otras cargas, enlaces e inicializaciones consecuentes), se invoca el método principal de Test.

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

public static void main(String[] args)

o

public static void main(String... args)

Especificación de máquina virtual Oracle Java

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

La máquina virtual Java comienza 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 hace que la clase especificada se cargue (§2.17.2), se vincule (§2.17.3) a otros tipos que usa y se inicialice (§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, consulte ../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);

... ...

44
El problema aquí es que esta es realmente una muy buena respuesta a la pregunta en su forma original, con muchas referencias (+1). Sin embargo, me encantaría conocer la justificación de la decisión de diseño de hacer de un método estático el punto de entrada, en lugar de un método de instalador o constructor.
Konrad Rudolph

1
@KonradRudolph, para preguntas relacionadas con el lenguaje y el diseño de la especificación JVM, tal vez podría intentar contactar a la fuente original de Oracle y ver si puede obtener algún comentario positivo.
yorkw

2
En términos generales, cuando el cálculo del resultado de un método depende solo de sus parámetros, de modo que no depende del estado interno de la instancia del objeto, puede ser estático. Y se recomienda configurarlo como estático para la mantenibilidad / reutilización del código. Si el método mainno era estático, significa que debe conocerse el estado de la instancia de clase y es mucho más complejo de definir, como qué constructor usar primero.
Yves Martin

@KonradRudolph Curiosamente, Oak (el predecesor de Java) ya requería que el método principal tuviera un prototipo similar: public static void main(String arguments[])- Referencia: Oak 0.2 Spec .
assylias

2
@Yves puede ser. No es necesario, si otro diseño tiene sentido. He escuchado algunos buenos argumentos en los comentarios aquí, pero sigo pensando que un proceso es efectivamente muy parecido a un hilo ( es ), y un hilo en Java generalmente se representa como una instancia de Runnable. Representar todo el proceso de la misma manera (es decir, tener Runnable.Runcomo punto de entrada) definitivamente tiene sentido en Java. Por supuesto, Runnablesí mismo podría decirse que es una falla de diseño, causada por el hecho de que Java aún no tiene métodos anónimos. Pero como ya está allí ...
Konrad Rudolph

36

Simplemente imaginemos que eso staticno sería necesario 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 el código del constructor y el mainmétodo es necesaria porque en OO speak un constructor solo se asegurará de que una instancia se inicialice correctamente. Después de la inicialización, la instancia se puede utilizar para el "servicio" previsto. Poner el código completo de la aplicación en el constructor lo estropearía.

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

  • No debe ser un constructor por defecto. De lo contrario, la JVM no sabría a qué constructor llamar y qué parámetros deberían proporcionarse.
  • No debe ser un mainmétodo 1 . Ok, esto no es sorprendente.
  • La clase no debe ser abstract. De lo contrario, la JVM no podría crear una instancia.

El staticenfoque, por otro lado, solo requiere un contrato:

  • Debe haber un mainmétodo 1 .

Aquí no importan abstractni los constructores múltiples.

Dado que Java fue diseñado para ser un lenguaje simple para el usuario, no es sorprendente que también el punto de entrada de la aplicación se haya diseñado de manera simple usando un contrato y no de manera compleja usando tres contratos independientes y frágiles.

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


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


1
En realidad, los requisitos son más complejos: tiene que haber un mainmétodo que es public, staticy tiene la firma void main(String[]). Estoy de acuerdo en que, si el método fuera un método de instancia, el JRE tendría un poco más de trabajo pero el tipo de trabajo sería el mismo, y la complejidad no sería significativamente mayor (ver las discusiones en los comentarios de la respuesta anterior). No creo que esta diferencia explique la decisión de hacer que el punto de entrada sea estático, en particular porque existen los métodos necesarios para la resolución de un método de instancia, y son fácilmente utilizables.
Konrad Rudolph el

3
@KonradRudolph: Mi punto no es sobre el trabajo que el JRE tendría que hacer. Mi punto es sobre obligar a cada usuario del idioma a seguir más contratos según sea necesario. En este sentido, un static public main(String[])método es una firma y, por lo tanto, un contrato. De lo contrario, deben seguirse tres contratos independientes .
AH

1
Ah Sin embargo, todavía no estoy de acuerdo en que esto haga alguna diferencia. Las clases de punto de entrada bien podrían implementarse Runnable. Claramente, Java espera que los desarrolladores sigan ese contrato todo el tiempo, ¿por qué debería ser demasiado para el punto de entrada de la aplicación? Eso no tiene sentido.
Konrad Rudolph el

3
@KonradRudolph: No hay contradicción: en un caso, el sistema forzaría tres contratos al usuario. Contratos que son dudosos, que no son verificables a través del compilador y que, desde el punto de vista del usuario, son independientes. En el caso habitual Thready en el Runnablecaso de que el usuario no oculte nada, puede ver claramente lo que está sucediendo y tiene el cambio para implementar solo aquellos contratos que le convengan: él tiene el control, no el sistema.
AH

2
Esta es la mejor respuesta aquí. Es una pena que muchos usuarios solo lean las 2 o 3 respuestas principales en la página; y es poco probable que llegue pronto. Menciona el punto importante de que un constructor es SOLO para la inicialización y, por lo tanto, no tiene sentido codificar en un estilo en el que el constructor ejecuta toda la aplicación.
Dawood ibn Kareem el


12

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


Incorrecto. O al menos muy poco preciso. public class Main {objeto Object estático = nuevo Object () {{System.out.println ("objeto creado"); }}; public static void main (String [] args) {System.out.println ("en main"); }}
eljenso

Comentario justo Técnicamente, debería haber dicho que antes de llamar al método Main, no se instancia la clase que contiene el método main.
BlackWasp

12

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


10

Déjame explicarte 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 publices un modificador de acceso que permite llamar al miembro desde fuera de la clase.

staticse usa porque permite main()ser llamado sin tener que instanciar una instancia particular de esa clase.

voidindica que main()no devuelve ningún valor.


9

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

  1. public es un especificador de acceso, lo que significa que cualquiera puede acceder / invocarlo, como JVM (Java Virtual Machine).
  2. staticpermite main()ser llamado antes de que se haya creado un objeto de la clase. Esto es necesario porque main()es invocado por la JVM antes de hacer 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 static en algún momento para métodos definidos por el usuario, por lo que no necesitamos hacer objetos.

  3. voidindica que el main()método que se declara no devuelve un valor.

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

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


6

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


5

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 programa Java es el nombre y la ubicación de una clase. Si no fuera estático, también tendría que saber cómo crear una instancia de esa clase, o requerir que la clase tenga un constructor vacío.


No es una convención; es parte de la especificación del lenguaje; el tiempo de ejecución no reconocerá una clase sin un método principal estático como un punto de entrada válido.
Rob

2
La especificación del lenguaje en sí sigue la convención. No existe un requisito real para que los diseñadores de Java hayan optado por requerir una fuente principal estática. Sin embargo, como explica Logan, las alternativas son más complicadas.
David Arno

@DavidArno Tendría más sentido decir que la convención sigue la especificación del lenguaje.
Marqués de Lorne

5

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


5

Cuando ejecutas la máquina virtual Java (JVM) con el javacomando,

java ClassName argument1 argument2 ...

Cuando ejecuta su aplicación, especifica su nombre de clase como 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.

Declarando maincomo estática allowsla JVM a invokemain withoutcreando una instancede la clase.

volvamos al comando

ClassNamees un command-line argumentJVM que le dice qué clase ejecutar. Después de ClassName, también puede especificar un list of Strings(separado por espacios) como argumentos de línea de comandos que la JVM pasará a su aplicación. -Tales argumentos podrían usarse para especificar opciones (por ejemplo, un nombre de archivo) para ejecutar la aplicación- es por eso que hay un parámetro llamado String[] argsen el main

Referencias: Java ™ Cómo programar (primeros objetos), décima edición


4

Recientemente, se ha publicado una pregunta similar en Programmers.SE

TL; DR parte de la respuesta aceptada es,

En Java, la razón 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 lenguaje mantuvieron la sintaxis del punto de entrada del programa familiar para los programadores provenientes de Java. Como dice el arquitecto C # Anders Hejlsberg ,

... nuestro enfoque con C # ha sido simplemente ofrecer una alternativa ... a los programadores de Java ...

...


3

Creo que la palabra clave 'static' 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 requiere un objeto de referencia. Entonces, cuando se compila la clase de controlador, se puede invocar el método principal. (Solo estoy en el nivel alfabético de Java, lo siento si me equivoco)


Todos los métodos 'tienen solo una copia'.
Marqués de Lorne

3

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

Es una pizarra limpia. Su aplicación se está ejecutando en este punto, incluso sin que se declare ningún objeto (recuerde, hay patrones de codificación de procedimiento YOO). Usted, como desarrollador, convierte la aplicación en una solución orientada a objetos creando instancias de sus objetos y dependiendo del código compilado dentro.

La orientación a objetos es excelente por millones de razones obvias. Sin embargo, ya pasaron 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 contraparte OO: invocación de método.

También puede ver el punto de entrada estático (principal) como pura libertad. Si Java hubiera sido lo suficientemente diferente como para crear una instancia de un objeto y presentarle solo esa instancia durante la ejecución, no tendría otra opción PERO escribir una aplicación de procedimiento. Por inimaginable que pueda parecer para Java, es posible que haya muchos escenarios que requieran 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, viva y respirante de esa clase.


77
Esto es incorrecto. Se instancian muchos objetos antes de mainalcanzarlos. Y si incluye un constructor estático en la clase que contiene main, eso se ejecuta antes de la mainmisma manera.
Konrad Rudolph

2

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 billón de objetos antes de llegar a su método main ().


2

El prototipo 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 String.

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

La máquina virtual Java se inicia creando una clase inicial, que se especifica de manera dependiente de la implementación, utilizando el cargador de clases bootstrap (§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 todas las ejecuciones posteriores. La ejecución de las instrucciones de la máquina virtual Java que constituyen el método principal puede provocar la vinculación (y, en consecuencia, la creación) de clases e interfaces adicionales, así como la invocación de métodos adicionales.

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

La inicialización de una clase o interfaz consiste en ejecutar su método de inicialización de clase o 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 <clinit>, 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 de la siguiente manera:

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

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 necesitan mencionar que el método principal debe ser estático en la especificación JVM porque está implícito en el hecho de que no se crea ninguna instancia antes de llamar al método principal.


2

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

Lo contrario de publices private, lo que evita que un miembro sea utilizado por código definido fuera de su clase.

En este caso, main()debe declararse como public, ya que debe ser invocado por un código fuera de su clase cuando se inicia el programa.

La palabra clave staticpermite main()ser llamada sin tener que instanciar una instancia particular de la clase. Esto es necesario ya que main()el intérprete de Java lo llama antes de que se cree ningún objeto.

La palabra clave voidsimplemente le dice al compilador que main()no devuelve un valor.


1

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 construye una instancia del objeto seguido de llamar al método de instancia.

Con eso fuera del camino, examinaré las razones para elegir una específica de las siguientes tres opciones:

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

Descompostura:

static void main()

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

void main()

  1. Llama al constructor estático de la clase envolvente.
  2. Construye una instancia de la clase envolvente mediante una llamada efectiva new ClassName().
  3. Llama al método de instancia main().

new ClassName()

  1. Llama al constructor estático de la clase envolvente.
  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 objetivos de diseño de Java era enfatizar (exigir cuando sea posible) buenas prácticas de programación orientada a objetos. En este contexto, el constructor de un objeto inicializa el objeto, pero no debe ser responsable del comportamiento del objeto. Por lo tanto, una especificación que proporcionara un punto de entrada new ClassName()confundiría la situación de los nuevos desarrolladores de Java al forzar una excepción al diseño de un constructor "ideal" en cada aplicación.

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

En resumen, especificar a 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 main()método que construya una instancia de una clase y llame a un método de instancia, no hay una ventaja real en especificarlo main()como método de instancia.


1
Esto solo está planteando la pregunta. Java necesita un cargador de aplicaciones de todos modos, lo que hace un trabajo pesado antes de llamar main. Su justificación sobre mainser demasiado complejo para principiantes parece increíble. De hecho, la estática maines muy confusa para principiantes, dudo que un constructor lo sea aún más. Dices que un "constructor no debe ser responsable del comportamiento del objeto". Esto suena interesante pero no estoy seguro de estar de acuerdo. ¿Por qué no lo hace? ¿Qué impide esto?
Konrad Rudolph

1

static: cuando la JVM realiza una llamada al método principal, no existe ningún objeto para la clase que se llama, por lo tanto, debe tener un método estático para permitir la invocación desde la clase.


1

No sé si la JVM llama al método principal antes de que los objetos sean instanciados ... Pero hay una razón mucho más poderosa por la cual el método main () es estático ... Cuando JVM llama al método principal de la clase (digamos , Persona). lo invoca por " Person.main () ". Verá, la JVM lo invoca por el nombre de la clase. Es por eso que se supone que el método main () es estático y público para que JVM pueda acceder a él.

Espero que haya ayudado. Si lo hizo, avíseme comentando.


0

Los métodos estáticos no requieren ningún objeto. Se ejecuta directamente, de modo que el principal se ejecuta directamente.


0

La palabra clave estática en el método principal se usa porque no hay ninguna instanciación que tenga lugar en el método principal. Pero el objeto se construye en lugar de la invocación, como resultado utilizamos la palabra clave estática en el método principal. En el contexto jvm, la memoria se crea cuando la clase se carga en ella y todos los miembros estáticos están presentes en esa memoria. si hacemos la estática principal ahora, estará en la memoria y podrá acceder a jvm (class.main (..)) para que podamos llamar al método principal sin necesidad de crear un montón.


0

Es solo una convención como podemos ver aquí:

El método debe declararse público y estático , no debe devolver ningún valor y debe aceptar una matriz String como parámetro. Por defecto, el primer argumento sin opción es el nombre de la clase a invocar. Se debe usar un nombre de clase completamente calificado. Si se especifica la opción -jar, el primer argumento sin opción es el nombre de un archivo JAR que contiene archivos de clase y recursos para la aplicación, con la clase de inicio indicada por el encabezado del manifiesto Main-Class.

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


Regla del idioma, quieres decir.
Marqués de Lorne

0

Las palabras clave públicas de vacío estático significan que el intérprete de máquina virtual Java (JVM) puede llamar al método principal del programa para iniciar el programa (público) sin crear una instancia de la clase (estático), y el programa no devuelve datos al intérprete Java VM (nulo) cuando termina.

Fuente: Essentials, Parte 1, Lección 2: Creación de aplicaciones


0

Básicamente, hacemos que los MIEMBROS DE DATOS y las FUNCIONES DE LOS MIEMBROS sean ESTÁTICOS que no realizan ninguna tarea relacionada con un objeto. Y en el caso del método principal, lo estamos haciendo como ESTÁTICO porque no tiene nada que ver con el objeto, ya que el método principal siempre se ejecuta si estamos creando un objeto o no.


0

Cualquier método declarado como estático en Java pertenece a la clase misma. Nuevamente, solo se puede acceder al método estático de una clase en particular haciendo referencia a la clase comoClass_name.method_name();

Por lo tanto, una clase no necesita ser instanciada antes de acceder a un método estático.

Por lo tanto, el método main () se declara de staticmodo que se pueda acceder sin crear un objeto de esa clase.

Dado que guardamos el programa con el nombre de la clase donde está presente el método principal (o desde donde el programa debe comenzar su ejecución, aplicable a las clases sin un main()método () (Nivel avanzado)). Entonces, de la manera mencionada anteriormente:

Class_name.method_name();

Se puede acceder al método principal.

En resumen, cuando el programa se compila, busca el main()método que tiene Stringargumentos como: main(String args[])en la clase mencionada (es decir, por el nombre del programa), y dado que al principio no tiene alcance para instanciar esa clase, entonces main () El método se declara como estático.


Ocurre cuando el programa se ejecuta, no se compila.
Marqués de Lorne

0

Desde java.sun.com (hay más información en el sitio):

El método principal es estático para dar al intérprete de Java VM una forma de iniciar la clase sin crear primero una instancia de la clase de control. Las instancias de la clase de control se crean en el método principal después de que se inicia el programa.

Siempre he entendido que el método principal, como cualquier método estático, se puede invocar sin crear una instancia de la clase asociada, lo que le permite ejecutarse antes que cualquier otra cosa en el programa. Si no fuera estático, tendría que crear una instancia de un objeto antes de llamarlo, lo que crea un problema de 'huevo y gallina', ya que el método principal es generalmente el que se usa para instanciar objetos al comienzo del programa.


Pero no se ejecuta "antes que nada en el programa". Todo el argumento es una falacia, y lo que es más, esta no es la primera respuesta que lo menciona, ni siquiera la segunda o la tercera.
Konrad Rudolph

Lamento que mi respuesta repita lo que otros han dicho; Solo respondí lo mejor que pude y por lo que pude encontrar en línea. De los resultados que he visto no hay otra razón por la cual el método principal es estático; a menos que haya uno profundamente oculto en alguna parte, tal vez esa sea la única respuesta que hay. Mi comprensión de Java es bastante básica, pero he escuchado la razón anterior (de profesores, libros de texto, etc.) y nunca otra.
Jesse M

@Jesse M Tu comentario solo tiene sentido si ni siquiera consideraste leer las otras respuestas primero. Que por cierto no es una cosa descabellada para hacer. Como usted mismo mencionó, su comprensión es bastante básica, por lo que es muy probable que otra persona ya haya respondido la pregunta de manera más competente. Y su comentario parece ser una racionalización para que su respuesta se vea mejor. Es una afirmación extraordinaria que tienes libros de texto y profesores de Java que piensan lo que dices y, francamente, no creo que lo hagan. (¿Alguna referencia?)
LeoR

1
@KonradRudolph Los mejores comentarios parecen bastante razonables. main () se usa como un punto de entrada al programa y hay varias referencias en el sitio web de Java que dicen que se supone que es similar a cómo C / C ++ tiene una función main (). Como Java es todo Objeto, debe ser estático para evitar la creación de instancias de objeto. Tenerlo estático también le permite cargarse y ejecutarse en la JVM en tiempo de ejecución. Solo estoy regurgitando respuestas anteriores, pero me pregunto qué considerarías una respuesta satisfactoria. Creo que lo mejor que obtendrás es "Así lo querían". Tenga en cuenta la fecha en que se creó Java.
trevor-e

1
@Jesse Spot-on. Es completamente posible que sea simplemente una cuestión de convención (aunque espero que no lo sea, esa sería una respuesta tan aburrida). Mi interés original en esta pregunta fue porque pensé que usar una instancia adecuada para representar el objeto "aplicación en ejecución" y que el punto de entrada fuera un método (o el constructor) de esta clase sería un diseño mucho más obvio, ya que Java fue diseñado para ser orientado desde el primer momento objeto, y desde objetos aparentemente análogas (hilos, vía Runnable) en Java hacer uso de este diseño. ¿Por qué la excepción (aparente) aquí?
Konrad Rudolph
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.