Por que o método principal do Java está estático?

A assinatura do método de um método main () do Java é:

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

Existe uma razão para este método ser estático?

O método é estático porque, do contrário, haveria ambigüidade: qual construtor deveria ser chamado? Especialmente se sua turma se parece com isso:

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

A JVM deve chamar o new JavaClass(int) ? O que deveria passar por x ?

Caso contrário, a JVM deve instanciar o JavaClass sem executar nenhum método construtor? Eu acho que não deveria, porque isso vai dar um caso especial a toda a sua class – às vezes você tem uma instância que não foi inicializada, e você tem que verificar isso em todos os methods que podem ser chamados.

Há muitos casos de borda e ambigüidades para fazer sentido que a JVM tenha que instanciar uma class antes que o ponto de input seja chamado. É por isso que o main é estático.

Eu não tenho idéia porque main é sempre marcado como public embora.

Isso é apenas convenção. Na verdade, até mesmo o nome main () e os argumentos transmitidos são puramente convencionais.

Quando você executa java.exe (ou javaw.exe no Windows), o que está realmente acontecendo é um par de chamadas Java Native Interface (JNI). Essas chamadas carregam a DLL que é realmente a JVM (isso mesmo – java.exe NÃO é a JVM). JNI é a ferramenta que usamos quando temos que unir o mundo das máquinas virtuais, o mundo de C, C ++, etc … O inverso também é verdade – não é possível (pelo menos que eu saiba) obter um JVM em execução sem usar o JNI.

Basicamente, java.exe é um aplicativo C super simples que analisa a linha de comando, cria uma nova matriz String na JVM para conter esses argumentos, analisa o nome da class que você especificou como contendo main (), usa chamadas JNI para localizar o O método main () propriamente dito, invoca o método main (), passando o array string criado recentemente como um parâmetro. Isso é muito, muito parecido com o que você faz quando usa o reflexo do Java – ele usa apenas chamadas de function nativas confusas.

Seria perfeitamente legal para você escrever sua própria versão do java.exe (a fonte é distribuída com o JDK) e fazer algo completamente diferente. Na verdade, é exatamente isso que fazemos com todos os nossos aplicativos baseados em Java.

Cada um dos nossos aplicativos Java tem seu próprio lançador. Nós fazemos isso principalmente para obter nosso próprio nome de ícone e processo, mas ele vem a calhar 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 nós realmente passamos um identificador COM para main () ao invés de um array de string).

Então, longo e curto: a razão é estática é b / c que é conveniente. A razão pela qual é chamado de ‘principal’ é que ele tinha que ser algo, e main () é o que eles faziam nos velhos tempos de C (e naqueles dias, o nome da function era importante). Eu suponho que java.exe poderia ter permitido que você apenas especificasse um nome de método principal totalmente qualificado, em vez de apenas a class (java com.mycompany.Foo.someSpecialMain) – mas isso só dificulta que os IDEs detectem automaticamente o ‘ “classs” em um projeto.

O método main () em C ++, C # e Java é estático porque pode ser chamado pelo mecanismo de tempo de execução sem ter que instanciar uma instância da class pai.

Por que public static void main (String [] args)?

É assim que a linguagem Java é projetada e a Java Virtual Machine é projetada e gravada.

Especificação de Linguagem Java da Oracle

Confira o capítulo 12 Execução – Seção 12.1.4 Invoque Test.main :

Finalmente, após a conclusão da boot para o teste de class (durante o qual outro carregamento, vinculação e boot conseqüentes podem ter ocorrido), o método principal do teste é chamado.

O método main deve ser declarado public, static e void. Ele deve aceitar um único argumento que seja uma matriz de seqüências de caracteres. Esse método pode ser declarado como

 public static void main(String[] args) 

ou

 public static void main(String... args) 

Especificação do Oracle Java Virtual Machine

Confira o Capítulo 2 Conceitos da linguagem de programação Java – Seção 2.17 Execução :

A máquina virtual Java inicia a execução chamando o método principal de alguma class especificada e passando a ele um único argumento, que é uma matriz de cadeias. Isso faz com que a class 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 public, static e void.

Oracle OpenJDK Source

Faça o download e extraia o jar de origem e veja como a JVM está gravada, verifique ../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); ... ... 

Vamos simplesmente fingir que a static não seria necessária como o ponto de input do aplicativo.

