sábado, 12 de janeiro de 2013

Nossa primeira aplicação JavaFX

O JavaFX é uma plataforma de UI lançada pelo Java para criação de aplicativos ricos para internet (os tais RIA - Rich Internet Applications) mas o JavaFX não é somente isto, como ele podemos criar aplicações standalone para os ambiente onde roda o Java. Com ele conseguimos ainda gerar código compatível com dispositivos móveis.

A arquitetura apresentada pelo Java para o JavaFX está representada no diagrama abaixo:
Fonte: http://docs.oracle.com/javafx/2/architecture/jfxpub-architecture.htm

Quer dizer que o JavaFX é uma mistura de Swing, JavaME e Internet? Mais ou menos isto. O código ainda não é 100% portável de uma plataforma para outra, exigindo do competência do programador para prever as alterações necessárias nos arquivos de configuração como CSS (é o JavaFX usa css para configurar tela). Mas com o JavaFX você pode fazer uma aplicação para desktop, internet, dispositivos móveis (celular , tablet), set-top box, etc.

Vamos ao nosso exemplo. No vídeo você vai ver que o netbeans permite criar automaticamente um "Hello World". Vou mostrar esta criação e também um passo a passo de como construímos a classe manualmente:


Veja o vídeo



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.

sábado, 5 de janeiro de 2013

Tratamento de exceções

Vamos verificar alguns pontos do tratamento de exceções no Java. O primeiro tópico que vou tratar neste post é a diretiva assert. Ela é utilizada para nos permitir gerar paradas na execução do programa baseado em uma condição booleana. Esta diretiva existe desde a versão 1.4 do Java. Este recurso permite que testemos alguma pré suposição durante o desenvolvimento ter que escrever manipuladores para exceções que provavelmente não ocorrerão quando o programa tiver saído da fase de desenvolvimento.

As assertivas permitem que você teste suas suposições durante a fase de desenvolvimento.

A estrutura do comando é

assert Expressao_booleana : método_não_void;


Como por exemplo:

assert (boolean) : string;


O comando funciona da seguinte maneira: o valor (boolean) deve ser sempre verdadeiro. Quando este valor for avaliado como falso, é gerado uma exceção tipo AssertionError.

Por padrão, assert vem desabilitado. Para desfrutar do recurso é necessário ativá-lo. Os passos são:

1.Colocar as clausulas assert nos locais desejados no nosso programa

2.Compilar as classes (devemos solicitar que a compilação seja feita para uma versão superior a 1.4)

javac -source 1.5 classe.java

3.Habilitar o uso de assert durante a execução utilizando um dois dois parâmetros do java

java –ea classe
java –enableassertions classe

Para desabilitar as assertivas usamos os parâmetros

java –da classe
java –disableassertions classe

Regras de uso assert:
  • Assert não pode ser usado no lugar do IF
  • Assert não pode testar métodos públicos ou argumento digitado pelo usuário
  • Não pode apresentar efeitos colaterais no programa, ou seja, o seu programa deve rodar tanto com ele habilitado ou não.
Como recomendação nós devemos utilizar assert quando escreveríamos um comentários por exemplo em uma cláusula if-then-else. Vamos ver um exemplo abaixo:

    if (i % 3 == 0) {
        ...
    } else if (i % 3 == 1) {
        ...
    } else {
        assert i % 3 == 2 : i;
        ...
    }


Note que esperamos que (i % 3) na última cláusula else sempre dê 2. Porém como o operador % não opera módulo, podemos eventualmente um valor negativo, que não estamos esperando neste local. Com isto uma exceção AssertionError pode ser utilizada.

Outro local onde poderíamos utilizar assert é em declarações switch...case sem cláusula default. A inexistência de uma cláusula default não é recomendada, mas vamos dizer que acreditamos que testamos os pontos cardeiais como no switch abaixo:

switch (direcao) {
  case PontoCardeal.NORTE:
    ....
    break;
  case PontoCardeal.SUL:
    ....
    break;
  case PontoCardeal.LESTE:
    ....
    break;
  case PontoCardeal.OESTE:
    ....
    break;
}

se a variável direcao for do tipo Enum PontoCardeal nunca teremos necessidade de uma cláusula default. Uma alteração possível é a colocação da seguinte cláusula default.

  default:
    throw new AssertionError(suit);



Se a variável aceitar um quinto valor, será gerada uma exceção AssertionError.