Estoy buscando una respuesta definitiva de una fuente primaria o secundaria de por qué (especialmente) 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 (con el punto de entrada ser un constructor apropiado).
Antecedentes y detalles de mi investigación previa.
Esto se ha preguntado antes. Desafortunadamente, las respuestas existentes simplemente están planteando la pregunta . En particular, las siguientes respuestas no me satisfacen, ya que las considero incorrectas:
- Habría ambigüedad si el constructor estuviera sobrecargado. - De hecho, C # (así como C y C ++) permite diferentes firmas para
Main
que exista la misma ambigüedad potencial y se aborde. - Un
static
método significa que no se pueden instanciar objetos antes, por lo que el orden de inicialización es claro. - Esto es realmente incorrecto, algunos objetos se instancian antes (por ejemplo, en un constructor estático). - Por lo tanto, el tiempo de ejecución puede invocarlos sin tener que crear una instancia de un objeto primario. - Esta no es una respuesta en absoluto.
Solo para justificar aún más por qué creo que esta es una pregunta válida e interesante:
Muchos marcos hacen uso de clases para representar las aplicaciones y los constructores como puntos de entrada. Por ejemplo, el marco de la aplicación VB.NET utiliza un diálogo principal dedicado (y su constructor) como punto de entrada 1 .
Ni Java ni C # técnicamente necesitan un método principal. Bueno, C # necesita uno para compilar, pero Java ni siquiera eso. Y en ninguno de los casos es necesario para la ejecución. Por lo tanto, esto no parece ser una restricción técnica. Y, como mencioné en el primer párrafo, para una simple convención, parece extrañamente inadecuado para el principio general de diseño de Java y C #.
Para ser claros, no hay una desventaja específica de tener un main
método estático , es claramente extraño , lo que me hizo preguntarme si había alguna razón técnica detrás de esto.
Estoy interesado en una respuesta definitiva de una fuente primaria o secundaria, no meras especulaciones.
1 Aunque hay una devolución de llamada ( Startup
) que puede interceptar esto.
fuente
Respuestas:
TL; DR
En Java, la razón
public static void main(String[] args)
es quePara 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 ,
Versión larga
expandiéndose arriba y respaldado con aburridas referencias.
java Terminator Hasta la vista Baby!
VM Spec, 2.17.1 Inicio de máquina virtual
... vea también: Apéndice: Necesito su ropa, sus botas y su motocicleta.
ejecución dirigida para su uso como scripts típicos en la interfaz de línea de comandos.
paso lateral importante
... eso ayuda a evitar un par de rastros falsos en nuestra investigación.
VM Spec, 1.2 La máquina virtual Java
Noté lo anterior al estudiar el capítulo anterior - 1.1 Historia que pensé que podría ser útil (pero resultó inútil).
ejecución se rige solo por las especificaciones de VM, que
declara explícitamente que no tiene nada que ver con el lenguaje Java
=> OK para ignorar JLS y cualquier cosa relacionada con el lenguaje Java
Gosling: un compromiso entre C y el lenguaje de script ...
Basado en lo anterior, comencé a buscar en la web el historial de JVM . No ayudó, demasiada basura en los resultados.
Luego, recordé las leyendas sobre Gosling y reduje mi búsqueda a la historia de Gosling JVM .
Eureka! Cómo surgió la especificación JVM
declaración explícita de que en el momento de la creación,
C y las secuencias de comandos se han considerado las influencias más importantes.
Ya visto un guiño a las secuencias de comandos en VM Spec 2.17.1, los
argumentos de la línea de comandos explican lo suficiente
String[] args
pero,
static
ymain
aún no están allí, necesitan profundizar más ...Tenga en cuenta que mientras escribo esto, conectando C, scripting y VM Spec 1.2 con su nada de Java, siento que algo familiar, algo ... orientado a objetos está desapareciendo lentamente. Toma mi mano y sigue moviéndote No disminuyas la velocidad, ya casi estamos allí
Las diapositivas de Keynote están disponibles en línea: 20_Gosling_keynote.pdf , bastante conveniente para copiar puntos clave.
A-ha! Veamos más de cerca a la sintaxis C .
¿Nos estamos acercando? usted apuesta También vale la pena seguir el enlace "principal" de la cita anterior:
para estar cómodo con el desarrollador de C, el punto de entrada del programa debe serlo
main
.Además, dado que Java requiere que cualquier método esté en clase,
Class.main
eslo
más parecido posible : invocación estática, solo nombre de clase y punto, sin constructores, por favor. C no sabe nada de eso.
Esto también se aplica de forma transitiva a C #, teniendo en cuenta
la idea de una fácil migración desde Java.
Los lectores que piensan que el punto de entrada del programa familiar no importa están amablemente invitados a buscar y verificar las preguntas de desbordamiento de pila en las que los hombres que vienen de Java SE intentan escribir Hello World para Java ME MIDP. Nota El punto de entrada MIDP no tiene
main
nistatic
.Conclusión
Basado en lo anterior, diría eso
static
,main
yString[] args
en los momentos de creación de Java y C #, las opciones más razonables para definir el punto de entrada del programa .Apéndice: necesito tu ropa, tus botas y tu motocicleta
Debo admitir que leer VM Spec 2.17.1 fue muy divertido.
Referencias simbólicas de
Terminator
oh sí.fuente
Eso se siente vagamente abusivo para mí. Un constructor se utiliza para la inicialización de un objeto: configura un objeto, que luego es utilizado por el código que lo creó.
Si coloca la funcionalidad de uso básica dentro del constructor, y luego nunca usa el objeto que el constructor crea en código externo, entonces está violando los principios de OOP. Básicamente, hacer algo realmente extraño sin razón aparente.
¿Por qué querrías hacer eso de todos modos?
fuente
Main
método funciona bien para el caso simple, y no es realmente un problema en casos más difíciles, entonces, ¿por qué no?Para Java, creo que el razonamiento es simple: al desarrollar Java, los desarrolladores sabían que la mayoría de las personas que aprenden el lenguaje sabrían C / C ++ de antemano.
Por lo tanto, Java no solo se parece mucho a C / C ++ en lugar de decir smalltalk, sino que también se hizo cargo de las idiosincrasias de C / C ++ (solo piense en literales enteros octales). Dado que c / c ++ utilizan un método principal, hacer lo mismo para Java tiene sentido desde ese punto de vista.
Estoy bastante seguro de que recuerdo que Bloch o alguien dijo algo en este sentido sobre por qué agregaron literales enteros octales, veré si puedo encontrar algunas fuentes :)
fuente
:
aextends
? Ypublic static void main(String [ ] args)
dentro de una clase es bastante diferente queint main(int argc, char **argv)
fuera de una clase.:
aextends
es una cuestión de sintaxis y son esencialmente lo mismo. Todo lo demás está dictado por el idioma.main()
, cuando aparentemente no fue lo suficientemente importante en otros casos?Bueno, hay muchas funciones principales que solo ejecutan un bucle infinito. Un constructor que trabaja de esta manera (con un objeto que nunca se construye) es lo que me parece extraño.
Hay muchas cosas divertidas sobre este concepto. Su lógica se ejecuta sobre un objeto no nacido, objetos que nacen para morir (ya que hacen todo su trabajo en el constructor), ...
¿No todos estos efectos secundarios corromperían mucho más el vagón OO que un simple público (porque necesita ser accedido por un desconocido) estático (porque no se necesita ninguna instancia para comenzar) void main (porque es el punto de entrada )?
Para que exista un punto de entrada de función simple y simple en Java, se requerirá automáticamente public y static. Aunque es un método estático , se reduce a lo que podemos acercarnos más a una función simple para lograr lo que se desea: un simple punto de entrada.
Si no va a adoptar un punto de entrada de función simple y llano como punto de entrada. ¿Qué sigue después que no parece extraño como un constructor que no está destinado a construir?
fuente
Puede ejecutar rápidamente algunas pruebas independientes en una clase, durante el desarrollo, al pegar una
main()
en la clase que está tratando de probar.fuente
Tienes que empezar por alguna parte. Un entorno estático principal es el entorno de ejecución más simple que puede tener, no es necesario crear ninguna instancia (fuera de la JVM y los parámetros de cadena simples), por lo que puede "generar" un mínimo de alboroto (y baja probabilidad de un error de codificación que impide el inicio, etc.) y puede hacer cosas simples sin mucha otra configuración.
Básicamente una aplicación de KISS.
[Y, por supuesto, la razón principal es: ¿por qué no?]
fuente
A mi entender, la razón principal es simple. Sun era una compañía de Unix que vendía máquinas Unix y para eso se diseñó la convención C "main (args)" para invocar un binario .
Además, Java se diseñó explícitamente para que fuera fácil de aprender para los programadores de C y C ++, por lo que no había una buena razón para no simplemente elegir la convención de C.
El enfoque elegido donde cada clase puede tener un método de invocación es bastante flexible, especialmente en combinación con la
Main-Class
línea en el archivo MANIFEST.MF en un jar ejecutable.fuente
No es coherente con la filosofía OOP que un programa sea un objeto desde el punto de vista del proceso del sistema operativo, ya que no hay forma de tener más de uno por definición.
Además de eso, un constructor no es un punto de entrada de ninguna manera.
Me parece la opción más razonable para tener main como una función estática, que en realidad es al final del día. Dada la arquitectura de las máquinas virtuales como JVM y CLR, cualquier otra opción sería empujarla innecesariamente.
fuente
Runnable
objetos para que tengan múltiples hilos.