Uma class 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 o código do construtor e o método main é necessária porque no OO speak um construtor deve apenas certificar-se de que uma instância é inicializada corretamente. Após a boot, 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:

  • Deve haver um construtor padrão. Caso contrário, a JVM não saberia qual construtor chamar e quais parâmetros devem ser fornecidos.
  • Deve haver um método main 1 . Ok, isso não é surpreendente.
  • A turma não deve ser abstract . Caso contrário, a JVM não poderia instanciá-lo.

A abordagem static , por outro lado, requer apenas um contrato:

  • Deve haver um método main 1 .

Aqui nem abstract nem múltiplos construtores são importantes.

Como o Java foi projetado para ser uma linguagem simples para o usuário , não é surpresa que o ponto de input do aplicativo tenha sido projetado de maneira simples, usando um contrato e não de maneira complexa, usando três contratos independentes e frágeis.

Por favor note: Este argumento não é sobre simplicidade dentro da JVM ou dentro do JRE. Este argumento é sobre simplicidade para o usuário .


1 Aqui, a assinatura completa conta como apenas um contrato.

Se não foi, qual construtor deve ser usado se houver mais de um?

Há mais informações sobre a boot e a execução de programas Java disponíveis na Especificação da linguagem Java .

Antes do método principal ser chamado, nenhum object é instanciado. Ter a palavra-chave estática significa que o método pode ser chamado sem criar nenhum object primeiro.

Porque senão, precisaria de uma instância do object a ser executado. Mas ele deve ser chamado do zero, sem construir o object primeiro, já que geralmente é tarefa da function main () (bootstrap), analisar os argumentos e construir o object, geralmente usando esses argumentos / parâmetros de programa.

Qual é o significado de public static void main(String args[]) ?

  1. public é um especificador de access que significa que qualquer pessoa pode acessá-lo / invocá-lo, como JVM (Java Virtual Machine).
  2. static permite main() ser chamado antes que um object da class tenha sido criado. Isso é necessário porque main() é chamado pela JVM antes de qualquer object ser feito. Como é estático, pode ser invocado diretamente pela class.

     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 algum tempo para methods definidos pelo usuário, para que não precisemos criar objects.

  3. void indica que o método main() que está sendo declarado não retorna um valor.

  4. String[] args especifica o único parâmetro no método main() .

    args – um parâmetro que contém uma matriz de objects do tipo de class String .

Deixe-me explicar essas coisas de uma maneira muito mais simples:

 public static void main(String args[]) 

Todos os aplicativos Java, exceto os applets, iniciam sua execução a partir de main() .

A palavra-chave public é um modificador de access que permite que o membro seja chamado de fora da class.

static é usada porque permite que main() seja chamado sem ter que instanciar uma instância específica dessa class.

void indica que main() não retorna nenhum valor.

Applets, midlets, servlets e beans de vários tipos são construídos e, em seguida, são chamados methods de ciclo de vida. Invocar main é tudo o que já foi feito para a class principal, portanto, não há necessidade de um estado ser mantido em um object que é chamado várias vezes. É bastante normal colocar o principal em outra class (embora não seja uma ótima idéia), o que atrapalharia o uso da class para criar o object principal.

É apenas uma convenção, mas provavelmente mais conveniente que a alternativa. Com um main estático, tudo o que você precisa saber para invocar um programa Java é o nome e a localização de uma class. Se não fosse estático, você também teria que saber como instanciar essa class ou exigir que a class tenha um construtor vazio.

Se o método principal não fosse estático, você precisaria criar um object da sua class principal de fora do programa. Como você gostaria de fazer isso?

Quando você executa a Java Virtual Machine (JVM) com o comando java ,

 java ClassName argument1 argument2 ... 

Quando você executa seu aplicativo, você especifica seu nome de class como um argumento para o comando java, como acima

a JVM tenta chamar o método principal da class que você especifica

Neste ponto, nenhum object da class foi criado.

Declarar main como static allows a JVM invoke main without criar uma instance da class.

vamos voltar ao comando

ClassName é um command-line argument para a JVM que informa qual class executar. Seguindo o ClassName, você também pode especificar uma list of Strings (separadas por espaços) como argumentos da linha de comandos que a JVM passará para 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 arquivo principal.

Referências: Java ™ Como programar (primeiros objects), décima edição

Eu acho que a palavra-chave ‘static’ torna o método main um método de class, e os methods de class têm apenas uma cópia e podem ser compartilhados por todos, e também não requer um object para referência. Portanto, quando a class do driver é compilada, o método principal pode ser chamado. (Eu estou apenas no nível do alfabeto de java, desculpe se eu estou errado)

