Dicas de Java

Conteúdo desta página:

Sugestão 1: observe exemplos apresentados em sala de aula e divulgados na página da disciplina, dê uma olhada nos slides e no livro do Deitel. Se persistirem dúvidas, converse comigo pessoalmente nas aulas ou envie mensagem através de e-mail ou fórum.

Sugestão 2: dois lugares interessantes para obter informações sobre Java são: The Java Tutorials e API Java. O primeiro disponibiliza uma série de tutoriais ensinando a implementar diversas coisas em Java. O segundo trás a documentação da API disponibilizada junto com a compilador e a máquina virtual. Sendo assim, lista para você todas as classes por pacote e para cada classe descreve suas constantes e métodos.

Dicas gerais:

A seguir alguns links interessantes sobre Java.

Para comparar String utilize String.equals(<valor>) ou !String.equals(<valor>) e nunca var == <valor> ou var != <valor>. Isso se deve ao fato de String não ser tipo primitivo. Daí se você utiliza == ou != o que iria ser verificado seria o id dos objetos e não os conteúdo. Iria sempre retornar false.

Para converter de String para inteiro utilize Integer.parse(umaString).

Para converter de inteiro para String utilize String.valueOf(umInteiro)

Uma classe abstrata é uma classe que não pode ser instanciada diretamente. Ele é por definição uma superclasse. Uma classe abstrata pode ou não possuir métodos abstratos.

Um método abstrato é uma assinatura de um método declarado em uma classe abstrata. Isso força a subclasse, que herda da classe abstrata, a fornecer uma implementação daquele método.

Uma classe que possui ao menos um método abstrato será uma classe abstrata.

Uma interface define um tipo. É essencialmente uma lista de assinaturas de métodos. Se uma classe declara que implementa uma interface, ela terá de prover uma implementação para cada método listado na interface.

Seja ClasseX uma classe que implementa a interface InterfaceX. Seja ImplementacaoClasseAbstrata uma classe que implementa a classe abstrata ClasseAbstrata. A seguir exemplos de formas corretas de uso destas.

InterfaceX classeX1 = new ClasseX();

ClasseAbstrata classeAbst1 = new ImplementacaoClasseAbstrata();

boolean test1 = classX1 instanceof ClasseX; //true

boolean test2 = classAbst1 instanceof ImplementacaoClasseAbstrata; //true

boolean test3 = classAbst1 instanceof ClasseAbstrata; //true

ClasseX classeX2 = (ClasseX)classeX1;

ImplementacaoClasseAbstrata classeAbst2 = (ImplementacaoClasseAbstrata)classeAbst1;

ClasseX classeX3 = new ClasseX();

ImplementacaoClasseAbstrata classeAbst3 = new ImplementacaoClasseAbstrata();

boolean test4 = classX3 instanceof ClasseX; //true

boolean test5 = classAbst3 instanceof ImplementacaoClasseAbstrata; //true

boolean test6 = classAbst3 instanceof ClasseAbstrata; //true

A seguir exemplos de mau uso.

new InterfaceX();

new ClasseAbstrata();

Interface gráfica com o usuário:

Para começar crie uma classe que estende JFrame (isso é uma janela). Crie um construtor que invoca o construtor de JFrame para definir o título da janela. Ele também deve definir o tamanho da janela (largura e altura) e informar que a janela estará visível. Implemente um método main que deve instanciar um objeto do tipo janela, aquele que você acabou de implementar, e define a operação que será realizada quando o usuário clicar no fechar janela (x no canto da barra de título). O método main pode ser deslocado para uma outra classe. Isso tudo é feito pelo seguinte código.

import javax.swing.JFrame;

