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


505

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?


1
neste caso, não devemos dizer a assinatura do método , porque o termo refere-se apenas aos nomes de método e seus parâmetros
Andrew Tobilko

O Java foi projetado deliberadamente para parecer familiar para um programador em C. Isso é muito próximo da convenção C.
Thorbjørn Ravn Andersen

Respostas:


337

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 JavaClasssem 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 mainestá sempre marcado public.


4
A implementação de uma interface não resolve o problema da instanciação.
precisa

26
Pessoalmente, gosto disso public static void mainserve 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.
Jacob Krall

5
@ EdwinDalorzo - O que seria ganho forçando a classe de ponto de entrada a ser instanciada? Chamar um método estático coloca a menor quantidade de carga na classe. É gratuito se instanciar, se isso faz mais sentido para o seu design.
David Harkness

18
"Qual construtor deve ser chamado?" Como isso é um problema concebível ? O mesmo "problema" existe para a decisão maina ser chamada. Estranhamente (para você), a JVM gerencia isso muito bem.
21912 Konrad Rudolph

9
O método principal é sempre público porque deve ser acessado pelo mecanismo de tempo de execução, a JVM.
Gthm

398

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.


66
+1: Muito fascinante (especialmente a parte sobre a escrita de um costume java.exe)
Adam Paynter

9
Interessante, eu discordo do "Isso é apenas uma convenção". Parte da resposta. A principal questão do OP foi o motivo da estática na declaração. Não acho que statica 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.
Jared

2
@ David Assim foi. Na verdade, eu teria preferido uma resposta de uma das pessoas originalmente envolvidas - mas isso foi muito longe. Infelizmente, a maioria das outras respostas é um exercício de raciocínio ad-hoc. Este fornece detalhes bastante interessantes, além de ter a humildade de não inventar detalhes técnicos errados para justificar uma causa (provavelmente) não técnica.
21912 Konrad Rudolph

2
@ Jared - Eles poderiam ter exigido um construtor público sem argumentos e tornado mainnão estático e ainda assim se encaixam dentro dos limites da linguagem. Sem ouvir os designers, teremos que concordar em discordar. :)
David Harkness

4
@BenVoigt Você chama LoadLibrary () para obter a dll jvm. Em seguida, chame getprocaddress ("JNI_CreateJavaVM") e invoque a função JNI_CreateJavaVM ( docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/… ). Depois que a VM é carregada, você usa chamadas JNI padrão para encontrar a classe correta, carregue o método principal estático e invoque-o. Não há muito espaço para interpretações erradas lá. JNI é absolutamente como você carrega a VM. Você pode estar acostumado a escrever apenas JNI do lado do cliente usando a palavra-chave nativa, javah -jni, etc ... mas isso é apenas metade da JNI.
Kevin dia

188

O main()método C++, C#e Javasã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.


1
Tudo bem, mas o tempo de execução não poderia instanciar um objeto da classe? E, em seguida, chame o método Main? Por quê?
Andrei Rînea

12
Como a JVM saberia qual construtor chamar, se sua classe principal sobrecarregasse os construtores? Quais parâmetros ele passaria?
24630 Jacob Krall

1
@Noah, quando você diz classe pai, você quer dizer a classe que contém o método principal? Porque, nesse caso, o termo "classe pai" é bastante confuso aqui e, caso contrário, não faria sentido para mim. Além disso, se por convenção usamos 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?
Edwin Dalorzo

2
@Jacob Como a JVM saberia qual sobrecarga static void mainchamar? Não um problema de todos.
Konrad Rudolph

4
@Namratha: Sim, você está perdendo alguma coisa. Simplesmente não é verdade que "o método estático não possa fazer referência a um método não estático". A declaração correta é: "Todo método estático deve fornecer um objeto ao usar qualquer método não estático". E veja, staticmétodos como mainos usados newcom frequência para criar esse objeto.
Ben Voigt

38

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

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

Especificação da linguagem Java Oracle

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)

Especificação da Java Virtual Machine da Oracle

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.

Origem do Oracle OpenJDK

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);

... ...

4
O problema aqui é que essa é realmente uma resposta muito boa para a pergunta em sua forma original, com muitas referências (+1). No entanto, eu adoraria aprender sobre a justificativa para a decisão de design de tornar um método estático o ponto de entrada, em vez de um método construtor ou de instância.
21978 Konrad Rudolph