main () é estático porque; nesse ponto do ciclo de vida do aplicativo, a pilha do aplicativo é processual por não haver objects ainda instanciados.

É uma ardósia limpa. Seu aplicativo está sendo executado neste ponto, mesmo sem nenhum object sendo declarado (lembre-se, há padrões de codificação procedurais AND OO). Você, como desenvolvedor, transforma o aplicativo em uma solução orientada a objects criando instâncias de seus objects e dependendo do código compilado nele.

Orientado a objects é ótimo por milhões de razões óbvias. No entanto, foram os dias em que a maioria dos desenvolvedores de VB usava regularmente palavras-chave como “goto” em seu código. “goto” é um comando procedural no VB que é substituído por sua contraparte OO: chamada de método.

Você também pode olhar para o ponto de input estático (principal) como pura liberdade. Se Java tivesse sido diferente o suficiente para instanciar um object e apresentar apenas essa instância para você em execução, você não teria escolha, MAS para gravar um aplicativo procedural. Por mais inimaginável que possa parecer para Java, é possível que existam muitos cenários que exigem abordagens processuais.

Esta é provavelmente uma resposta muito obscura. Lembre-se, “class” é apenas uma coleção de códigos inter-relacionados. “Instância” é uma geração autônoma isolada, viva e que respira dessa class.

O protoype public static void main(String[]) é uma convenção definida no JLS :

O método main deve ser declarado public, static e void. Deve especificar um parâmetro formal (§8.4.1) cujo tipo declarado é array de String.

Na especificação da JVM 5.2. Partida de Máquina Virtual , podemos ler:

A máquina virtual Java é inicializada criando uma class inicial, que é especificada de maneira dependente da implementação, usando o carregador de classs de boot (§5.3.1). A máquina virtual Java, em seguida, vincula a class inicial, inicializa-a e chama o método de class pública void main (String []) . A invocação deste método conduz 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 a criação) de classs e interfaces adicionais, bem como a invocação de methods adicionais.

Engraçado, na especificação da JVM não é mencionado que o método principal tem que ser estático. Mas a especificação também diz que a máquina virtual Java executa 2 etapas antes:

  • liga a class inicial ( 5.4. Ligando )
  • inicializa-o ( 5.5. Inicialização )

A boot de uma class ou interface consiste em executar seu método de boot de class ou interface.

Em 2.9. Métodos Especiais :

Um método de boot de class ou interface é definido:

Uma class ou interface tem no máximo um método de boot de class ou interface e é inicializada (§5.5) invocando esse método. O método de boot de uma class ou interface tem o nome especial , não aceita argumentos e é inválido.

E um método de boot de class ou interface é diferente de um método de boot de instância definido como segue:

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 boot de instância que possui o nome especial .

Portanto, a JVM inicializa um método de boot de class ou interface e não um método de boot de instância que na verdade é 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 main.

Recentemente, uma pergunta semelhante foi publicada em Programmers.SE

  • Por que um método principal estático em Java e C #, em vez de um construtor?

    Procurando por 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 input – em vez de representar uma instância de aplicativo por uma instância de uma class Application , sendo o ponto de input um construtor apropriado?

TL; DR parte da resposta aceita é,

Em Java, o motivo de public static void main(String[] args) é que

  1. Gosling queria
  2. o código escrito por alguém com experiência em C (não em Java)
  3. para ser executado por alguém acostumado a executar o PostScript no NeWS

http://i.stack.imgur.com/qcmzP.png

Para C #, o raciocínio é transitivamente semelhante, por assim dizer. Os designers de linguagem mantiveram a syntax do ponto de input 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 …

É apenas uma convenção. A JVM certamente poderia lidar com methods principais não estáticos se essa fosse a convenção. Afinal, você pode definir um inicializador estático em sua class e instanciar um zilhão de objects antes de chegar ao seu método main ().

O verdadeiro ponto de input para qualquer aplicativo é um método estático. Se a linguagem Java suportasse um método de instância como o “ponto de input”, o tempo de execução precisaria implementá-lo internamente como um método estático que construiu uma instância do object seguido pela chamada do método de instância.

Com isso fora do caminho, examinarei a justificativa para escolher uma das três opções específicas a seguir:

  1. Um static void main() como vemos hoje.
  2. Um método de instância void main() chamou um object recém-construído.
  3. Usando o construtor de um tipo como ponto de input (por exemplo, se a class de input foi chamada de Program , a execução consistiria efetivamente em new Program() ).

