A assinatura do método de um método Java main () é:
public static void main(String[] args){
...
}
Existe uma razão para esse método ser estático?
A assinatura do método de um método Java main () é:
public static void main(String[] args){
...
}
Existe uma razão para esse método ser estático?
Respostas:
O método é estático porque, caso contrário, haveria ambiguidade: qual construtor deve ser chamado? Especialmente se a sua turma estiver assim:
public class JavaClass{
protected JavaClass(int x){}
public void main(String[] args){
}
}
A JVM deve ligar new JavaClass(int)
? O que deveria passar x
?
Caso contrário, a JVM deve instanciar JavaClass
sem executar nenhum método construtor? Eu acho que não deveria, porque isso será um caso especial para toda a classe - às vezes você tem uma instância que não foi inicializada e precisa verificar em todos os métodos que podem ser chamados.
Existem muitos casos extremos e ambiguidades para que faça sentido para a JVM instanciar uma classe antes que o ponto de entrada seja chamado. É por isso que main
é estático.
Eu não tenho idéia do por que main
está sempre marcado public
.
public static void main
serve como um marcador de um ponto de entrada - um construtor público sem parâmetros não grita "Este é provavelmente um ponto de entrada!" do mesmo jeito.
main
a ser chamada. Estranhamente (para você), a JVM gerencia isso muito bem.
Isso é apenas convenção. De fato, mesmo o nome main () e os argumentos passados são puramente convenções.
Quando você executa o java.exe (ou javaw.exe no Windows), o que realmente está acontecendo são algumas chamadas JNI (Java Native Interface). Essas chamadas carregam a DLL que é realmente a JVM (isso mesmo - java.exe NÃO é a JVM). O JNI é a ferramenta que usamos quando precisamos fazer uma ponte entre o mundo das máquinas virtuais e o mundo de C, C ++, etc ... O inverso também é verdadeiro - não é possível (pelo menos que eu saiba) obter um JVM em execução sem usar JNI.
Basicamente, java.exe é um aplicativo C super simples que analisa a linha de comando, cria uma nova matriz String na JVM para armazenar esses argumentos, analisa o nome da classe que você especificou como contendo main (), usa chamadas JNI para encontrar o O método main (), em seguida, chama o método main (), passando a matriz de cadeias recém-criada como parâmetro. Isso é muito, muito parecido com o que você faz quando usa a reflexão do Java - apenas usa chamadas de função nativas com nomes confusos.
Seria perfeitamente legal escrever sua própria versão do java.exe (a fonte é distribuída com o JDK) e fazer com que ele fizesse algo totalmente diferente. De fato, é exatamente isso que fazemos com todos os nossos aplicativos baseados em Java.
Cada um dos nossos aplicativos Java possui seu próprio iniciador. Primeiramente, fazemos isso para obter nosso próprio ícone e nome de processo, mas ele foi útil em outras situações em que queremos fazer algo além da chamada regular main () para fazer as coisas funcionarem (por exemplo, em um caso, estamos fazendo Interoperabilidade COM e, na verdade, passamos um identificador COM para main () em vez de uma matriz de strings).
Então, longo e curto: a razão pela qual é estático é b / c que é conveniente. O motivo pelo qual é chamado 'main' é que tinha que ser alguma coisa, e main () é o que eles faziam nos velhos tempos de C (e naqueles dias, o nome da função era importante). Suponho que java.exe poderia permitir que você especificasse apenas um nome de método principal totalmente qualificado, em vez de apenas a classe (java com.mycompany.Foo.someSpecialMain) - mas isso dificulta a identificação automática dos IDEs por ' classes 'iniciáveis' em um projeto.
java.exe
)
static
a main()
declaração seja apenas por uma questão de convenção. O fato de ser `main () 'e não de outra coisa é possível, no entanto.
main
não estático e ainda assim se encaixam dentro dos limites da linguagem. Sem ouvir os designers, teremos que concordar em discordar. :)
O main()
método C++
, C#
e Java
são estáticos
Porque eles podem, então, ser invocado pelo mecanismo de tempo de execução sem ter que instanciar todos os objetos, em seguida, o código no corpo main()
fará o resto.
public static void main...
, por que não poderia ser a convenção de que a classe de ponto de entrada do aplicativo deveria ter um construtor público padrão?
static void main
chamar? Não um problema de todos.
static
métodos como main
os usados new
com frequência para criar esse objeto.
É assim que a linguagem Java é projetada e a Java Virtual Machine é projetada e escrita.
Confira o Capítulo 12 Execução - Seção 12.1.4 Invoke Test.main :
Finalmente, após a conclusão da inicialização da classe Test (durante a qual outros carregamentos, links e inicialização consequentes podem ter ocorrido), o método principal do Teste é chamado.
O método main deve ser declarado público, estático e sem efeito. Ele deve aceitar um único argumento que é uma matriz de seqüências de caracteres. Este método pode ser declarado como
public static void main(String[] args)
ou
public static void main(String... args)
Confira o Capítulo 2 Conceitos da linguagem de programação Java - Seção 2.17 .
A máquina virtual Java inicia a execução invocando o método main de alguma classe especificada e passando a ele um único argumento, que é uma matriz de cadeias. Isso faz com que a classe especificada seja carregada (§2.17.2), vinculada (§2.17.3) a outros tipos que ela usa e inicializada (§2.17.4). O método main deve ser declarado público, estático e sem efeito.
Faça o download e extraia o jar de origem e veja como a JVM é gravada; confira ../launcher/java.c
, que contém o código C nativo por trás do 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
não for estático, significa que o estado da instância da classe deve ser conhecido e é muito mais complexo definir, como qual construtor usar primeiro.
public static void main(String arguments[])
- Referência: Oak 0.2 Spec .
Runnable
. Representar todo o processo da mesma maneira (isto é, ter Runnable.Run
como ponto de entrada) definitivamente faz sentido em Java. Obviamente, Runnable
ele próprio é indiscutivelmente uma falha de design, causada pelo fato de o Java ainda não ter métodos anônimos. Mas como já está lá…
Vamos simplesmente fingir que static
isso não seria necessário como ponto de entrada do aplicativo.
Uma classe de aplicativo ficaria assim:
class MyApplication {
public MyApplication(){
// Some init code here
}
public void main(String[] args){
// real application code here
}
}
A distinção entre código e main
método do construtor é necessária porque, em OO, o construtor deve apenas garantir que uma instância seja inicializada corretamente. Após a inicialização, a instância pode ser usada para o "serviço" pretendido. Colocar o código completo do aplicativo no construtor estragaria isso.
Portanto, essa abordagem forçaria três contratos diferentes no aplicativo:
main
método 1 . Ok, isso não é surpreendente.abstract
. Caso contrário, a JVM não poderia instancia-lo.A static
abordagem, por outro lado, requer apenas um contrato:
main
método 1 .Aqui abstract
nem vários construtores são importantes.
Como o Java foi projetado para ser uma linguagem simples para o usuário , não surpreende que também o ponto de entrada do aplicativo tenha sido projetado de maneira simples, usando um contrato, e não de maneira complexa, usando três contratos independentes e quebradiços.
Observe: Este argumento não é sobre simplicidade dentro da JVM ou dentro do JRE. Este argumento é sobre simplicidade para o usuário .
main
método que é public
, static
e tem a assinatura void main(String[])
. Concordo que, se o método fosse um método de instância, o JRE teria um pouco mais de trabalho, mas o tipo de trabalho seria o mesmo e a complexidade não significativamente maior (consulte as discussões nos comentários da resposta anterior). Não acredito que essa diferença seja responsável pela decisão de tornar o ponto de entrada estático, principalmente porque os métodos necessários para a resolução de um método de instância existem e são facilmente utilizáveis.
static public main(String[])
método é uma assinatura e, portanto, um contrato. Caso contrário, três contratos independentes devem ser seguidos.
Runnable
. Claramente, o Java espera que os desenvolvedores sigam esse contrato o tempo todo, por que deveria ser demais para o ponto de entrada do aplicativo? Isso não faz sentido.
Thread
e Runnable
caso nada oculte do usuário, ele pode ver claramente o que está acontecendo e ele tem a alteração para implementar apenas os contratos que lhe convêm - ele está no controle, não no sistema.
Caso contrário, qual construtor deve ser usado se houver mais de um?
Há mais informações sobre a inicialização e execução de programas Java disponíveis no Java Language Specification .
Antes que o método principal seja chamado, nenhum objeto é instanciado. Ter a palavra-chave estática significa que o método pode ser chamado sem criar nenhum objeto primeiro.
Porque, caso contrário, seria necessário que uma instância do objeto fosse executada. Mas deve ser chamado do zero, sem construir o objeto primeiro, pois geralmente é a tarefa da função main () (bootstrap) analisar os argumentos e construir o objeto, geralmente usando esses argumentos / parâmetros do programa.
Deixe-me explicar essas coisas de uma maneira muito mais simples:
public static void main(String args[])
Todos os aplicativos Java, exceto os miniaplicativos, iniciam sua execução main()
.
A palavra public
- chave é um modificador de acesso que permite que o membro seja chamado de fora da classe.
static
é usado porque permite main()
ser chamado sem precisar instanciar uma instância específica dessa classe.
void
indica que main()
não retorna nenhum valor.
Qual é o significado de public static void main(String args[])
?
public
é um especificador de acesso, o que significa que qualquer pessoa pode acessá-lo / invocá-lo, como JVM (Java Virtual Machine).static
permite main()
ser chamado antes que um objeto da classe seja criado. Isso é necessário porque main()
é chamado pela JVM antes de qualquer objeto ser criado. Por ser estático, pode ser chamado diretamente através da classe
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 */
}
}
Da mesma forma, usamos estática em algum momento para métodos definidos pelo usuário, de forma que não precisamos criar objetos.
void
indica que o main()
método que está sendo declarado não retorna um valor.
String[] args
especifica o único parâmetro no main()
método
args
- um parâmetro que contém uma matriz de objetos do tipo classe String
.
Applets, midlets, servlets e beans de vários tipos são construídos e, em seguida, têm métodos de ciclo de vida necessários. A chamada de main é tudo o que é feito na classe principal, portanto, não há necessidade de um estado ser mantido em um objeto chamado várias vezes. É bastante normal fixar main em outra classe (embora não seja uma ótima idéia), o que atrapalharia o uso da classe para criar o objeto principal.
É apenas uma convenção, mas provavelmente mais conveniente que a alternativa. Com um main estático, tudo o que você precisa saber para chamar um programa Java é o nome e o local de uma classe. Se não fosse estático, você também teria que saber como instanciar essa classe ou exigir que a classe tenha um construtor vazio.
Quando você executa a Java Virtual Machine (JVM) com o java
comando,
java ClassName argument1 argument2 ...
Ao executar seu aplicativo, você especifica o nome da classe como um argumento para o comando java, como acima
a JVM tenta chamar o método principal da classe especificada
- neste ponto, nenhum objeto da classe foi criado.
Declarando
main
estáticaallows
a JVM comoinvoke
principalwithout
criando uminstance
da classe.
vamos voltar ao comando
ClassName
é um command-line argument
para a JVM que informa qual classe executar. Após o ClassName, você também pode especificar a list of Strings
(separado por espaços) como argumentos da linha de comandos que a JVM passará para o seu aplicativo. - Esses argumentos podem ser usados para especificar opções (por exemplo, um nome de arquivo) para executar o aplicativo - é por isso que existe um parâmetro chamado String[] args
no diretório principal.
Referências: Java ™ Como Programar (Objetos Antigos), Décima Edição
Recentemente, uma pergunta semelhante foi publicada em Programmers.SE
Procurando uma resposta definitiva de uma fonte primária ou secundária, por que (notavelmente) 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?
TL; DR parte da resposta aceita é,
Em Java, o motivo
public static void main(String[] args)
é que
- Gosling queria
- o código escrito por alguém com experiência em C (não em Java)
- para ser executado por alguém acostumado a executar o PostScript no NeWS
Para 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 C # Anders Hejlsberg coloca ,... nossa abordagem com C # foi simplesmente oferecer uma alternativa ... aos programadores Java ...
...
Eu acho que a palavra-chave 'static' torna o método principal um método de classe, e os métodos de classe têm apenas uma cópia e podem ser compartilhados por todos, além de não exigir um objeto para referência. Portanto, quando a classe do driver é compilada, o método principal pode ser chamado. (Estou apenas no nível do alfabeto de java, desculpe se estou errado)
main () é estático porque; nesse ponto do ciclo de vida do aplicativo, a pilha de aplicativos é procedural por natureza, porque ainda não existem objetos instanciados.
É uma lousa limpa. Seu aplicativo está sendo executado neste momento, mesmo sem que nenhum objeto seja declarado (lembre-se, existem padrões de codificação de procedimento e OO). Você, como desenvolvedor, transforma o aplicativo em uma solução orientada a objetos, criando instâncias de seus objetos e dependendo do código compilado.
A orientação a objetos é ótima por milhões de razões óbvias. No entanto, já se foram os dias em que a maioria dos desenvolvedores de VB usava regularmente palavras-chave como "goto" em seu código. "goto" é um comando processual no VB que é substituído por sua contraparte OO: invocação de método.
Você também pode considerar o ponto de entrada estático (principal) como pura liberdade. Se o Java tivesse sido diferente o suficiente para instanciar um objeto e apresentar apenas essa instância para você em execução, você não teria escolha, MAS escrever um aplicativo procedural. Por mais inimaginável que possa parecer para Java, é possível que haja muitos cenários que exijam abordagens processuais.
Esta é provavelmente uma resposta muito obscura. Lembre-se de que "classe" é apenas uma coleção de códigos inter-relacionados. "Instância" é uma geração autônoma isolada, viva e respiratória dessa classe.
main
serem atingidos. E se você incluir um construtor estático na classe que contém main, isso será executado antes da main
mesma forma.
O protoype public static void main(String[])
é uma convenção definida no JLS :
O método main deve ser declarado público, estático e sem efeito. Ele deve especificar um parâmetro formal (§8.4.1) cujo tipo declarado é matriz de String.
Na especificação da JVM 5.2. Inicialização da máquina virtual , podemos ler:
A máquina virtual Java é iniciada criando uma classe inicial, especificada de uma maneira dependente da implementação, usando o carregador de classes de autoinicialização (§5.3.1). A máquina virtual Java vincula a classe inicial, inicializa-a e chama o método de classe pública void main (String []) . A invocação desse método direciona toda a execução adicional. A execução das instruções da máquina virtual Java que constituem o método principal pode causar a vinculação (e consequentemente criação) de classes e interfaces adicionais, bem como a invocação de métodos adicionais.
O engraçado é que, na especificação da JVM, não há menção de que o método principal precise ser estático. Mas a especificação também diz que a máquina virtual Java executa duas etapas antes:
A inicialização de uma classe ou interface consiste em executar seu método de inicialização de classe ou interface.
Um método de inicialização de classe ou interface é definido:
Uma classe ou interface possui no máximo um método de inicialização de classe ou interface e é inicializada (§5.5) invocando esse método. O método de inicialização de uma classe ou interface tem o nome especial
<clinit>
, não aceita argumentos e é nulo.
E um método de inicialização de classe ou interface é diferente de um método de inicialização de instância definido da seguinte maneira:
No nível da máquina virtual Java, todo construtor escrito na linguagem de programação Java (JLS §8.8) aparece como um método de inicialização de instância que possui o nome especial
<init>
.
Portanto, a JVM inicializa um método de inicialização de classe ou interface e não um método de inicialização de instância que é realmente um construtor. Portanto, eles não precisam mencionar que o método principal deve ser estático na especificação da JVM, porque está implícito no fato de que nenhuma instância é criada antes de chamar o método principal.
A public
palavra-chave é um modificador de acesso, que permite ao programador controlar a visibilidade dos membros da classe. Quando um membro da classe é precedido por public
, esse membro pode ser acessado por código fora da classe na qual é declarado.
O oposto de public
é private
, que impede que um membro seja usado pelo código definido fora de sua classe.
Nesse caso, main()
deve ser declarado como public
, pois deve ser chamado por código fora de sua classe quando o programa for iniciado.
A palavra-chave static
permite
main()
ser chamada sem ter que instanciar uma instância específica da classe. Isso é necessário, pois main()
é chamado pelo interpretador Java antes de qualquer objeto ser criado.
A palavra-chave void
simplesmente informa ao compilador que main()
não retorna um valor.
O verdadeiro ponto de entrada para qualquer aplicativo é um método estático. Se a linguagem Java suportasse um método de instância como o "ponto de entrada", o tempo de execução precisaria implementá-lo internamente como um método estático que construiu uma instância do objeto seguida por chamar o método de instância.
Com isso fora do caminho, examinarei a justificativa para escolher uma das três opções a seguir:
static void main()
como a vemos hoje.void main()
chamado em um objeto recém-construído.Program
, a execução consistirá efetivamente new Program()
).static void main()
main()
.void main()
new ClassName()
.main()
.new ClassName()
Eu vou na ordem inversa para este.
Lembre-se de que um dos objetivos de design do Java era enfatizar (exigir quando possível) boas práticas de programação orientada a objetos. Nesse contexto, o construtor de um objeto inicializa o objeto, mas não deve ser responsável pelo comportamento do objeto. Portanto, uma especificação que forneceu um ponto de entrada new ClassName()
confundiria a situação dos novos desenvolvedores Java, forçando uma exceção ao design de um construtor "ideal" em cada aplicativo.
Ao criar main()
um método de instância, o problema acima certamente está resolvido. No entanto, cria complexidade exigindo que a especificação liste a assinatura do construtor da classe de entrada, bem como a assinatura do main()
método.
Em resumo, especificar a static void main()
cria uma especificação com a menor complexidade, ao mesmo tempo em que adere ao princípio de colocar o comportamento em métodos . Considerando o quão simples é implementar um main()
método que constrói uma instância de uma classe e chama um método de instância, não há vantagem real em especificar main()
como método de instância.
main
. Sua lógica de main
ser complexo demais para iniciantes parece inacreditável. De fato, a estática main
é muito confusa para iniciantes, duvido que um construtor seria mais. Você diz que um "construtor não deve ser responsável pelo comportamento do objeto". Parece interessante, mas não tenho certeza se concordo. Por que não? O que impede isso?
static - Quando a JVM faz uma chamada para o método principal, não existe nenhum objeto para a classe que está sendo chamada, portanto, ele deve ter um método estático para permitir a chamada da classe.
Não sei se a JVM chama o método principal antes que os objetos sejam instanciados ... Mas há uma razão muito mais poderosa pela qual o método main () é estático ... Quando a JVM chama o método principal da classe (por exemplo, , Pessoa). ele chama por " Person.main () ". Veja bem, a JVM a chama pelo nome da classe. É por isso que o método main () deve ser estático e público para que possa ser acessado pela JVM.
Espero que tenha ajudado. Se isso acontecer, avise-me comentando.
A palavra-chave estática no método principal é usada porque não existe nenhuma instanciação no método principal. Mas o objeto é construído em vez de invocação, como resultado, usamos a palavra-chave estática no método principal. No contexto da jvm, a memória é criada quando a classe é carregada nela. E todos os membros estáticos estão presentes nessa memória. se tornarmos o main estático agora, ele estará na memória e poderá ser acessado pelo jvm (class.main (..)) para que possamos chamar o método principal sem a necessidade de criar heap.
É apenas uma convenção, como podemos ver aqui:
O método deve ser declarado público e estático , não deve retornar nenhum valor e deve aceitar uma matriz String como parâmetro. Por padrão, o primeiro argumento não opcional é o nome da classe a ser chamada. Um nome de classe totalmente qualificado deve ser usado. Se a opção -jar for especificada, o primeiro argumento de não opção é o nome de um archive JAR contendo arquivos de classe e recursos para o aplicativo, com a classe de inicialização indicada pelo cabeçalho de manifesto da Classe Principal.
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html#description
As palavras-chave void estáticas públicas significam que o interpretador da Java virtual machine (JVM) pode chamar o método principal do programa para iniciar o programa (público) sem criar uma instância da classe (estática), e o programa não retorna dados para o interpretador Java VM (nulo) quando terminar.
Basicamente, tornamos os MEMBROS DE DADOS e FUNÇÕES DOS MEMBROS como estáticos que não estão executando nenhuma tarefa relacionada a um objeto. E, no caso do método principal, estamos fazendo isso como STATIC, porque não tem nada a ver com objeto, pois o método principal sempre é executado, quer estejamos criando um objeto ou não.
Qualquer método declarado como estático em Java pertence à própria classe. Novamente, o método estático de uma classe específica pode ser acessado apenas consultando a classe comoClass_name.method_name();
Portanto, uma classe não precisa ser instanciada antes de acessar um método estático.
Portanto, o método main () é declarado static
para que possa ser acessado sem criar um objeto dessa classe.
Como salvamos o programa com o nome da classe em que o método principal está presente (ou de onde o programa deve iniciar sua execução, aplicável a classes sem um main()
método () (Nível Avançado)). Então, da maneira mencionada acima:
Class_name.method_name();
o método principal pode ser acessado.
Resumidamente, quando o programa é compilado, ele procura o main()
método com String
argumentos como: main(String args[])
na classe mencionada (ou seja, pelo nome do programa) e, desde o início, não tem escopo para instanciar essa classe, portanto, o main () O método é declarado como estático.
Em java.sun.com (há mais informações no site):
O método principal é estático para fornecer ao interpretador Java VM uma maneira de iniciar a classe sem criar primeiro uma instância da classe de controle. Instâncias da classe de controle são criadas no método principal após o início do programa.
Meu entendimento sempre foi simplesmente o de que o método principal, como qualquer método estático, pode ser chamado sem criar uma instância da classe associada, permitindo que ele seja executado antes de qualquer outra coisa no programa. Se não fosse estático, você teria que instanciar um objeto antes de chamá-lo - o que cria um problema de 'galinha e ovo', pois o método principal geralmente é o que você usa para instanciar objetos no início do programa.
Runnable
) em Java fazer usar este projeto. Por que a exceção (aparente) aqui?