1
@KonradRudolph, para perguntas relacionadas ao idioma e ao design de especificação da JVM, talvez você possa tentar entrar em contato com a fonte original da Oracle e ver se consegue algum feedback positivo.
yorkw

2
De um modo geral, quando um cálculo de resultado de método depende apenas de seus parâmetros, para que não dependa do estado interno da instância do objeto, ele pode ser estático. E é recomendável defini-lo como estático para manutenção / reutilização do código. Se o método mainnã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.
Yves Martin

@KonradRudolph Curiosamente, o Oak (o antecessor do Java) já exigia que o método principal tivesse um protótipo semelhante: public static void main(String arguments[])- Referência: Oak 0.2 Spec .
assylias 16/07/12

2
@Yves Pode ser. Não é necessário, se outro design fizer sentido. Eu ouvi alguns bons argumentos nos comentários aqui, mas ainda acho que um processo é efetivamente muito parecido com um encadeamento ( é ), e um encadeamento em Java geralmente é representado como uma instância de Runnable. Representar todo o processo da mesma maneira (isto é, ter Runnable.Runcomo ponto de entrada) definitivamente faz sentido em Java. Obviamente, Runnableele 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á…
Konrad Rudolph

36

Vamos simplesmente fingir que staticisso 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 mainmé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:

  • Não deve ser um construtor padrão. Caso contrário, a JVM não saberia qual construtor chamar e quais parâmetros devem ser fornecidos.
  • Não deve ser um mainmétodo 1 . Ok, isso não é surpreendente.
  • A classe não deve ser abstract. Caso contrário, a JVM não poderia instancia-lo.

A staticabordagem, por outro lado, requer apenas um contrato:

  • Deve haver um mainmétodo 1 .

Aqui abstractnem 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 .


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


1
Na verdade, as exigências são mais complexas: deve haver um mainmétodo que é public, statice 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.
Konrad Rudolph

3
@KonradRudolph: Meu ponto não é sobre o trabalho que o JRE teria que fazer. O que quero dizer é forçar todos os usuários do idioma a seguir mais contratos, conforme necessário. Nesse sentido, um static public main(String[])método é uma assinatura e, portanto, um contrato. Caso contrário, três contratos independentes devem ser seguidos.
AH

1
Ah Ainda discordo que isso faça alguma diferença. Classes de ponto de entrada poderiam muito bem ser implementadas 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.
Konrad Rudolph

3
@KonradRudolph: Não há contradição: em um caso, o sistema forçaria três contratos com o usuário. Contratos duvidosos, que não são verificáveis ​​pelo compilador e que, do ponto de vista do usuário, são independentes. No habitual Threade Runnablecaso 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.
AH

2
Esta é a melhor resposta aqui. É uma pena que muitos usuários leiam apenas as 2 ou 3 principais respostas da página; e é improvável que este chegue lá tão cedo. Ele menciona o ponto importante de um construtor ser SOMENTE para inicialização - e, portanto, não faz sentido codificar em um estilo em que o construtor execute o aplicativo inteiro.
Dawood ibn Kareem

14

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 .


12

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.


Errado. Ou pelo menos muito impreciso. classe pública Main {static Object object = new Object () {{System.out.println ("objeto criado"); }}; public static void main (String [] args) {System.out.println ("in main"); }}
eljenso

Comentário justo. Tecnicamente, eu deveria ter dito que antes que o método Main seja chamado, a classe que contém o método principal não é instanciada.
29119 BlackWasp

12

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.


10

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.

voidindica que main()não retorna nenhum valor.


9

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

  1. public é um especificador de acesso, o que significa que qualquer pessoa pode acessá-lo / invocá-lo, como JVM (Java Virtual Machine).
  2. staticpermite 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.

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

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

    args- um parâmetro que contém uma matriz de objetos do tipo classe String.


6

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.


5

É 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.


Não é uma convenção; faz parte da especificação da linguagem; o tempo de execução não reconhecerá uma classe sem um método principal estático como um ponto de entrada válido.
Rob

2
A própria especificação de idioma segue a convenção. Não há um requisito real para os designers de Java terem optado por exigir um main estático. No entanto, como explica Logan, as alternativas são mais complicadas.
David Arno

@DavidArno Faria mais sentido dizer que a convenção segue a especificação da linguagem.
Marquês de Lorne

5

Se o método principal não for estático, você precisará criar um objeto da sua classe principal de fora do programa. Como você gostaria de fazer isso?