Demolir:

static void main()

  1. Chama o construtor estático da class de inclusão.
  2. Chama o método estático main() .

void main()

  1. Chama o construtor estático da class de inclusão.
  2. Constrói uma instância da class new ClassName() chamando efetivamente new ClassName() .
  3. Chama o método da instância main() .

new ClassName()

  1. Chama o construtor estático da class de inclusão.
  2. Constrói uma instância da class (então não faz nada com ela e simplesmente retorna).

Fundamentação:

Eu vou na ordem inversa para este.

Tenha em mente que um dos objectives do design do Java era enfatizar (exigir quando possível) boas práticas de programação orientadas a objects. Neste contexto, o construtor de um object inicializa o object, mas não deve ser responsável pelo comportamento do object. Portanto, uma especificação que fornecesse um ponto de input de new ClassName() confundiria a situação para novos desenvolvedores Java forçando uma exceção ao design de um construtor “ideal” em cada aplicativo.

Ao tornar main() um método de instância, o problema acima é certamente resolvido. No entanto, ele cria complexidade exigindo que a especificação liste a assinatura do construtor da class de input, bem como a assinatura do método main() .

Em resumo, a especificação de um 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 methods . Considerando como é simples implementar um método main() que construa uma instância de uma class e chame um método de instância, não há vantagem real em especificar main() como um método de instância.

A palavra-chave public é um modificador de access, que permite ao programador controlar a visibilidade dos membros da class. When a class member is preceded by public , then that member may be accessed by code outside the class in which it is declared.

The opposite of public is private , which prevents a member from being used by code defined outside of its class.

In this case, main() must be declared as public , since it must be called by code outside of its class when the program is started.

The keyword static allows main() to be called without having to instantiate a particular instance of the class. This is necessary since main() is called by the Java interpreter before any objects are made.

The keyword void simply tells the compiler that main() does not return a value.

static – When the JVM makes a call to the main method there is no object that exists for the class being called therefore it has to have static method to allow invocation from class.

I don’t know if the JVM calls the main method before the objects are instantiated… But there is a far more powerful reason why the main() method is static… When JVM calls the main method of the class (say, Person). it invokes it by ” Person.main() “. You see, the JVM invokes it by the class name. That is why the main() method is supposed to be static and public so that it can be accessed by the JVM.

Hope it helped. If it did, let me know by commenting.

Static methods don’t require any object. It runs directly so main runs directly.

The static key word in the main method is used because there isn’t any instantiation that take place in the main method. But object is constructed rather than invocation as a result we use the static key word in the main method. In jvm context memory is created when class loads into it.And all static members are present in that memory. if we make the main static now it will be in memory and can be accessible to jvm (class.main(..)) so we can call the main method with out need of even need for heap been created.

It is just a convention as we can see here:

The method must be declared public and static , it must not return any value, and it must accept a String array as a parameter. By default, the first non-option argument is the name of the class to be invoked. A fully-qualified class name should be used. If the -jar option is specified, the first non-option argument is the name of a JAR archive containing class and resource files for the application, with the startup class indicated by the Main-Class manifest header.

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

The public static void keywords mean the Java virtual machine (JVM) interpreter can call the program’s main method to start the program (public) without creating an instance of the class (static), and the program does not return data to the Java VM interpreter (void) when it ends.

Source: Essentials, Part 1, Lesson 2: Building Applications

Basically we make those DATA MEMBERS and MEMBER FUNCTIONS as STATIC which are not performing any task related to an object. And in case of main method, we are making it as an STATIC because it is nothing to do with object, as the main method always run whether we are creating an object or not.

Any method declared as static in Java belongs to the class itself . Again static method of a particular class can be accessed only by referring to the class like Class_name.method_name();

So a class need not to be instantiated before accessing a static method.

So the main() method is declared as static so that it can be accessed without creating an object of that class.

Since we save the program with the name of the class where the main method is present( or from where the program should begin its execution, applicable for classs without a main() method()(Advanced Level)). So by the above mentioned way:

 Class_name.method_name(); 

the main method can be accessed.

In brief when the program is compiled it searches for the main() method having String arguments like: main(String args[]) in the class mentioned(ie by the name of the program), and since at the the beginning it has no scope to instantiate that class, so the main() method is declared as static.

there is the simple reason behind it that is because object is not required to call static method , if It were non-static method, java virtual machine creates object first then call main() method that will lead to the problem of extra memory allocation.