terça-feira, 8 de janeiro de 2013

Você já pensou por o método main() é public static?

O método Main() na linguagem Java é uma dos primeiros métodos que nós programadores temos contato. Normalmente não pensamos porque ele é declarado como public, static e void. Para aqueles que vêm do C++ fica evidente uma diferença, nesta linguagem existe um método semelhante porém este retorna valor - um int.

Para que precisamos de um método main()? Esta é uma convenção criada para designar o ponto de entrada de qualquer programa Java. É importante destacar que estamos falando de classes usuais, excluindo destas os Servlets, Midlets, JavaFX ou outro programa Java que normalmente está contido em container Java, onde outros métodos de controle do seu ciclo de vida existem.

Ao executarmos na linha de comando

java nome-da-classe

Invocamos a JVM, que carrega a classe principal e passa a execução para um método com a seguinte assinatura

public static void main(String args[])

Se este método não for encontrado é gerada uma exceção do tipo NoSuchMethodError:main e o programa é finalizado.

A assinatura apresentada acima é a tradicional do Java, mas a partir do Java 5 é possível utilizar um novo formato em função da utilização dos varargs com a sintaxe abaixo:

public static void main(String... args)

Das assinaturas acima destaco que
  • public indica que o método main pode ser chamado por qualquer objeto e portanto pode ser chamada pela JVM.
  • static indica que o método main é um método de classe. Isto é podemos chamá-lo como NomeDaClasse.main() sem ter que instanciar a classe.
    • Alguns autores ressaltam que uma vez que C e C++ seguem esta convenção, isto favorece ao Java.
    • Se este método não fosse static, a JVM teria que instanciar a classe principal. Isto faria com que fosse obrigatório que esta classe tivesse um construtor sem parâmetros, pois não haveria como a JVM informar parâmetros para outros construtores que tivessem sido sobrepostos.
    • Tudo que é declarado em uma classe Java são acessados via referência e precisam ser instaciados (criados como objeto) para que possam ser utilizados. Métodos e dados estáticos são carregados em um espaço de memória separado dentro da JVM que é criado quando a classe é carregada (note que não é o instanciamento do objeto). Desta forma o método main sendo estático, ele fica imediatamente disponível quando a classe é carregada.
  • void indica que o método main não retorna valor.
  • args é um array de strings, constituindo um mecanismo através do qual o usuário pode enviar informações em runtime para a aplicação (durante a chamada do programa). Cada string (arg[0], arg[1], ...) é chamada de argumento de linha de comando. Isto nos permite fazer com que o programa execute tarefas diferentes ou com comportamentos diferentes sem ter que recompilar o programa.

Resumindo

  1. O método main() deve ser declarado como public, static e void, caso contrário a JVM não será capaz de rodar o programa.
  2. JVM envia uma exceção NoSuchMethodException:main se ela não achar o método main() com a assinatura (mostrada acima) na classe que é executada pelo comando java NomeDaClasse.*
  3. O método main() é o ponto de entrada para qualquer programa Java Core.
  4. O método main() é executado em uma thread especial denominada "main" em Java, de forma que o programa ficará executando enquanto esta thread estiver rodando ou enquanto alguma thread non-deamon criada pela thread "main" estiver rodando.**
  5. A partir do Java 1.5 é possível utilizar uma nova sintaxe public static void main(String... args)
  6. Além dos modificadores static, void e public, podemos utilizar os modificadores:
    1. final
    2. synchronized
    3. strictfp
  7. Você pode acrescentar na assinatura do método main() cláusulas throws para indicar as exceções que o método pode enviar.
  8. O método main pode ser sobreposto (overloaded) como qualquer outro método, porém somente o método com a assinatura indicada acima.

OBS:
* Um bloco de inicialização estático é executado antes da JVM chamar o método main(). Este bloco é executado quando a classe é carregada na memória.
** Uma thread daemon fica rodando residente, mesmo quando a thread principal é terminada.

Nenhum comentário:

Postar um comentário