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?
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?
Respuestas:
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 JavaClass
sin 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 main
es estático.
Sin embargo, no tengo idea de por qué main
siempre está marcado public
.
public static void main
sirva 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.
main
de llamar. Por extraño que parezca (para usted), la JVM maneja esto muy bien.
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.
java.exe
)
static
la main()
declaración sea solo por convenio. Sin embargo, el hecho de que sea 'main ()' y no otra cosa es factible.
main
no 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. :)
El main()
método está en C++
, C#
y Java
es 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.
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?
static void main
llamar? No es un problema en absoluto.
static
métodos como los que main
se usan new
con frecuencia para crear dicho objeto.
Así es como se diseña Java Language y se diseña y escribe Java Virtual Machine.
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)
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.
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);
... ...
main
no 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.
public static void main(String arguments[])
- Referencia: Oak 0.2 Spec .
Runnable
. Representar todo el proceso de la misma manera (es decir, tener Runnable.Run
como punto de entrada) definitivamente tiene sentido en Java. Por supuesto, Runnable
sí 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í ...
Simplemente imaginemos que eso static
no 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 main
mé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:
main
método 1 . Ok, esto no es sorprendente.abstract
. De lo contrario, la JVM no podría crear una instancia.El static
enfoque, por otro lado, solo requiere un contrato:
main
método 1 .Aquí no importan abstract
ni 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 .
main
método que es public
, static
y 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.
static public main(String[])
método es una firma y, por lo tanto, un contrato. De lo contrario, deben seguirse tres contratos independientes .
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.
Thread
y en el Runnable
caso 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.
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 programas Java disponible en la Especificación del lenguaje Java .
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.
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.
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 public
es un modificador de acceso que permite llamar al miembro desde fuera de la clase.
static
se usa porque permite main()
ser llamado sin tener que instanciar una instancia particular de esa clase.
void
indica que main()
no devuelve ningún valor.
¿Cuál es el significado de public static void main(String args[])
?
public
es un especificador de acceso, lo que significa que cualquiera puede acceder / invocarlo, como JVM (Java Virtual Machine).static
permite 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.
void
indica que el main()
método que se declara no devuelve un valor.
String[] args
especifica el único parámetro en el main()
método.
args
- un parámetro que contiene una matriz de objetos de tipo de clase String
.
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.
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.
Cuando ejecutas la máquina virtual Java (JVM) con el java
comando,
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
main
como estáticaallows
la JVM ainvoke
mainwithout
creando unainstance
de la clase.
volvamos al comando
ClassName
es un command-line argument
JVM 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[] args
en el main
Referencias: Java ™ Cómo programar (primeros objetos), décima edición
Recientemente, se ha publicado una pregunta similar en Programmers.SE
Buscando una respuesta definitiva de una fuente primaria o secundaria de por qué (en particular) Java y C # decidieron tener un método estático como punto de entrada, en lugar de representar una instancia de aplicación por una instancia de una
Application
clase, siendo el punto de entrada un constructor apropiado?
TL; DR parte de la respuesta aceptada es,
En Java, la razón
public static void main(String[] args)
es que
- Gosling quería
- El código escrito por alguien con experiencia en C (no en Java)
- para ser ejecutado por alguien acostumbrado a ejecutar PostScript en NeWS
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 ...
...
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)
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.
main
alcanzarlos. Y si incluye un constructor estático en la clase que contiene main, eso se ejecuta antes de la main
misma manera.
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.
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.
La public
palabra 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 public
es 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 static
permite
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 void
simplemente le dice al compilador que main()
no devuelve un valor.
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:
static void main()
como lo vemos hoy.void main()
llamado en un objeto recién construido.Program
, la ejecución consistiría efectivamente en new Program()
).static void main()
main()
.void main()
new ClassName()
.main()
.new ClassName()
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.
main
. Su justificación sobre main
ser demasiado complejo para principiantes parece increíble. De hecho, la estática main
es 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?
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.
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.
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.
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
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
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.
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 static
modo 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 String
argumentos 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.
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.
Runnable
) en Java hacer uso de este diseño. ¿Por qué la excepción (aparente) aquí?