Estou procurando uma resposta definitiva de uma fonte primária ou secundária para saber por que (principalmente) Java e C # decidiram ter um método estático como ponto de entrada, em vez de representar uma instância de aplicativo por uma instância de uma Application
classe (com o ponto de entrada sendo um construtor apropriado).
Antecedentes e detalhes da minha pesquisa anterior
Isso já foi perguntado antes. Infelizmente, as respostas existentes estão apenas implorando a pergunta . Em particular, as seguintes respostas não me satisfazem, pois as considero incorretas:
- Haveria ambiguidade se o construtor estivesse sobrecarregado. - De fato, o C # (assim como o C e o C ++) permite assinaturas diferentes para
Main
que exista a mesma ambiguidade potencial e seja tratada. - Um
static
método significa que nenhum objeto pode ser instanciado antes, para que a ordem de inicialização seja clara. - Isso é realmente errado, alguns objetos são instanciados antes (por exemplo, em um construtor estático). - Portanto, eles podem ser chamados pelo tempo de execução sem precisar instanciar um objeto pai. - Isso não é resposta.
Apenas para justificar ainda mais por que acho que essa é uma pergunta válida e interessante:
Muitas estruturas de fazer usar classes para representar aplicativos e construtores como pontos de entrada. Por exemplo, a estrutura do aplicativo VB.NET usa um diálogo principal dedicado (e seu construtor) como ponto de entrada 1 .
Nem Java nem C # tecnicamente precisam de um método principal. Bem, o C # precisa de um para compilar, mas o Java nem isso. E em nenhum dos casos é necessário para execução. Portanto, isso não parece ser uma restrição técnica. E, como mencionei no primeiro parágrafo, para uma mera convenção, parece estranhamente inadequado com o princípio geral de design de Java e C #.
Para ser claro, não há uma desvantagem específica em ter um main
método estático , é apenas distintamente estranho , o que me fez pensar se havia alguma lógica técnica por trás dele.
Estou interessado em uma resposta definitiva de uma fonte primária ou secundária, não em meras especulações.
1 Embora exista um retorno de chamada ( Startup
) que possa interceptar isso.
fonte
Respostas:
TL; DR
Em Java, o motivo
public static void main(String[] args)
é quePara C #, o raciocínio é transitivamente semelhante, por assim dizer. Os designers de linguagem mantinham a sintaxe do ponto de entrada do programa familiar para programadores vindos de Java. Como o arquiteto de C # Anders Hejlsberg coloca ,
Versão longa
expandindo acima e apoiado com referências chatas.
java Terminator Tem que ver Baby!
Especificações da VM, 2.17.1 Inicialização da máquina virtual
... veja também: Apêndice: Preciso de suas roupas, suas botas e sua motocicleta
execução direcionada para uso como scripts típicos na interface da linha de comandos.
passo importante
... isso ajuda a evitar alguns traços falsos em nossa investigação.
Especificações da VM, 1.2 A Java Virtual Machine
Notei acima ao estudar o capítulo anterior - 1.1 História, que pensei que poderia ser útil (mas acabou sendo inútil).
execução é governada apenas pelas especificações da VM, que
declara explicitamente que não tem nada a ver com a linguagem Java
=> OK para ignorar o JLS e qualquer coisa relacionada à linguagem Java.
Gosling: um compromisso entre C e linguagem de script ...
Com base no exposto, comecei a pesquisar na web o histórico da JVM . Não ajudou, muito lixo nos resultados.
Então, lembrei de lendas sobre Gosling e reduzi minha pesquisa à história da JVM de Gosling .
Eureka! Como a especificação da JVM veio a ser
declaração explícita de que, no momento da criação,
C e scripts foram considerados as influências mais importantes.
Já visto aceno para scripting em VM Spec 2.17.1,
argumentos de linha de comando suficientemente explicar
String[] args
, mas
static
emain
não estão lá ainda, necessidade de cavar ainda mais ...Observe que, ao digitar isso - conectando C, scripts e VM Spec 1.2 com seu nada de Java -, sinto-me algo familiar, algo ... orientado a objetos está lentamente desaparecendo. Pegue minha mão e continue andando Não diminua a velocidade, estamos quase lá agora
Os slides do Keynote estão disponíveis on-line: 20_Gosling_keynote.pdf , bastante conveniente para copiar pontos-chave.
A-ha! Vamos olhar mais de perto a sintaxe C .
Estamos chegando mais perto? pode apostar. Também vale a pena seguir o link "principal" da citação acima:
Para ser confortável para o desenvolvedor C, o ponto de entrada do programa deve ser
main
.Além disso, como o Java exige que qualquer método esteja na classe,
Class.main
é omais próximo possível: invocação estática, apenas nome e ponto da classe,
sem construtores, por favor - C não sabe nada disso.
Isso também se aplica transitivamente ao C #, levando em consideração
a idéia de fácil migração para ele do Java.
Os leitores que pensam que o ponto de entrada do programa familiar não importa são convidados a pesquisar e verificar as perguntas do Stack Overflow em que pessoas do Java SE estão tentando escrever o Hello World para Java ME MIDP. Nota O ponto de entrada MIDP não possui
main
nemstatic
.Conclusão
Com base no exposto, eu diria isso e
static
, nos momentos de criação de Java e C #, as escolhas mais razoáveis para definir o ponto de entrada do programa .main
String[] args
Apêndice: Preciso de suas roupas, suas botas e sua motocicleta
Tenho que admitir, ler o VM Spec 2.17.1 foi muito divertido.
Referências simbólicas de
Terminator
oh sim.fonte
Isso me parece vagamente abusivo. Um construtor é usado para a inicialização de um objeto: ele configura um objeto, que é então usado pelo código que o criou.
Se você colocar a funcionalidade básica de uso dentro do construtor e nunca usar realmente o objeto que o construtor cria no código externo, estará violando os princípios do OOP. Basicamente, fazer algo realmente estranho sem motivo aparente.
Por que você faria isso de qualquer maneira?
fonte
Main
método funciona bem para o caso simples e não é realmente um problema em casos mais difíceis; então, por que não?Para Java, acho que o raciocínio é simples: ao desenvolver Java, os desenvolvedores sabiam que a maioria das pessoas que aprendia a linguagem conheceria C / C ++ de antemão.
Portanto, o Java não apenas se parece muito com o C / C ++ em vez de dizer smalltalk, mas também assumiu as idiossincrasias do C / C ++ (pense apenas em literais inteiros octais). Como o c / c ++ usa um método principal, fazer o mesmo para java fazia sentido desse ponto de vista.
Tenho certeza de que me lembro de bloch ou de alguém dizendo algo nesse sentido sobre por que eles adicionaram literais de número inteiro octal, vou ver se consigo encontrar algumas fontes :)
fonte
:
paraextends
? Epublic static void main(String [ ] args)
dentro de uma classe é bem diferente do queint main(int argc, char **argv)
fora de uma classe.:
paraextends
é uma questão de sintaxe e é essencialmente o mesmo. Todo o resto é ditado pelo idioma.main()
, quando aparentemente não era importante o suficiente em outros casos?Bem, existem muitas funções principais por aí que executam um loop infinito. Um construtor que trabalha dessa maneira (com um objeto que nunca é construído) é o que me parece estranho.
Há tantas coisas engraçadas sobre esse conceito. Sua lógica rodando em cima de um objeto por nascer, objetos que nasceram para morrer (já que eles fazem todo o seu trabalho no construtor), ...
Todos esses efeitos colaterais não corromperão muito mais o vagão OO do que um simples público (porque precisa ser acessado por um desconhecido) estático (porque nenhuma instância é necessária para começarmos) void main (porque é o ponto de entrada )?
Para que um ponto de entrada de função simples e simples exista em Java, público e estático seriam automaticamente necessários. Embora seja um método estático , tudo se resume ao que podemos obter mais perto de uma função simples para realizar o que se deseja: um simples ponto de entrada.
Se você não adotará um ponto de entrada de função simples e claro como um ponto de entrada. O que vem a seguir que não parece estranho como um empreiteiro que não deve ser construído?
fonte
Você pode executar rapidamente alguns testes independentes em uma classe, durante o desenvolvimento, colocando um
main()
na classe que você está tentando testar.fonte
Você tem que começar de algum lugar. Um main estático é o ambiente de execução mais simples que você pode ter - nenhuma instância de nada (fora da JVM e dos parâmetros simples de cadeia de caracteres) precisa ser criada - para que possa "surgir" com um mínimo de confusão (e baixa probabilidade de um erro de codificação que impede a inicialização, etc.) e pode fazer coisas simples sem muitas outras configurações.
Basicamente, uma aplicação do KISS.
[E, claro, o principal motivo é: por que não?]
fonte
Para meu entendimento, a principal razão é simples. A Sun era uma empresa Unix que vendia máquinas Unix e Unix é para o que foi projetada a convenção C "principal (args)" para invocar um binário .
Além disso, o Java foi projetado explicitamente para ser fácil de entender para os programadores de C e C ++, portanto não havia uma boa razão para simplesmente não aceitar a convenção em C.
A abordagem escolhida na qual todas as classes podem ter um método de chamada é bastante flexível, especialmente em combinação com a
Main-Class
linha no arquivo MANIFEST.MF em um jar executável.fonte
Não é consistente com a filosofia OOP que um programa seria um objeto do ponto de vista do processo do SO, pois não há como ter mais de um por definição.
Além disso, um construtor não é um ponto de entrada de forma alguma.
Parece-me a escolha mais razoável de ter principal como uma função estática, o que realmente é no final do dia. Dada a arquitetura de VMs como JVM e CLR, qualquer outra opção seria desnecessária.
fonte
Runnable
objetos para ter vários threads.