5

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

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 mainestática allowsa JVM como invokeprincipal withoutcriando um instanceda classe.

vamos voltar ao comando

ClassNameé um command-line argumentpara 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[] argsno diretório principal.

Referências: Java ™ Como Programar (Objetos Antigos), Décima Edição


4

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 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 Applicationclasse, 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

  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 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 ...

...


3

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)


Todos os métodos 'possuem apenas uma cópia'.
Marquês de Lorne

3

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.


7
Isto está incorreto. Muitos objetos são instanciados antes de mainserem atingidos. E se você incluir um construtor estático na classe que contém main, isso será executado antes da mainmesma forma.
11133 Konrad Rudolph

2

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


2

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.

Em 2.9. Métodos especiais :

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.


2

A publicpalavra-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 staticpermite 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 voidsimplesmente informa ao compilador que main()não retorna um valor.


1

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:

  1. A static void main()como a vemos hoje.
  2. Um método de instância void main()chamado em um objeto recém-construído.
  3. Usando o construtor de um tipo como ponto de entrada (por exemplo, se a classe de entrada for chamada Program, a execução consistirá efetivamente new Program()).

Demolir:

static void main()

  1. Chama o construtor estático da classe envolvente.
  2. Chama o método estático main().

void main()

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

new ClassName()

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

Fundamentação da petição:

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.


1
Isso está apenas implorando a pergunta. De qualquer maneira, o Java precisa de um carregador de aplicativos que faça trabalho pesado antes de chamar main. Sua lógica de mainser 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?
Konrad Rudolph

1

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.


1

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.


0

Métodos estáticos não requerem nenhum objeto. Ele roda diretamente, então o main roda diretamente.


0

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.


0

É 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


Regra da língua, você quer dizer.
Marquês de Lorne

0

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.

Fonte: Essentials, Parte 1, Lição 2: Criando aplicativos


0

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.


0

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 staticpara 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 Stringargumentos 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.


Isso acontece quando o programa é executado, não compilado.
Marquês de Lorne

0

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.


Mas não é executado "antes de mais nada no programa". Todo o argumento é uma falácia e, além do mais, esta não é a primeira resposta a mencioná-lo, nem mesmo a segunda ou a terceira.
Konrad Rudolph

Lamento que minha resposta repita o que os outros disseram; Respondi apenas da melhor maneira possível e pelo que encontrei on-line. Pelos resultados que observei, não há outra razão para o método principal ser estático; a menos que exista alguém profundamente escondido em algum lugar, talvez seja a única resposta que existe. Meu entendimento de Java é bastante básico, mas ouvi o motivo acima (de professores, livros didáticos etc.) e nunca outro.
Jesse M

@Jesse M Seu comentário só faz sentido se você nem pensou em ler as outras respostas primeiro. Que, a propósito, não é algo muito buscado. Como você se mencionou, seu entendimento é bastante básico, portanto é muito provável que alguém já tenha respondido à pergunta com mais competência. E seu comentário parece ser uma racionalização para melhorar sua resposta. É uma afirmação extraordinária que você tenha livros e professores de Java que pensam o que afirma e, francamente, não acredito que eles pensam. (Alguma referencia?) #
317 LeoR

1
@KonradRudolph Os principais comentários parecem bastante razoáveis. main () é usado como um ponto de entrada para o programa e há várias referências no site Java dizendo que é parecido com o modo como o C / C ++ tem uma função main (). Como Java é todo Objeto, ele deve ser estático para evitar a instanciação do objeto. Tê-lo estático também permite que ele seja carregado e executável na JVM em tempo de execução. Estou apenas regurgitando respostas anteriores, mas estou imaginando o que você consideraria uma resposta satisfatória. Eu acho que o melhor que você terá é "É assim que eles queriam". Lembre-se da data em que o Java foi criado.
22413 trevor-e

1
@Jesse Spot-on. É perfeitamente possível que seja apenas uma questão de convenção (embora eu espero que não seja, essa seria uma resposta tão chata). Meu interesse original nessa questão era porque eu pensava que usar uma instância adequada para representar o objeto "aplicativo em execução" e ter o ponto de entrada como um método (ou construtor) dessa classe seria um design muito mais óbvio, já que Java foi projetado para ser orientada a objetos a partir do get-go, e uma vez que objetos aparentemente análogas (threads, via Runnable) em Java fazer usar este projeto. Por que a exceção (aparente) aqui?
21978 Konrad Rudolph
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.