public class MinhaJanela extends JFrame {

public MinhaJanela(){

super("Título da janela");

// Aqui o restante do código, tal como a instanciação dos componentes gráficos e adição a tela.

setSize(300, 200);

setVisible(true);

}

public static void main(String[] args){

MinhaJanela minhaJanela = new MinhaJanela();

minhaJanela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

A partir deste código básico passe a adicionar seus componentes gráficos. Recomendo declará-los como atributos da janela, pois assim você terá fácil acesso a eles caso necessário. Como atributo você pode declarar também variáveis de controle e constantes.

Os componentes gráficos são adicionados a janela através de seu container, que pode ser obtido invocando getContentPane(). Para facilitar a sua vida, logo depois de invocar o construtor da superclasse (JFrame), crie uma variável container que recebe getContentPane(). Defina o gerenciador de layout logo em seguida. Por padrão use FlowLayout, mas você tem opções como o BorderLayout e o GridLayout.

Container container = getContentPane();

container.setLayout(new FlowLayout());

Use JPanel para ajudar a organizar seus componentes. Adicione quantos precisar e lembre que cada JPanel pode ter um gerenciador de layout diferente.

JPanel meuPainel = new JPanel();

meuPainel.setLayout(new BorderLayout());

Adicione seus componentes ao container da janela ou paineis.

container.add(botao1);

meuPainel.add(botao2, BorderLayout.SOUTH);

Não esqueça de adicionar os painéis ao container da janela. Uma vez que a interface esteja montada, passe a tratar os eventos. Lembre que para isso você terá de implementar os tratadores de evento (classes que implementam a respectiva interface - Listener - ou estende a respectiva classe adaptadora - Adapter - referente ao evento desejado). É preciso também registrar os tratadores nos respectivos componentes gráficos. Os tratadores de eventos podem ser implementados de diversas formas. A primeira delas é implementando na própria classe que implementa a janela. Para isso depois de "extends JFrame" adicione "implements <tipo evento>Listener". Uma outra é criar uma classe aninhada (classe dentro da classe da janela) ou uma classe em outro arquivo. A vantagem da classe aninhada é o acesso aos componentes gráficos da janela sem dificuldades. A última forma é criar uma classe sem nome no próprio registro do evento. Nos exemplos disponibilizados na página da disciplina, nos slides ou no livro (Deitel) vocês podem ver como implementar o tratamento de eventos destas diversas formas.

Pensando na implementação:

Tenha em mente que: escrever código em uma linguagem orientada a objetos como Java ou C++ não é condição suficiente para programar orientado a objetos.

    1. Esqueça o computador por um momento. Use papel e caneta.

    2. Analise cuidadosamente o cenário dado pelo cliente (ou exercício/trabalho).

    3. Esclareça dúvidas antes de seguir em frente.

    4. A partir do cenário dado identifique objetos e agrupe estes em classes. A partir daí liste atributos e métodos para para estes objetos/classes.

    5. Pense nos construtores para as classes. Estes devem receber como parâmetros, no mínimo, os valores obrigatórios para a instanciação do objeto ou então você precisa atribuir valores padrões para estes atributos. Se classificar como útil, crie opções de construtores (usando sobrecarga) que permitam também definir valores não obrigatórios.

    6. Crie os respectivos métodos get e set para seus atributos. Porém não precisa criar indiscriminadamente. Crie get para aqueles atributos que objetos clientes precisarão consultar. Crie set para aqueles atributos que podem ser alterados.

      • Recomendo sempre (ou quase sempre) criar atributos como private. Atributos codificam uma informação e apenas a classe do atributo deve ter a obrigação de conhecer esta codificação. Se você alterar a codificação, mas mantiver a interface pública (assinatura dos métodos), a alteração não terá impacto em outras classes. Isso facilita a manutenção do código e evita bugs.

      • A priori métodos devem ser public. Porém se o método é apenas utilitário para outros da classe, defina como private.

      • Um recurso que você pode usar para modelar esta sua solução é o diagrama de classes da UML.

    7. Revise tudo.

    8. Se tudo estiver ok, começe a escrever código.

A sua preocupação inicial na implementação deve estar no seu modelo em si, nos objetos/classes que você deve gerenciar. A interface com o usuário deve ser a última de suas preocupações. Pensando num nível mais elevado, algo que vocês terão a oportunidade de estudar em uma disciplina de Engenharia de Software, você tem o padrão arquitetural MVC. Ele prega exatamente a separação de sua implementação em modelo, controle e visão. Modelo são os objetos que vocês devem gerenciar, visão é a interface com o usuário e controle é que faz o meio de campo. Faz uma interface entre a visão e o modelo.

Eu falei em deixar interface com o usuário para o final pensando num cenário de nossa disciplina ou num cenário onde temos apenas um desenvolvedor. Eventualmente se temos uma equipe onde há membros com especialidades como desenvolvedor e desenvolvedor de interface, podemos ter o desenvolvimento em paralelo destes módulos.

Tratamento de data e hora:

Para tratar data e hora vocês podem utilizar a classe GregorianCalendar. Ela é uma subclasse da classe abstrata Calendar. Um dos métodos de GregorianCalendar é getTimeInMillis(), que retorna um inteiro com a hora atual em milissegundos.

Calendar calendar = GregorianCalendar.getInstance();

long now = calendar.getTimeInMillis();

Observe que para obter uma instância de GregorianCalendar você precisa utilizar o método getInstance(). Ela utiliza um padrão de projeto chamado Singleton, que faz com que você só possua uma instância da classe. O tipo long é primitivo e permite um maior número de inteiros que int. Para maiores informações sobre os tipos primitivos, consulte o tutorial.

SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

System.out.println("Data: " + dateFormat.format(now));

SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");

System.out.println("Hora: " + timeFormat.format(now));

SimpleDateFormat dateTimeFormat = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");

System.out.println("Data e Hora: " + dateTimeFormat.format(now));

Acima está um exemplo de como formatar o valor obtido através de getTimeInMillis() para apresentar ao usuário. Para tanto utilizamos uma classe chamada SimpleDateFormat. No primeiro bloco nós exibimos apenas a data, no segundo apenas a hora e no terceiro data e hora. Consultando a API vocês podem consultar como construir um novo padrão para a exibição da data/hora.

Caso você queira adicionar uma hora à hora corrente, basta somar o respectivo valor ao long retornado por getTimeInMillis. Lembre que está em milissegundos. A seguir um exemplo disso.

int oneSecond = 1000;

int oneMinute = 60*oneSecond;

int oneHour = 60*oneMinute;

long future = now + oneHour;

System.out.println("Uma hora para frente: " + timeFormat.format(future));