apostila programação java
TRANSCRIPT
ESCOLA TÉCNICA ESTADUAL MONTEIRO LOBATO
Programação Java
Curso Técnico em Informática
______________________________________________________________________________________________
Curso Técnico em Informática 2 Programação Java
1 Introdução ................................................................................................................................... 8
1.1 Padronização ................................................................................................................. 9
1.2 Características ............................................................................................................... 9
1.3 Licença ......................................................................................................................... 10
1.4 Máquina Virtual ............................................................................................................ 10
1.5 Garbage Collection ...................................................................................................... 11
1.6 Estrutura de um código em Java ............................................................................... 11
1.7 Instalação e configuração do java ............................................................................. 13
1.7.1 Requisitos do Sistema Java 8 .......................................................................... 13
1.7.2 Download e Instalação ..................................................................................... 13
1.8 Ferramentas ................................................................................................................. 24
1.8.1 Eclipse ............................................................................................................. 24
1.8.2 NetBeans ......................................................................................................... 25
1.8.3 Jcreator ............................................................................................................ 25
1.8.4 BlueJ ................................................................................................................ 26
1.9 IDE Netbeans ............................................................................................................... 26
2 Linguagem Java ....................................................................................... .....................28
2.1 Sintaxe Java .................................................................................................................... 29
2.1.1 Delimitadores em Java ............................................................................................... 29
2.1.2 Identificadores e palavras reservadas ........................................................................ 30
2.1.3 Declaração de Variáveis ............................................................................................. 31
2.1.4 Tipos primitivos ........................................................................................................... 32
2.1.4.1 Tipos lógicos: boolean .................................................................................. 32
2.1.4.2 Tipos textuais: char e String .......................................................................... 32
2.1.4.3 Tipos numéricos inteiros: byte, short, int e long ............................................ 33
2.1.4.4 Tipos numéricos de ponto flutuante: float e double ....................................... 33
2.2 Convenções de codificação ....................................................................................... 33
3 Expressões .................................................................................................................... 34
3.1 Operadores .................................................................................................................. 34
3.1.1 Operadores Delimitadores............................................................................ 34
Sumário
______________________________________________________________________________________________
Curso Técnico em Informática 3 Programação Java
3.1.2 Operadores Aritméticos ................................................................................... 34
3.1.3 Operadores de Atribuição ................................................................................ 35
3.1.4 Operadores Unários ......................................................................................... 35
3.1.5 Operadores de Incremento e Decremento ....................................................... 35
3.1.6 Operadores Relacionais .................................................................................. 35
3.1.7 Operadores Lógicos ......................................................................................... 35
3.1.8 Operador de concatenação ............................................................................. 36
3.1.9 Operadores de deslocamento .......................................................................... 36
3.2 Casting ......................................................................................................................... 37
3.3 Recebendo dados do usuário .................................................................................... 38
4 Controle de Fluxo......................................................................................................................39
4.1 Execução Condicional .................................................................................................... 40
4.1.1 Comando if ...................................................................................................... 40
4.1.2 Comando if-else ............................................................................................... 41
4.1.3 Condicional ternário ......................................................................................... 42
4.1.4 Comando If-else Aninhados ............................................................................. 42
4.1.5 Comando switch ............................................................................................. 44
4.2 Laços de Repetição ........................................................................................................ 48
4.2.1 Comando While ............................................................................................... 48
4.2.2 Comando do-while ........................................................................................... 49
4.2.3 Comando for .................................................................................................... 50
4.2.4 Comandos de desvio ....................................................................................... 51
4.3 Recursividade .............................................................................................................. 54
5 Estrutura de dados................................................................................................................. 56
5.1 Vetores ......................................................................................................................... 56
5.1.1 Inicialização de vetores .................................................................................... 61
5.1.2 Estrutura for aprimorada .................................................................................. 62
5.2 Matrizes ........................................................................................................................ 64
6 Programação Orientada a Objetos....................................................................................... 68
6.1 Introdução .................................................................................................................... 68
6.2 Ideias básicas da POO ................................................................................................ 69
6.3 Classes ......................................................................................................................... 69
6.4 Objetos ......................................................................................................................... 70
6.5 Mensagens ................................................................................................................... 71
6.6 Métodos ........................................................................................................................ 71
______________________________________________________________________________________________
Curso Técnico em Informática 4 Programação Java
6.7 Abstração ..................................................................................................................... 73
6.8 Encapsulamento .......................................................................................................... 73
6.9 Herança ........................................................................................................................ 76
6.10 Classes abstratas ...................................................................................................... 79
6.11 Polimorfismo .............................................................................................................. 82
7 Documentação – JavaDoc..................................................................................................... 86
8 Interface Gráfica.....................................................................................................................91
8.1 Componentes Swing ..................................................................................................... 91
8.1.1 Hierarquia das Classes dos Componentes ...................................................... 92
8.1.2 Portabilidade .................................................................................................... 93
8.1.3 Look And Feel .................................................................................................. 93
8.1.4 Bases de Estruturação das Interfaces Gráficas ............................................... 93
8.1.4.1 Conteiners .......................................................................................... 94
8.1.4.2 Swing - Mensagens ............................................................................ 94
8.1.4.3 Componentes: JFrame, JPanel e JButton .......................................... 95
8.1.4.4 JFrame ............................................................................................... 95
8.1.4.5 JDesktopPane e JInternalFrame ........................................................ 97
8.1.4.6 JDialog ............................................................................................... 97
8.1.4.7 Componentes Atômicos...................................................................... 98
8.1.4.7.1 JLabel ................................................................................... 98
8.1.4.7.2 Botões ................................................................................... 98
8.1.4.7.3 JButton .................................................................................. 99
8.1.4.7.4 JCheckBox ............................................................................ 99
8.1.4.7.5 JRadioButton ...................................................................... 100
8.1.4.7.6 JTextField ............................................................................ 100
8.1.4.7.7 JPasswordField................................................................... 101
8.1.4.7.8 JTextArea ............................................................................ 101
8.1.4.7.9 JScrollPane ......................................................................... 102
8.1.4.7.10 JSlider ............................................................................... 102
8.1.4.7.11 JComboBox....................................................................... 103
8.1.4.7.12 JList .................................................................................. 103
8.1.4.7.13 JPopupMenus ................................................................... 104
8.1.4.7.14 Menus ............................................................................... 104
8.2 Eventos ...................................................................................................................... 105
8.2.1 Tratamento de Eventos .................................................................................. 105
______________________________________________________________________________________________
Curso Técnico em Informática 5 Programação Java
8.2.1.1 A Origem do Evento ......................................................................... 105
8.2.1.2 O Objeto Evento ............................................................................... 105
8.2.1.3 Ouvinte do Evento ............................................................................ 106
8.2.2 Tratadores de Eventos ou Ouvintes (Listeners) ............................................. 106
8.2.2.1 ActionListener ................................................................................... 106
8.2.2.2 FocusListener ................................................................................... 106
8.2.2.3 ItemListener ...................................................................................... 107
8.2.2.4 KeyListener ...................................................................................... 107
8.2.2.5 MouseListener .................................................................................. 107
8.2.2.6 MouseMotionListener ....................................................................... 108
8.2.2.7 WindowListener ................................................................................ 108
8.3 Classes Adaptadoras ................................................................................................ 108
8.4 JavaFX ........................................................................................................................ 109
8.4.1 Introdução ...................................................................................................... 109
8.4.2 Aplicação de internet rica (RICH INTERNET APPLICATION – RIA) .............. 109
8.4.3 Sobre JAVAFX ............................................................................................... 110
8.4.4 Características ............................................................................................... 111
8.4.5 À linguagem JavaFX script ............................................................................ 113
8.4.5.1 Tipos de variáveis ............................................................................. 115
8.4.5.2 Características especiais.................................................................. 115
8.4.5.3 Ambiente web ................................................................................... 117
8.4.5.4 A aplicação JXplayer ........................................................................ 118
8.4.5.4.1 Características da aplicação JXPlayer ................................ 118
8.4.5.4.2 Ferramentas de apoio ao desenvolvimento ........................ 118
8.4.6 Interface e efeitos gráficos ............................................................................. 119
8.4.7 Suporte a áudio e vídeo ................................................................................. 119
9 Expressões Regulares – Java..........................................................................................120
10 Tratando exceções em Java...........................................................................................124
10.1 Entendendo as exceções ........................................................................................ 124
11 Conexão com banco de dados ............................................................................................ 131
12 Java Persistence API - JPA .................................................................................................. 134
12.1 Entity ........................................................................................................................ 135
12.1.1 Anotações para Entity .................................................................................. 136
12.1.1.1 javax.persistence.Entity .................................................................. 136
12.1.1.2 javax.persistence.Table .................................................................. 136
______________________________________________________________________________________________
Curso Técnico em Informática 6 Programação Java
12.1.1.3 javax.persistence.Id ........................................................................ 137
12.1.1.4 javax.persistence.Column .............................................................. 137
12.1.1.5 javax.persistence.SequenceGenerator .......................................... 138
12.1.1.6 javax.persistence.GeneratedValue ................................................. 138
12.1.1.7 javax.persistence.Temporal ............................................................ 139
12.1.1.8 javax.persistence.Transient ............................................................ 139
12.2 EntityManager .......................................................................................................... 141
12.3 Unidade de Persistência ......................................................................................... 141
12.4 Criando uma unidade de persistência no NetBeans ............................................ 142
12.5 EntityManager gerenciado pela Aplicação ............................................................ 147
12.6 EntityManager gerenciado pelo Container ............................................................ 148
12.7 Interface EntityManager .......................................................................................... 149
12.7.1 Ciclo de vida da Entity ................................................................................. 150
12.8 DAO (CRUD) utilizando JPA ................................................................................... 150
12.9 Estratégia de SEQUENCE para gerar ID ................................................................ 156
12.10 Utilizando chave composta .................................................................................. 158
12.11 Relacionamento entre entidades .......................................................................... 168
12.12 Os quatro tipos de cardinalidade ......................................................................... 168
12.13 Cascade Type ......................................................................................................... 189
12.14 FetchType ............................................................................................................... 189
12.15 Consultas com JPAQL .......................................................................................... 199
12.15.1 Interface Query ............................................................................................. 203
13 Relatórios .............................................................................................................................. 207
13.1 Acesso ao banco de Dados .................................................................................... 213
13.2 iReport Wizard ....................................................................................................... 2130
13.3 Modelo Relatório iReport ........................................................................................ 213
13.3.1 Estrutura de um relatório ............................................................................. 213
13.3.2 Variáveis, Parâmetros e campos ............................................................... 2134
13.3.3 Arquivos gerados pelo iReport ..................................................................... 216
14 Threads em Java ................................................................................................................... 223
14.1 Thread em Java ....................................................................................................... 224
14.2 Criando Threads em Java ....................................................................................... 225
14.2.1 Implementando o Comportamento de uma Thread ..................................... 226
14.2.2 Criando uma subclasse de Thread .............................................................. 226
14.2.3 Implementando a Interface Runnable .......................................................... 226
14.2.4 Escolhendo entre os dois métodos de criação de threads ........................... 227
______________________________________________________________________________________________
Curso Técnico em Informática 7 Programação Java
14.2.5 O ciclo de vida de uma Thread .................................................................... 230
14.2.6 Criando Threads .......................................................................................... 230
14.2.7 Iniciando Threads ........................................................................................ 230
14.2.8 Fazendo Thread Esperar ............................................................................. 231
14.2.9 Finalizando Threads .................................................................................... 231
14.2.9.1 Verificando se Threads estão Executando/Pronta/Esperando ou
Novas/Mortas ............................................................................................................................... 231
14.10 Threads Daemon ................................................................................................. 2341
14.11 Escalonamento de Threads ................................................................................ 2342
14.12 Sincronizando Threads (Concorrência) ........................................................... 2343
14.13 Implementando Exclusão Mútua de Regiões Críticas ...................................... 2343
14.14 Comunicação Entre Threads ................................................................................ 234
14.15 Evitando Starvation e Deadlock ........................................................................... 234
______________________________________________________________________________________________
Curso Técnico em Informática 8 Programação Java
Java é uma linguagem de programação orientada a objetos desenvolvida no início
da década de 90, pela Sun Microsystems1. Diferentemente das linguagens convencionais, que
são compiladas para código nativo, a linguagem Java é compilada para um bytecode2 que é
executado por uma máquina virtual.
Em 1991, a Sun Microsystems, deu início ao Green Project, a origem do Java,
uma linguagem de programação orientada a objetos. Os idealizadores do projeto eram Patrick
Naughton, Mike Sheridan, e James Gosling. Eles acreditavam que, em breve, haveria uma
convergência dos computadores com os equipamentos e eletrodomésticos utilizados no dia-a-dia.
Para provar a viabilidade desta ideia, 13 pessoas trabalharam durante 18 meses. No verão
de 1992 foi apresentado uma demonstração funcional da ideia inicial. O protótipo se
chamava *7 (lê-se “Star Seven”), um controle remoto com uma interface gráfica touchscreen. Para
o *7, foi criado um mascote, hoje amplamente conhecido no mundo Java, o Duke. O trabalho do
Duke no *7 era ser um guia virtual ajudando e ensinando o usuário a utilizar o equipamento. O *7
tinha a habilidade de controlar diversos dispositivos e aplicações. James Gosling especificou uma
nova linguagem de programação para o *7. Gosling decidiu batizá-la de “Oak”, que quer
dizer carvalho, uma árvore que ele podia observar quando olhava através da sua janela.
O próximo passo era encontrar um mercado para o *7. A equipe achava que uma boa ideia
seria controlar televisões e vídeo por demanda com o equipamento. Eles construíram uma
demonstração chamada de MovieWood, mas infelizmente era muito cedo para que o vídeo por
demanda bem como as empresas de TV a cabo pudessem viabilizar o negócio. A ideia que o *7
tentava vender, hoje já é realidade em programas interativos e também na televisão digital. Permitir
ao telespectador interagir com a emissora e com a programação em uma grande rede de cabos,
era algo muito visionário e estava muito longe do que as empresas de TV a cabo tinham capacidade
de entender e comprar. A ideia certa, na época errada.
Entretanto, o estouro da internet aconteceu e rapidamente uma grande rede interativa
estava se estabelecendo. Era este tipo de rede interativa que a equipe do *7 estava tentando vender
para as empresas de TV a cabo. E, da noite para o dia, não era mais necessário construir a
infraestrutura para a rede, ela simplesmente estava lá. Gosling foi incumbido de adaptar o Oak para
a internet e em janeiro 1995 foi lançada uma nova versão do Oak que foi rebatizada para Java. A
tecnologia Java tinha sido projetada para se mover por meio das redes de dispositivos
heterogêneos, redes como a internet. Agora aplicações poderiam ser executadas dentro
dos navegadores nos Applets Java e tudo seria disponibilizado pela internet instantaneamente. Foi
o estático HTML dos navegadores que promoveu a rápida disseminação da dinâmica tecnologia
Java. A velocidade dos acontecimentos seguintes foi assustadora, o número de usuários cresceu
rapidamente, grandes fornecedores de tecnologia, como a IBM anunciaram suporte para a
tecnologia Java.
Desde seu lançamento, em maio de 1995, a plataforma Java foi adotada mais rapidamente
do que qualquer outra linguagem de programação na história da computação. Em 2004 Java
1Sun Microsistens : É uma subsidiária da Oracle Corporation fabricante de computadores, semicondutores e
software com sede em Santa Clara, Califórnia, no Silicon Valley. 2Bytecode : É a forma intermediária de código, resultante da compilação de um código escrita na linguagem Java.
Introdução
1
______________________________________________________________________________________________
Curso Técnico em Informática 9 Programação Java
atingiu a marca de 3 milhões de desenvolvedores em todo mundo. Java continuou crescendo e
hoje é uma referência no mercado de desenvolvimento de software. Java tornou-se popular pelo
seu uso na internet e hoje possui seu ambiente de execução presente
em navegadores, mainframes, sistemas operacionais, celulares, palmtops, cartões inteligentes etc.
1.1 Padronização Em 1997 a Sun Microsystems tentou submeter a linguagem a padronização pelos
órgãos ISO/IEC e ECMA, mas acabou desistindo.3 4 5 Java ainda é um padrão de fato, que é
controlada através da JCP Java Community Process.6. Em 13 de novembro de 2006, a Sun lançou
a maior parte do Java como Software Livre sob os termos da GNU General Public License (GPL).
Em 8 de maio de 2007 a Sun finalizou o processo, tornando praticamente todo o código Java como
software de código aberto, menos uma pequena porção da qual a Sun não possui copyright.7
1.2 Características
A tecnologia Java é composta basicamente de uma linguagem de programação, um
ambiente de desenvolvimento, um ambiente de distribuição e uma Java Virtual Machine (Máquina
virtual Java), responsável pela execução das aplicações (SANTOS, pág. 13, 2010).
A linguagem Java foi projetada tendo em vista os seguintes objetivos:
Orientação a objetos - Baseado no modelo de simular;
Portabilidade - Independência de plataforma - "escreva uma vez, execute em qualquer lugar"
("write once, run anywhere");
Recursos de Rede - Possui extensa biblioteca de rotinas que facilitam a cooperação com
protocolos TCP/IP, como HTTP e FTP;
Segurança - Pode executar programas via rede com restrições de execução;
Além disso, podem-se destacar outras vantagens apresentadas pela linguagem:
Sintaxe similar a C/C++;
Facilidades de Internacionalização - Suporta nativamente caracteres Unicode;
Simplicidade na especificação, tanto da linguagem como do "ambiente" de execução (JVM);
É distribuída com um vasto conjunto de bibliotecas (ou APIs);
Possui facilidades para criação de programas distribuídos e multitarefa (múltiplas linhas de
execução num mesmo programa);
Deslocação de memória automática por processo de coletor de lixo;
Carga Dinâmica de Código - Programas em Java são formados por uma coleção de classes
armazenadas independentemente e que podem ser carregadas no momento de utilização;
De acordo com Santos (pág. 14, 2010), um programa feito em Java é composto de classes que
possuem atributos e métodos. Os atributos em uma classe são variáveis que podem ser
modificadas ao longo da execução do programa, os métodos por sua vez, executam determinadas
tarefas e retornam respostas.
Ainda de acordo com Santos (pág. 14, 2010), Java é totalmente orientada a objetos, possui
suporte para threads3, ou seja, garante que o programa rode vários processos ao mesmo tempo
3thread : Um fluxo de controle sequencial isolado dentro de um programa.
______________________________________________________________________________________________
Curso Técnico em Informática 10 Programação Java
(multitarefa), possuí tratamento de erros (exceptions), coletor de lixo (Garbage Colector). Possui
também um conjunto de bibliotecas de classes (API) prontas, que diminuem o trabalho do
programador, é multiplataforma, enfim são essas, e outras características que fazem do Java uma
das linguagens mais populares do mundo.
1.3 Licença A Sun disponibiliza a maioria das distribuições Java gratuitamente e obtém receita com
programas mais especializados como o Java Enterprise System. Em 13 de novembro de 2006, a
Sun liberou partes do Java como software livre, sob a licença GNU General Public License. A
liberação completa do código fonte sob a GPL ocorreu em maio de 2007.
1.4 Máquina Virtual
Quando um programa Java é compilado, gera-se um código intermediário, o bytecode, que
é interpretado pela máquina virtual Java, que por sua vez traduz os bytecodes para a linguagem de
máquina nativa do processador. Desta forma, a tecnologia Java é multiplataforma, ou seja, um
programa em Java rodará em qualquer plataforma que possua um JVM (SANTOS, pág. 3, 2010).
De acordo com a especificação da SUN, a máquina virtual do Java pode ser vista como:
Uma máquina imaginária que é implementada via software ou hardware;
Um código a ser executado por essa máquina deve ser gravado em um arquivo com
extensão .class. e possuir um código compatível com as instruções Java.
Para um programa Java ser executado, ele precisa passar pelo processo ilustrado na figura a
seguir:
O código é compilado, gerando um conjunto de instruções chamado de byte-code. Esse
byte-code é aplicado à Máquina Virtual Java ( JVM ) que se encarrega de interpretar os comandos
para o sistema operacional onde o programa está rodando, ou seja, a máquina virtual traduz as
instruções do código Java para instruções válidas no sistema operacional em que está rodando.
Se essa portabilidade fosse requerida em C, o código deveria ser compilado várias vezes – uma
para cada sistema operacional desejado. No caso do Java, o código é compilado apenas uma vez,
gerando o byte-code. Esse byte-code poderá então ser interpretado por qualquer máquina virtual
Java, rodando em Linux, Windows, Palm OS, Solaris ou qualquer outro sistema operacional que
possua uma máquina virtual Java implementada.
Uma JVM possui definições concretas para a implementação dos seguintes itens:
Conjunto de instruções (equivalentes às instruções da CPU);
______________________________________________________________________________________________
Curso Técnico em Informática 11 Programação Java
Conjunto de registradores;
Formato padrão de classes;
Pilha de memória;
Pilha de objetos coletados pelo garbage-collector;
Área de memória.
IMPORTANTE: a JVM não permite que um programa Java acesse recursos de hardware
diretamente, protegendo o computador de operações perigosas, como acesso a regiões protegidas
da memória ou formatação física do disco rígido. Um programa Java só é executado caso o seu
byte-code passe pela verificação de segurança da JVM, que consiste em dizer que:
O programa foi escrito utilizando-se a sintaxe e semântica da linguagem Java;
Não existem violações de áreas restritas de memória no código;
O código não gera Stack Overflow;
Os tipos de parâmetros dos métodos são corretos;
Não existe nenhuma conversão ilegal entre dados do programa, como a tentativa de
conversão de inteiros em ponteiros;
O acesso a objetos está corretamente declarado;
Caso alguma das condições acima não seja satisfeita, a máquina virtual Java causará um
erro de execução (runtime error).
1.5 Garbage Collection Durante a execução de um programa de computador, ocorre a alocação e liberação dinâmica
de memória RAM. Dados são escritos e lidos da memória do computador satisfazendo os requisitos
de cada programa. Em linguagens tradicionais como Pascal, Basic e C/C++, o programador é
responsável por controlar essa alocação, impedindo o estouro de memória (stack overflow) e outros
problemas, como o acesso indevido a áreas reservadas de memória. Para facilitar a vida dos
programadores, e evitar os erros comuns associados à alocação de memória, a linguagem Java
introduziu um novo conceito: o garbage-collection.
Garbage-collection é um mecanismo de controle automático de alocação e liberação de
memória. Quando uma variável é declarada em um código de computador, a JVM cria um ponteiro
para uma área de memória equivalente ao tamanho do tipo de dado utilizado por essa variável.
Quando essa variável é associada a outra região de memória, a JVM coloca o espaço alocado
anteriormente em uma pilha de objetos em desuso. Caso o computador fique com pouca memória
disponível, a JVM remove objetos dessa pilha, permitindo que esse espaço de memória seja
realocado.
O processo de garbage-collection ocorre automaticamente durante a execução de um
programa Java. O programador não precisa se preocupar com aritmética de ponteiros (grande
dificuldade em linguagens como C e Pascal).
1.6 Estrutura de um código em Java Como todas as outras linguagens de programação, Java possui um formato básico para a
______________________________________________________________________________________________
Curso Técnico em Informática 12 Programação Java
escrita de códigos. Tal formato é demonstrado a seguir:
1. // Duas barras significam comentário
2. /* comentários também podem seguir o formato de C++ */
3.
4. public class NomeDoPrograma
5. {
6. // O método main sempre deve estar presente para que um código Java possa ser
executado:
7. static public void main(String[] args)
8. {
9. // aqui virão os comandos, que são parecidos com C++
10. }
11. }
Compreendendo o código Java:
linhas 1 e 2: representam comentários. Um comentário pode conter qualquer informação
relevante ao comportamento do programa, autor, versão, etc.;
linha 3: está em branco, pois Java permite linhas em branco entre os comandos;
linha 4: é a declaração do "nome do programa", que é case-sensitive (existe diferença entre
maiúsculas e minúsculas). O arquivo que contém o código Java deve ser salvo com o mesmo
nome que aparece após a declaração public class e mais a extensão .java (o exemplo acima
deveria ser salvo como NomeDoPrograma.java);
linha 5 e 8: a abertura de chave { indica início de bloco;
linha 7: essa linha deve aparecer em todos os códigos Java. Quando um programa Java é
executado, o interpretador da JVM executa os comandos que estiverem dentro do bloco
indicado pelo método "static public void main(String)";
Linha 9: aqui seria escrito o código propriamente dito. Instruções como for-next, print, etc.;
Linha 10 e 11: o fechamento de chave } indica fim de bloco;
______________________________________________________________________________________________
Curso Técnico em Informática 13 Programação Java
Exemplo de código Java:
Como rodar o programa:
1. Salvar o código acima em um arquivo nomeado: OlaMundo.java (não esqueça o case-sensitive);
2. Digite no console:
a. C:\exercicio-java>javac AloMundo.java;
3. Caso não ocorra nenhuma mensagem de erro, digite:
a. C:\exercicio-java>java AloMundo
Obs: Caso os procedimentos acima não funcionarem deve ser verificado se o Java está instalado
na máquina, ou o JDK (Kit de Desenvolvimento Java), ou ainda se as configurações estão corretas.
1.7 Instalação e configuração do java
As instruções aqui contidas referem-se ao sistema operacional Windows 7.
1.7.1 Requisitos do Sistema Java 8
Windows 10 (8u51 e versões posteriores);
Windows 8.x (Desktop);
Windows 7 SP1;
Windows Vista SP2;
Windows Server 2008 R2 SP1 (64 bits);
Windows Server 2012 e 2012 R2 (64 bits);
RAM: 128 MB;
Espaço em disco: 124 MB para JRE; 2 MB para Java Update;
Processador: no mínimo, um processador Pentium 2 de 266 MHz;
Browsers: Internet Explorer 9 e versão mais recente, Firefox, Chrome;
1.7.2 Download e Instalação É recomendável a desativação do firewall da Internet antes de continuar com a instalação
on-line. Em alguns casos, as configurações padrão do firewall estão definidas para rejeitar
instalações automáticas ou on-line, como a do Java. Se o firewall não estiver configurado
corretamente, talvez ele atrase a operação de download/instalação do Java sob certas condições.
______________________________________________________________________________________________
Curso Técnico em Informática 14 Programação Java
Consulte o seu manual específico para obter instruções sobre como desativar seu firewall da
Internet.
Acessar a página de download: manual:https://www.java.com/pt_BR/download/manual.jsp
Clicar em Windows Online.
A caixa de diálogo Download de Arquivo é exibida, solicitando que execute ou salve o
arquivo do download.
Para executar o instalador, clique em Executar.
Para salvar o arquivo para instalação posterior, clicar em Salvar.
Selecione a localização da pasta e salve o arquivo no sistema local.
Dica: salvar o arquivo em um local do computador que seja fácil de acessar, como a área de
trabalho.
Para iniciar o processo de instalação, clicar duas vezes no arquivo salvo.
O processo de instalação será iniciado. Clicar no botão Instalar para aceitar os termos de
licença e continuar com a instalação.
A Oracle é parceira de algumas empresas que oferecem diversos produtos. O instalador poderá
apresentar uma opção para instalar esses programas quando você instalar o Java. Depois de
verificar se os programas desejados foram selecionados, clique no botão Avançar para
continuar com a instalação;
Algumas caixas de diálogo confirmam as últimas etapas do processo de instalação. Clique em
Fechar na última caixa de diálogo. Isso concluirá o processo de instalação do Java.
______________________________________________________________________________________________
Curso Técnico em Informática 15 Programação Java
Remover versões mais antigas (8u20 e versões posteriores). A partir do Java 8 Update 20
(8u20), nos sistemas Windows, a ferramenta de desinstalação do Java é integrada com o instalador
para fornecer uma opção para remover do sistema as versões mais antigas do Java. A alteração
se aplica a plataformas Windows de 32 bits e de 64 bits.
Notificações sobre Java desativado e restauração de prompts. O instalador avisa caso o
conteúdo Java esteja desativado nos Web browsers e fornece instruções para ativá-lo. Se você
tiver optado por ocultar alguns prompts de segurança para applets e aplicações Java Web Start, o
instalador fornecerá uma opção para restaurar os prompts. O instalador pode solicitar que o
computador seja reiniciado se você tiver optado por não reiniciar um Internet browser quando foi
solicitado a fazê-lo.
Após a instalação do Java (JRE) o sistema está pronto para executar aplicações construídas
utilizando a linguagem. Porém, para que se possa criar novos programas não é o suficiente. Para
tanto é necessário ter instalado no computador o JDK (Kit de Desenvolvimento Java).
Instalação do JDK
O JDK (Java Development Kit) possui todo o ambiente necessário para desenvolver e
executar aplicativos em Java, contendo uma cópia do JRE que pode ser distribuído junto com sua
aplicação em algum tipo de instalador ou CD, por exemplo, para os clientes não precisarem baixar
e/ou instalar o Java pessoalmente.
A seguir o endereço para o obter a versão 8 do JDK:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
Um ponto bastante importante é sempre escolher o tipo do sistema operacional, este exemplo de
instalação é para versões Windows (x86).
______________________________________________________________________________________________
Curso Técnico em Informática 16 Programação Java
Página para download do JDK 8.
Após ter baixado o instalador da JDK, execute o instalador e avance nas telas a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 17 Programação Java
Opções de instalação:
Status de instalação e pasta de destino:
______________________________________________________________________________________________
Curso Técnico em Informática 18 Programação Java
Progresso da instalação JDK:
Local da instalação do JRE:
Browser que irá possuir o plugin do Java
Progresso da instalação do JRE:
______________________________________________________________________________________________
Curso Técnico em Informática 19 Programação Java
Finalização da Instalação:
Após o término da instalação vamos configurar as variáveis do ambiente, abaixo estão os passos
a serem seguidos.
1. Clique com o botão direito em cima do ícone “Meu Computador”;
2. Vá em “Propriedades”;
3. Selecione a aba “Avançado” (Windows XP) ou “Configurações avançadas do sistema”, depois
na aba “Avançado” (Windows 7);
4. Clique no botão “Variáveis de ambiente”;
5. Clique no botão “Nova” em “Variáveis do sistema”;
5.1. Nome da variável: JAVA_HOME
5.2. Valor da variável: coloque aqui o endereço de instalação (o caminho tem que ser o
mesmo especificado na figura a seguir) “C:\Arquivos de programas\Java\jdk1.5.0_05”
5.3. Clique em OK
______________________________________________________________________________________________
Curso Técnico em Informática 20 Programação Java
6. Clique novamente no botão “Nova” em “Variáveis do sistema”;
6.1. Nome da variável: CLASSPATH
6.2. Os valores da variável encontram-se abaixo, sempre insira um do lado outro sem
espaços e com o ; (ponto e vírgula) no final.
Listagem 1: Valor da variável
CLASSPATH ;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar;%JAVA
_HOME%\lib\htmlconverter.jar;%JAVA_HOME%\jre\lib;%JAVA_HOME%\jre\lib\rt.jar;
6.3. Clique em OK
7. Selecione a variável PATH em “Variáveis do sistema” e clique no botão “Editar”;
7.1. Defina o valor dessa variável com o caminho da pasta Bin. No caso, pode-se utilizar a
variável JAVA_HOME previamente definida.
Listagem 2: Valor da variável de ambiente PATH;%JAVA_HOME%\bin
______________________________________________________________________________________________
Curso Técnico em Informática 21 Programação Java
7.3. Então confirma-se todas as telas no botão Ok.
Logo após ter realizado a configuração acima emula-se um programa em Java.
Testando o Programa em Java
Abra o programa de bloco de notas do Windows (Iniciar > Programas > Acessórios > Bloco de
Notas.
Digite as seguintes linhas:
Listagem 3: Código de um programa Java para teste
public class Ola{
public static void main(String[] args){
System.out.println("Bem Vindo ao Mundo Java!");
}
}
______________________________________________________________________________________________
Curso Técnico em Informática 22 Programação Java
Salvamento do arquivo Ola.java:
Depois de salvar abra o Prompt do Dos para testar a saída desse sistema.
1. Iniciar
2. Windows XP - Executar e digitar a palavra cmd
3. Windows 7 apenas digite cmd e aperte Enter
Prompt do DOS
Digite a seguinte linha abaixo, para testar se o java está tendo retorno da sua máquina. Deve ser
retornado uma mensagem conforme a figura a seguir.
Verificando a versão do Java
java -version
______________________________________________________________________________________________
Curso Técnico em Informática 23 Programação Java
Versão do Java instalada no computador
Após obter o retorno da versão estamos prontos para compilar nosso primeiro programa em
Java. Para efetuar a ação seguinte irá ser preciso entrar em modo DOS na pasta em que foi salvo
o arquivo “Ola.java”, como nesse exemplo foi salvo dentro da pasta que já iniciou o Prompt do Dos
(c:\Users\Thiago), apenas vamos digitar a seguinte linha.
Compilando um programa Java pelo prompt
javac Ola.java
Ao efetuar esse processo é criado na nossa pasta mais um arquivo “Ola.class”, que nada
mais é que os bytecodes gerados pela JVM, quando compilado o arquivo “Ola.java”.
Os arquivos .java são os nossos códigos fontes e os .class são a execução deles, sendo que
se tentarmos abrir um arquivo .class irá aparecer vários caracteres especiais, sendo ilegível, ou
seja, ele transforma o código fonte para código de máquina sendo este independente de plataforma.
Agora, para finalizarmos, vamos ver a saída do programa digitando a linha abaixo:
java Ola
______________________________________________________________________________________________
Curso Técnico em Informática 24 Programação Java
O resultado deverá possuir a saída “Bem Vindo ao Mundo Java”.
1.8 Ferramentas
O desenvolvimento de software é uma das áreas que mais recursos livres possui,
frameworks multiplataforma, IDE4´s livres de alta qualidade, bancos de dados, entre outros. Nesta
apostila é apresentado algumas ferramentas que proporcionam maior qualidade no processo de
desenvolvimento de software, na linguagem Java, totalmente livres.
A seguir é apresentado um algumas das principais IDEs, de para desenvolvimento em Java.
Na área de desenvolvimento de software, muitos programadores (principalmente aqueles
que iniciam) possuem certo grau de indecisão sobre qual IDE utilizar. Atualmente, as duas IDEs
mais conhecidas e utilizadas para o desenvolvimento de software em Java são o Eclipse e o
NetBeans, sendo ótimas opções aos desenvolvedores, que muitas vezes se deparam com a dúvida
de qual escolher. Estes dois ambientes possuem código aberto e são gratuitos, podendo ser
utilizados para o desenvolvimento de aplicações em outras linguagens, além de Java, podendo
também serem executados em diversas plataformas, além do Windows.
Existem ainda outras IDEs, gratuítas, para o desenvolvimento de aplicações java, como o
JCreator, CodeBlock, BlueJ e outros.
1.8.1 Eclipse
O Eclipse é uma ferramenta IDE que compreende vários tipos de linguagem e que aceita a
instalação de plugins para emular o desenvolvimento da plataforma.
O projeto Eclipse foi iniciado pela IBM, que doou como software livre para a comunidade a
primeira versão do produto. Os autores que criam plug-ins para Eclipse ou que o usam como base
para um aplicativo de desenvolvimento de software são obrigados a liberar qualquer código ou
modificação do Eclipse que usarem de acordo com os termos da EPL, mas podem licenciar suas
próprias adições da maneira que desejarem.
Com o Eclipse boa parte da dificuldade em compilar o programa é descartada, pois, seu
editor de códigos possui muitas funcionalidades e ferramentas, facilitando o desenvolvimento da
aplicação.
Como desvantagem pode-se citar a falta de funcionalidades essenciais para o
desenvolvimento, como criação de telas GUI (Graphic User Interface) que são janelas de
4IDE : IDE é uma ferramenta que reúne recursos para que o desenvolvimento de software fique mais ágil e fácil,
possibilitando assim maior produtividade ao desenvolvedor.
______________________________________________________________________________________________
Curso Técnico em Informática 25 Programação Java
programas e sistemas comerciais, como as do Windows e do Linux) e design de páginas web.
1.8.2 NetBeans
O NetBeans é uma ferramenta IDE que permite o desenvolvimento rápido e fácil de
aplicações desktop Java, móveis e Web e também aplicações HTML5 com HTML, JavaScript e
CSS. O IDE também fornece um grande conjunto de ferramentas para desenvolvedores de PHP e
C/C++. Ela é gratuita e tem código-fonte aberto, além de uma grande comunidade de usuários e
desenvolvedores em todo o mundo.
O Netbeans foi desenvolvido por dois estudantes tchecos na Universidade de Charles,
em Praga, quando a linguagem de programação Java ainda não era tão popular como atualmente.
Primeiramente o nome do projeto era Xelfi, em alusão ao Delphi, pois a pretensão deste
projeto era ter funcionalidades semelhantes aos IDEs tão populares do Delphi, que eram mais atra-
tivas por serem ferramentas visuais e mais fáceis de usar, porém com o intuito de ser totalmente
desenvolvido em Java.
Em 1999 o projeto já havia evoluído para uma IDE proprietário, com o nome de NetBeans
DeveloperX2, nome que veio da ideia de reutilização de componentes que era a base do Java.
Nessa época a empresa Sun Microsystems havia desistido de sua IDE Java Workshop e, procu-
rando por novas iniciativas, adquiriu o projeto NetBeans DeveloperX2 incorporando-o a sua linha
de softwares.
Como uma das vantagens do NetBeans ele é 100% java, feito em Swing, portanto roda onde
houver uma JRE 1.3 compatível (Java Runtime Environment), suporta 'out-of-the-box' (sem plugins
extras) J2EE (EJBs, WebServices, JSP, etc), design visual de telas Swing. Versão 4.1 é uma versão
mais rápida e possui menos memória
Como desvantagens ele fica um pouco atrás nas funcionalidades na compilação de progra-
mas, poucos templates de código, pouco controle no código da aplicação por parte do desenvolve-
dor. A IDE gera código automaticamente sem que o desenvolvedor o conheça.
1.8.3 Jcreator
JCreator é um IDE Ambiente de Desenvolvimento Integrado criado pela Xinox Software
tendo as versões Pro e LE (Learn Edition) que suporta o desenvolvimento em Java,JavaS-
cript,XML,HTML.
JCreator é uma poderosa e interativa ferramenta de desenvolvimento (IDE) para JAVA que
com as seguintes características:
Manipulação de projetos em uma interface semelhante à do Microsoft Visual Studio;
Definição de esquemas de cor XML;
Reutilização de código de projetos existentes usando diferentes versões do JDK;
Modelos pré-definidos;
Permite manusear e intercambiar código com sua integração entre Ant e CVS.
Personalização da interface do usuário.
Como vantagem pode-se citar o uso dele pela web, incorpora Framework, desvantagens perde um
pouco em agilidade.
______________________________________________________________________________________________
Curso Técnico em Informática 26 Programação Java
1.8.4 BlueJ O BlueJ é um ambiente gratuito de desenvolvimento de aplicações orientadas a objetos
utilizando a linguagem de programação Java. Uma de suas características principais é a facilidade
de aprendizagem de programação OO, através de recursos visuais interativos. Por exemplo,
classes e relacionamentos podem ser definidos visualmente, e é possível verificar o comportamento
dos objetos em memória durante a execução.
O BlueJ é resultado de um projeto de pesquisa voltado ao ensino de orientação a objetos
para iniciantes, desenvolvido pela Deakin University (Austrália) e University of Kent (Inglaterra),
com contribuições de diversos outros grupos. É também suportado pela Sun Microsystems. O
projeto "NetBeans BlueJ Edition", que recentemente liberou sua primeira versão beta, permite a
migração suave de iniciantes utilizando do BlueJ para um IDE profissional.
1.9 IDE Netbeans
Os exemplos apresentados doravante serão construídos utilizando a IDE NetBeans.
Portanto faz-se necessário uma apresentação mais detalhada desta ferramenta. A seguir é
apresentado os recursos mais utilizados desta ferramenta.
Criação de Projeto:
1 – Abrir a ferramenta NetBeans, clicar em “Arquivo”, “Novo Projeto”.
2- Em “Novo Projeto”, selecionar a opção “aplicação JAVA”, então “Próximo”.
______________________________________________________________________________________________
Curso Técnico em Informática 27 Programação Java
Criando classe:
______________________________________________________________________________________________
Curso Técnico em Informática 28 Programação Java
Criando primeiro programa em Java
Execução do Programa:
Antes de apresentar a sintaxe da linguagem Java, é importante apresentar alguns conceitos
básicos e essenciais para a programação, utilizando como ferramenta a linguagem Java, que se
baseia nas linguagens C e C++.
Um programa escrito em Java é composto de classes que possuem atributos e métodos. Os
atributos em uma classe são variáveis que podem ser modificadas ao longo da execução do
programa, já os métodos, executam determinadas tarefas a partir de informações de entrada,
retornando ou não, respostas.
Java é totalmente orientada a objetos, ...
Linguagem Java 2
______________________________________________________________________________________________
Curso Técnico em Informática 29 Programação Java
2.1 Sintaxe Java
O formato de codificação da linguagem Java deve seguir uma serie de diretrizes para que
os algoritmos possam ser implementados. Um algoritmo é um procedimento para resolver um
problema em um número finito de passos, que frequentemente envolve a repetição de operações.
2.1.1 Delimitadores em Java
Em um código-fonte Java, alguns símbolos são utilizados pelo compilador para diferenciar
comandos, blocos de comandos, métodos, classes, etc. Tais símbolos, chamados de delimitadores,
são enumerados a seguir:
2.1.1.1 Comentários
Comentários servem para identificar a função de um comando, um trecho de código, ou um
método.
Além disso, os comentários podem ser utilizados para documentar aspectos de
desenvolvimento de um programa: como o nome da empresa que o desenvolveu, nome dos
programadores, versão, etc. Existem dois tipos de comentário: o simples e o de documentação.
O comentário simples é delimitado por duas barras // e termina ao final de uma linha. O
comentário de documentação é iniciado pelo símbolo /** e encerrado pelo símbolo */, podendo
conter várias linhas de texto e linhas em branco.
2.1.1.2 Blocos
Um bloco é formado por um conjunto de instruções delimitadas por chaves, como no
exemplo abaixo:
Ponto e vírgula, blocos e espaços em branco: em Java, todo comando é terminado por um ponto
e vírgula (;). Exemplo: System.out.println("note o ponto e vírgula no final ");
Espaço em branco, quebra de linha e caracteres de tabulação são permitidos em qualquer
______________________________________________________________________________________________
Curso Técnico em Informática 30 Programação Java
trecho do código-fonte, devendo ser utilizados para realçar o aspecto visual de seu código. Apesar
do aspecto visual do código-fonte não ter nenhum impacto no desempenho de um programa Java,
o uso de endentação é uma característica de bons códigos-fonte. Um único programador não será
o único a ler o código-fonte de seus programas, portanto o programa deve ser escrito da maneira
mais organizada e legível possível.
2.1.2 Identificadores e palavras reservadas
Em Java, um identificador é uma sequência de símbolos UNICODE (64K símbolos) que
começa com uma letra, um símbolo subscrito _, ou o caractere $. Os demais símbolos de um
identificador podem conter também números. Identificadores são case-sensitive e não tem um
tamanho máximo estabelecido. Apesar da tabela UNICODE ser bastante extensa, um bom hábito
de programação é utilizar somente letras do alfabeto (a-Z) e números para nomear identificadores.
Exemplo de identificadores Válidos:
data
_data
$data
data_do_mês
data1
uma_variável_pode_SER_bastante_extensa_e_conter_Numeros234876238476
data_public_class_NoteQueEsseIdentificadorContemPalavrasReservadas
Apesar desta "liberdade" de opções para nomes de identificadores, algumas palavras não
são permitidas. Tais palavras são ditas palavras reservadas, e representam o conjunto de
comandos que forma a sintaxe da linguagem Java. O conjunto de palavras reservadas em Java é
o seguinte:
abstract
boolean
break
byte
case
catch
char
class
const
continue
default
double
else
extends
final
finally
float
for
goto
if
implements
import
int
interface
long
native
new
package
private
protected
public
return
short
strictfp
super
switch
synchronized
this
throw
______________________________________________________________________________________________
Curso Técnico em Informática 31 Programação Java
throws
transient
try
void
volatile
static
while
Não é preciso se preocupar em memorizar o nome das palavras reservadas em Java. À
medida que se pratica a programação em Java, isso se tornará natural. Além disso, o compilador
acusa um erro de nomenclatura quando se tenta utilizar uma palavra reservada para nomear uma
variável, um método ou uma classe.
2.1.3 Declaração de Variáveis
Uma variável é sempre declarada seguindo do seguinte esquema:
<tipo> + <espaço> + identificador + ;
ou
<tipo> + <espaço> + identificador + = + valor + ;
onde:
<tipo> é um tipo primitivo de dados ou o nome de uma classe ou interface
identificador é o nome da variável
valor é o valor atribuído à variável. No caso de uma variável ser declarada sem atribuir um valor,
ela não poderá ser utilizada em um código Java, a tentativa de utilizar uma variável não inicializada
em Java gerará um erro de compilação. Exemplos:
Posteriormente será visto que Java possui um mecanismo de inicialização de variáveis de
seus tipos primitivos, mas o aluno deve evitar considerar essa inicialização como prática de
programação. De fato, esta inicialização automática não funciona para variáveis de tipos agregados
ou abstratos de dados e também que o escopo das variáveis, de classe ou de instância, tem
influência na sua inicialização. O aluno é fortemente recomendado a pensar em variáveis como
espaços alocados na memória RAM, inicialmente podendo conter qualquer valor (conhecido como
lixo na memória).
______________________________________________________________________________________________
Curso Técnico em Informática 32 Programação Java
2.1.4 Tipos primitivos
A linguagem Java utiliza oito tipos primitivos de dados e um tipo especial. Esses tipos
primitivos podem ser utilizados para declarar constantes ou variáveis utilizadas em programas Java.
Os tipos primitivos estão divididos em quatro categorias: lógicos, textuais, numéricos inteiros e
numéricos de ponto flutuante.
2.1.4.1 Tipos lógicos: boolean
Valores lógicos possuem dois estados, normalmente ditos verdadeiro/falso, sim/não e ligado/
desligado. Em Java um tipo lógico é definido pela palavra boolean, e pode assumir dois valores:
true ou false.
2.1.4.2 Tipos textuais: char e String
Caracteres simples são representados pelo tipo char. Um char representa um caracter
UNICODE, ou seja, um número inteiro sem sinal de 16 bits, no intervalo de 0 até 216 -1. O valor de
um literal char deve ser delimitado por aspas simples:
Palavras são representadas por uma sequência de dados do tipo char, agrupadas em um
tipo especial de dados: a classe String. Apesar de ser uma classe, uma variável do tipo String
______________________________________________________________________________________________
Curso Técnico em Informática 33 Programação Java
suporta operações como se fosse um tipo primitivo de dados. O valor de uma variável String deve
ser delimitado por aspas duplas "valor". A concatenação de qualquer tipo de dado com um dado do
tipo String resulta em um novo dado do tipo String.
2.1.4.3 Tipos numéricos inteiros: byte, short, int e long
Existem quatro tipos primitivos de números em Java. Além disso, os valores numéricos
podem ser representados de forma decimal, octal ou hexadecimal:
Valores numéricos inteiros em Java:
2 decimal
077 um número que começa com zero está representado de forma octal
0xBABE representação hexadecimal
Todos os valores numéricos em Java têm sinal positivo ou negativo. Um valor numérico é
sempre considerado do tipo int, a menos que seja acompanhado do sufixo L, que representa um
valor do tipo long. A diferença de um inteiro para um longo é a capacidade de dígitos que podem
ser representados, conforme aparece no quadro abaixo.
Valores numéricos em Java, representados como long:
2L decimal
077L um número que começa com zero está representado de forma octal
0xBABEL representação hexadecimal
2.1.4.4 Tipos numéricos de ponto flutuante: float e double
Um valor fracionário pode ser representado em Java através dos tipos float e double. A
diferença entre esses dois tipos é o tamanho da mantissa:
float 32 bits
double 64 bits
Para um número ser considerado do tipo ponto flutuante, é necessário a inclusão de um ponto, do
caractere E (de expoente) ou do sufixo D ou F, conforme mostra o quadro abaixo:
// Representação de valores numéricos de ponto flutuante
float pi = 3.141516;
float taxa = 6.02E23;
double valor= 123.4E+306D;
Todo o valor numérico de ponto flutuante é considerado do tipo double, a menos que o programador
o declare explicitamente como float.
2.2 Convenções de codificação
Durante os estudos realizados a partir desta disciplina, será adotada a seguinte convenção
______________________________________________________________________________________________
Curso Técnico em Informática 34 Programação Java
de codificação:
Classes: as classes devem ser designadas por nomes, começando por uma letra maiúscula
e depois minúsculas. Cada nova palavra que formar o nome da classe deve ser capitalizada.
Ex: class Calculadora, class CalculadoraCientifica, ...
Interfaces: igual às classes. Ex: interface Calculo, interface EquacaoLogaritmica, ...
Métodos: métodos devem ser nomeados por verbos, seguindo o mesmo formato de
capitalização das classes. Entretanto, um método sempre deve começar com letra
minúscula. Ex: public void calcular(int numero), public void extrairRaiz(int numero), ...
Constantes: constantes devem ter todas as suas letras em maiúsculo, com o símbolo de
subscrito para separa as palavras. Ex: final int ANO = 2002, final boolean VERDADE =
true, ...
Variáveis: tal qual os métodos, as variáveis devem começar com uma letra minúscula e
depois alternar a cada palavra. Procure usar nomes significativos para variáveis. Evite
declarar variáveis usando apenas um a letra.
Através de expressões é implementado a manipulação de variáveis e implementação de
tomada de decisões em programas Java.
3.1 Operadores
Os operadores Java são similares em estilo e função aos operadores da linguagem C/C++.
A tabela abaixo enumera esses operadores em ordem de precedência:
3.1.1 Operadores Delimitadores
. [] () ; , Servem para delimitar partes distintas de um comando, método ou classe.
3.1.2 Operadores Aritméticos
+ Adição
- Subtração
* Multiplicação
/ Divisão
% Resto (Modulo)
Expressões 3
______________________________________________________________________________________________
Curso Técnico em Informática 35 Programação Java
3.1.3 Operadores de Atribuição
+= x += y → x=x + y
-= x -= y → x=x - y
*= x *= y → x=x * y
/= x /= y → x=x / y
%= x %= y → x=x % y
3.1.4 Operadores Unários + e - Para mudar o sinal do operando.
3.1.5 Operadores de Incremento e Decremento ++ Incremento Ex: x++ → x=x+1
-- Decremento Ex: x-- → x=x-1
3.1.6 Operadores Relacionais
> Maior que
< Menor que
== Igual a
!= Diferente de
>= Maior ou igual
<= Menor ou igual
3.1.7 Operadores Lógicos
&& Devolve true se ambos operandos forem true.
||
!
Esses operadores permitem a representação de expressões booleanas, que formam o argumento
para comandos de decisão (IF), seguindo a seguinte tabela:
AND
true && true = true;
false && false = false;
false && true = false;
true && false = false;
OR
true || true = true
false || false = false
false || true = true
true || false = true
Os comandos de controle (if, while, switch) utilizam o valor de expressões booleanas para guiar o
fluxo de controle de um programa, como no exemplo a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 36 Programação Java
3.1.8 Operador de concatenação + Concatena (junta) dados do tipo string
Quando o operador + é aplicado a dados do tipo String, ele cria um novo dado do tipo String,
concatenando os dois operandos:
/**
* Concatenação de Strings
*/
String sigla = "CIMOL";
String nome = "Escola Estadual Monteiro Lobato";
String titulo = sigla + " - " + nome;
// Esse comando imprimirá na tela a frase:
// SOO-I – Sistemas Orientados a Objetos I
System.out.prinln(titulo);
int i = 10;
String legenda = "valor = ";
// campo é uma variável do tipo String
String campo = legenda + i;
3.1.9 Operadores de deslocamento
>> É usado para deslocar o padrão de bits para a direita respeitando o bit do
sinal, ou seja, tudo é deslocado, menos o primeiro bit.
<< É usado para deslocar os bits para a esquerda.
>>> Não respeita o sinal, ou seja, realmente todo mundo é deslocado para
direita, e é colocado um bit com valor 0 à esquerda do padrão.
O operador de deslocamento aritmético >> executa um deslocamento de um bit para a direita
de um número (na prática, o primeiro argumento desse operador é dividido por dois 'n' vezes –
onde n é o segundo argumento do operador):
8 >> 2 = 2
______________________________________________________________________________________________
Curso Técnico em Informática 37 Programação Java
128 >> 1 = 64
256 >> 4 = 16
Notação em complemento de dois: o operador >> mantém o sinal do bit mais significativo
durante o deslocamento.
O operador de deslocamento lógico >>> executa um deslocamento no padrão dos bits ao
invés do significado aritmético de um valor numérico. Esse operador sempre adiciona o valor 0 ao
bit mais significativo:
1010 ... >> 2 = 111010 ...
1010 ... >>> 2 = 001010 …
Os operadores de deslocamento reduzem seus operandos à direita módulo 32 para um valor
do tipo int e módulo 64 para um tipo long. Dessa forma, para qualquer valor do tipo int:
int x
x >>> 32 = x
O operador de deslocamento lógico >>> só pode ser aplicado a valores inteiros, e não é
efetivo em valores int e long. Se for aplicado a valor short ou byte, o valor será promovido a um int
antes da aplicação do operador. Por isso, um deslocamento sem sinal acaba se tornando um
deslocamento com sinal.
3.2 Casting
A linguagem Java não suporta atribuições arbitrárias entre variáveis de tipos diferentes. Por
exemplo, você não pode inicializar uma variável inteira com um valor de ponto flutuante sem
explicitar isso através de um processo que chamamos de casting.
Quando atribuímos um valor a uma variável, e esse valor é incompatível com o tipo de dado
definido para a variável, ocorrerá uma conversão. Em alguns casos, essa conversão será
automática, em outros o programador deve indicar de que forma o valor será convertido ao tipo de
dado da variável.
Quando o processo de conversão for automático, dizemos que ocorreu uma promoção, ou
seja, um valor com um tipo de dado foi promovido a outro tipo de dado. Veja no exemplo abaixo:
// Promoção entre valores de tipos de dados distintos
// Apesar 6 ser um inteiro, o valor da variável grande
// continua sendo do tipo long
long grande = 6;
// Uma variável do tipo inteiro não possui
// espaço para armazenar um valor longo.
// A instrução abaixo é ilegal, e causará um erro de compilação.
int pequeno = 99L;
float a = 12.121F;
float b = 12.121;
// correto
// 12.121 é um double - incorreto
Como visto acima, algumas conversões não podem ser realizadas de forma automática, pois
______________________________________________________________________________________________
Curso Técnico em Informática 38 Programação Java
o compilador não pode assumir que tipo de conversão ele deve realizar (o tamanho do tipo de dado
a ser recebido por uma variável é maior que o tamanho pré-definido para o tipo dessa variável, logo
o compilador não sabe como "ajustar" os bits excedentes). Nesse caso, o programador deve indicar
ao compilador que tipo de conversão deverá ocorrer, digitando o tipo de dado que o valor deverá
assumir entre parênteses:
// Casting entre valores de tipos de dados distintos
// Apesar 6 ser um inteiro, o valor da variável grande
// continua sendo do tipo long
long grande = 6;
int pequeno = (int)99L; // sem problemas
float a = 12.121F;
float b = (float)a;
// sem problemas
3.3 Recebendo dados do usuário
Até este momento as variáveis estão sendo definidas juntamente com seus valores durante
a programação. Mas e se for necessário obter essa informação do usuário? Por exemplo, para
perguntar a idade ou para criar uma calculadora? Depende do que for digitado.
De agora em diante será utilizado a classe Scanner para realizar a leitura de dados a partir do
teclado.
3.3.1 Importando (import) classes (class) e pacotes (packages)
Existem milhares de funcionalidades no Java. Essas classes foram agrupadas em pacotes,
os packages.
E pacotes para a mesma funcionalidade são chamados de API (Application Programming
Interface). Por exemplo, tem uma seção sobre a API Java 2D, para fazer desenhos em 2D. Ou seja,
são uma série de pacotes para desenhar.
Porém, todos esses pacotes não estão simplesmente prontos para serem utilizados, pois
são muitos.
Inclusive, pode ser criado pacotes customizados, pode baixar, reutilizar, compartilhar, vender
etc.
Se todos estes estivessem prontos para utilização, demoraria MUITO para rodar um
programa em Java.
Para solucionar este problema, diz ao Java quais funcionalidades pretende-se usar. Pra isso,
usa-se a função 'import':
Import pacote_que_quer_importar;
Por exemplo: para usar print, printf e println, não precisa dizer nada ao Java. São métodos
tão comuns que podem ser usados automaticamente em qualquer aplicação. Esses métodos fazem
parte de um pacote chamado 'java.lang'.
Para receber dados do usuário, utiliza-se a classe Scanner, que faz parte do pacote 'java.util'.
Diz ao Java que essa classe será utilizada na aplicação. Para isso, adiciona-se essa linha no
começo do programa:
______________________________________________________________________________________________
Curso Técnico em Informática 39 Programação Java
import java.util.Scanner;
O próximo passo é declarar objeto do tipo Scanner. Chamá-lo de 'entrada'. Sua declaração
é feita da seguinte maneira:
Scanner entrada = new Scanner(System.in);
Agora, o objeto 'entrada' será usado para ler entradas do sistema.
Para o Java, há muita diferença entre inteiros, float, doubles e outros tipos. Portanto, é
necessário ser bem claro quanto ao tipo de dado que vai ser lido. Assim, a entrada será bem tipada.
Para receber um número inteiro do usuário, com nosso objeto 'entrada', usaremos a seguinte
sintaxe: inteiro = entrada.nextInt();
Esse é um exemplo bem simples que pergunta a idade do usuário, espera ele digitar (e teclar enter)
e exibe essa mensagem na tela:
No exemplo anterior foi realizado a leitura de um número inteiro. Caso o tipo de dados a ser lido
seja diferente de inteiro, deverá ser utilizado outro método, equivalente ao tipo de dados a ser
lido. Ex: Tipo double → entrada.nextDouble()
Mais informações sobre os métodos da classe Scanner pode ser encontrada na
documentação do Java: https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html.
De acordo com Santos (2010), no desenvolvimento de um programa, muitas vezes se faz
necessário o conhecimento de uma resposta para se possa decidir qual bloco de comando será
executado. Isto é alcançado através dos comandos de controle de fluxo disponibilizados pela
linguagem de programação. Desta forma, os comandos de controle de fluxo de uma linguagem de
programação especificam a ordem em que processamento é feito.
Controle de fluxo é a habilidade de ajustar a maneira como um programa realiza suas tarefas.
Por meio de instruções especiais, chamadas comandos. Essas tarefas podem ser executadas
seletivamente, repetidamente ou excepcionalmente. Não fosse o controle de fluxo, um programa
Controle de Fluxo 4
______________________________________________________________________________________________
Curso Técnico em Informática 40 Programação Java
poderia executar apenas uma única sequência de tarefas, perdendo completamente uma das
características mais interessantes da programação: a dinâmica.
Pode-se classificar os comandos aceitos pela linguagem Java em basicamente quatro categorias:
Comando Palavra Chave
Tomada de decisões if-else, switch-case
Laços ou repetições for, while, do-while
Apontamento e tratamento de
exceções
try-catch-finally, throw
outros break, continue, label:, return
4.1 Execução Condicional
4.1.1 Comando if
A forma mais simples de controle de fluxo é o comando if. Ele é empregado para executar
seletivamente ou condicionalmente um outro comando mediante um critério de seleção. Esse
critério é dado por uma expressão, cujo valor resultante deve ser um dado do tipo booleano, isto
é, true ou false. Se esse valor for true, então o outro comando é executado; se for false, a
execução do programa segue adiante. A sintaxe para esse comando é:
if ([condição])
[comando] // Executado se a condição for true
Exemplo:
Exercícios:
1) Crie um programa em que o usuário informa o nome de um mês (ex: janeiro) e o programa exibe
o número correspondente a esse mesmo mês (ex: 1);
2) Faça um programa que para n==5 exiba uma mensagem de parabéns;
3) Crie um menu de uma biblioteca da seguinte maneira: 1. Retirar um livro; 2. Devolver um livro e
3. Renovar a retirada de um livro. Em seguida, conforme a opção digitada pelo usuário, mostrar as
mensagens: 1. Livro retirado com sucesso! 2. Livro devolvido com sucesso e 3. Livro renovado.
______________________________________________________________________________________________
Curso Técnico em Informática 41 Programação Java
4) Faça um programa usando o desvio condicional "IF", que leia o nome e a idade de 1 nadador e
exiba na tela o nome da categoria a qual este nadador pertence. A categoria dos nadadores é dada
pela seguinte tabela:
5) Usando o comando de desvio condicional simples “IF”, faça um programa que leia uma senha
de 8 caracteres inteiros e verifique se a senha informada equivale a senha predefinida no programa.
Se for válida informe na tela "Acesso Autorizado. Caso a senha não estiver correta informe "Acesso
negado".
4.1.2 Comando if-else
Uma variação do comando if, e o if-else que permitem escolher alternadamente entre dois
outros comandos a executar. Nesse caso, se o valor da expressão condicional que define o critério
de seleção for true, então o primeiro dos outros dois comandos é executado, do contrário, o
segundo.
if([condição]) [comando 1] // Executado se a condição for true else [comando 2] // Executado se a condição for false
Exemplo:
O if-else compacto não é propriamente um comando, mas um operador que realiza
avaliação seletiva de seus operandos, mediante o valor de uma expressão booleana semelhante à
do comando if-else. Se essa expressão for true, então um primeiro operando é avaliado; se for
false então o segundo operando é avaliado. A sua sintaxe é:
[expressão condicional] ? [expressão 1] : [expressão 2]
onde [condição condicional] deve resultar em true ou false,[expressão1] e [expressão 2] são
os operandos, que podem ser expressões quaisquer. O valor resultante da aplicação do operador
if-else compacto é obviamente igual ao valor do operando que tiver sido avaliado. O tipo desse
valor obedece às regras de conversão de tipos de dados discutida anteriormente.
Para melhor ilustrar o if-else compacto, considera-se o seguinte comando:
y = x < 1 ? x*x : 2-x;
______________________________________________________________________________________________
Curso Técnico em Informática 42 Programação Java
Este é logicamente equivalente à seguinte sequência de comandos:
if (x<1) then
y = x*x;
else
y = 2-x;
4.1.3 Condicional ternário
O operador condicional ternário, também chamado de if-else compacto, é uma forma
composta de expressar uma instrução if-else:
(condição)? “Operação caso verdadeiro” : “operação caso falso”;
Exemplo:
int m = x < y ? x : y
Na instrução anterior é testado a condição, e caso, for verdadeira atribui x para m, senão
atribui y para m.
É importante notar que o operador condicional ternário é de baixa precedência, logo o uso
de parênteses para separar seus operandos não é necessário (a menos que mais de um desses
operadores esteja presente na mesma expressão). Porém há casos em que o uso de parênteses
para definir claramente os operandos é essencial. Por exemplo, y = |x|*sin(x), pode ser codificado
como:
y = ( x<0 ? -x : x ) * Math.sin(x); // aqui os parenteses são essenciais.
Sem os parênteses, x * Math.sin(x) seria visto pelo operador if-else compacto como se fosse um
único operando, devido à alta precedência do operador multiplicação.
4.1.4 Comando If-else Aninhados
No comando utilizando if-else aninhado o else é sempre associado ao if mais interno (mais
próximo). Frequentemente, deseja-se que um único comando (ou único bloco de comandos) de
uma lista seja executado mediante um dado critério. Isso pode ser feito através do aninhamento ou
acoplamento de vários comandos if-else, do seguinte modo:
if ([condição 1])
[comando 1]
else if ([condição 2])
[comandos 2])
else if ([condição 3])
[comando 3]
....
else
[comando n]
A presença do último else, juntamente com seu comando, é opcional. Neste código,
o [comando 1] será executado (e os demais saltados) caso a primeira condição seja true,
o [comando 2] será executado (e os demais saltados) caso a primeira condição seja false e a
segunda condição seja true, e assim sucessivamente. O [comando n] (se houver) somente será
executado (e os demais saltados) caso todas as condições sejam false.
______________________________________________________________________________________________
Curso Técnico em Informática 43 Programação Java
Exemplo:
Exercícios:
1) Escreva um programa em Java que recebe um inteiro e diga se é par ou ímpar.
Use o operador matemático % (resto da divisão ou módulo) e o teste condicional if
2) Crie um programa que teste se o valor que usuário digitou está entre 10 e 15 e exiba alguma
mensagem na tela.
3) Faça um programa que solicite ao usuário digitar dois valores, em seguida, exiba na tela qual
dos dois é o maior. OBS: o usuário poderá informar valores iguais, logo, o sistema deve dizer que
foram digitados valores iguais.
4) Crie um algoritmo que pergunte ao usuário se ele deseja converter uma temperatura de graus
Celsius em graus Fahrenheit ou Fahrenheit em Celsius. Em seguida mostre na tela o valor final
correspondente a opção escolhida pelo usuário. F = 1.8 * C + 32 | C = (F – 32) / 1.8;
5) A calculadora de Luciana pifou, justo quando ela precisa fazer vários cálculos. Ela tem um
computador, mas não sabe que um dos acessórios do Windows é uma calculadora. Sendo
estudante de programação, Luciana resolveu fazer um programa. A especificação que bolou prevê
que programa leia dois números inteiros (o que atende suas necessidades) e em seguida um
símbolo de operação. Se este for '+', o programa soma os números, se '-', subtrai, se '*' multiplica
e se '/' divide. Se o símbolo for diferente desses, é mostrada uma mensagem de erro. O programa,
antes de dividir, critica se o divisor é zero e mostra uma mensagem de erro neste caso. Implemente
um programa que construa essa calculadora para Luciana, utilizando o desvio condicional "IF" e
“ELSE”. Crie também procedimentos para executar cada uma das funções da calculadora.
6) Receba três valores fornecidos pelo usuário que representarão os lados de um triângulo.
______________________________________________________________________________________________
Curso Técnico em Informática 44 Programação Java
Verifique se os valores formam um triângulo e classifique esse triângulo como:
a) Equilátero: três lados iguais.
b) Isósceles: dois lados iguais.
c) Escaleno: três lados diferentes.
Lembre-se de que, para formar um triângulo, nenhum dos lados pode ser igual a zero, um lado não
pode ser maior do que a soma dos outros dois.
7) A partir de 3 notas fornecidas de um aluno, informe se ele foi aprovado, ficou de recuperação ou foi reprovado. A média de aprovação é >= 7.0; a média de recuperação é >= 5.0 e < 7.0; e a média do reprovado é < 5.0
8) Solicite o nome e a idade de duas pessoas. Em seguida exiba o nome da pessoa mais velha e
o nome da pessoa mais nova.
9) Verifique quem entre duas pessoas faz aniversário primeiro. Exiba o nome do primeiro aniversa-
riante considerando que estamos no dia 1 de janeiro. Use como entrada o nome, o dia e o mês de
nascimento de cada pessoa.
10) Receba 2 horários e exiba a diferença entre eles em segundos. A entrada destes horários pode
ocorrer em qualquer ordem.
Dica: transforme os dois horários para segundos.
4.1.5 Comando switch
Assim como no caso da execução seletiva de múltiplos comandos, utilizando if-else
aninhados, há situações em que se sabe de antemão que as condições assumem o valor true de
forma mutuamente exclusiva, isto é, apenas uma entre as condições sendo testadas assume o
valor true num mesmo momento. Nesses casos, a linguagem Java (como também as linguagem
C, C++ e Pascal) provê um comando de controle de fluxo bastante poderoso. Trata-se do
comando swich, cuja sintaxe é a seguinte:
switch([expressão]) {
case [constante 1]:
[comando 1]
break;
case [constante 2]:
[comando 2]
break;
.
.
.
case [constante n]:
[de comando n]
break;
default:
[comando]
}
______________________________________________________________________________________________
Curso Técnico em Informática 45 Programação Java
A [expressão] pode ser qualquer expressão válida. Esta é avaliada e o seu valor resultante
é comparado com as constantes distintas [constante 1],[constante 2], ..., [constante n]. Caso
esse valor seja igual a uma dessas constantes, o respectivo comando é executado (e todos os
demais são saltados). Se o valor for diferente de todas essas constantes, então o comando
presente sob o rótulo default: é executado (e todos os demais são saltados), caso este esteja
presente.
Exemplo:
A opção default, é opcional, caso nenhuma das opções for executada, o switch não executará
nada. Somente serão aceitos valores int e char.
Exercícios:
1) Crie um programa que exibe se um dia é dia útil, fim de semana ou dia inválido dado o número
referente ao dia. Considere que domingo é o dia 1 e sábado é o dia 7.
2) Ler o código de um produto e exibir seu nome de acordo com a tabela a seguir:
3) Criar um programa para identificar o valor a ser pago por um plano de saúde dada a idade do
conveniado considerando que todos pagam R$ 100 mais um adicional conforme os seguintes
dados:
a) crianças com menos de 10 anos pagam R$80;
b) conveniados com idade entre 10 e 30 anos pagam R$50;
c) conveniados com idade entre 40 e 60 anos pagam R$ 95;
d) conveniados com mais de 60 anos pagam R$130.
______________________________________________________________________________________________
Curso Técnico em Informática 46 Programação Java
Exercícios:
1) Faça um programa que transforme um número Racional (formado por numerador e
denominador) para um número Real. Antes de dividir, verifique se o denominador é diferente de
zero. Emita uma mensagem de alerta ao usuário se for zero.
3) Um banco concede empréstimo a seus clientes no valor máximo de 30% do valor do seu salário
líquido. Receba o valor do salário bruto, o valor dos descontos e o valor do possível empréstimo de
um cliente, em seguida avise se ele poderá ou não fazer o empréstimo.
4) Escreva um programa que a partir de 3 notas fornecidas de um aluno, informe se ele foi aprovado,
ficou de recuperação ou foi reprovado. A média de aprovação é >= 7.0; a média de recuperação
é >= 5.0 e < 7.0; e a média do reprovado é < 5.0
5) Faça um programa que receba do usuário o nome de um mês. Exiba o número equivalente deste
mês. Caso seja informado um mês que não existe, deve ser informado ao usuário.
6) Faça um programa que verifique a validade de uma data de aniversário (solicite apenas o número
do dia e do mês). Além de falar se a data está ok, informe também o nome do mês. Dica: meses
com 30 dias: abril, junho, setembro e novembro.
7) Faça um programa que receba três valores inteiros, e exiba estes números em ordem crescente.
8) Faça um programa que solicite o nome e a idade de 2 pessoas. Em seguida exiba o nome da
pessoa mais velha e o nome da pessoa mais nova.
9) Escreva um programa que receba 2 horários e exiba a diferença entre eles em segundos.
10) Elaborar um programa que verifique quem entre duas pessoas faz aniversário primeiro. Exiba
o nome do primeiro aniversariante considerando que estamos no dia 1 de janeiro. Use como
entrada o nome, o dia e o mês de nascimento de cada pessoa.
11) As Organizações Tabajara resolveram dar um aumento de salário aos seus colaboradores e lhe
contrataram para desenvolver o programa que calculará os reajustes.
Faça um programa que recebe o salário de um colaborador e o reajuste segundo o seguinte critério,
baseado no salário atual:
Salários até R$ 280,00 (incluindo) : aumento de 20%;
Salários entre R$ 280,00 e R$ 700,00 : aumento de 15%;
Salários entre R$ 700,00 e R$ 1500,00 : aumento de 10%;
Salários de R$ 1500,00 em diante : aumento de 5% Após o aumento ser realizado, informe
na tela: O salário antes do reajuste;
O percentual de aumento aplicado;
O valor do aumento;
O novo salário, após o aumento.
______________________________________________________________________________________________
Curso Técnico em Informática 47 Programação Java
12) Faça um programa que calcule as raízes de uma equação do segundo grau, na forma ax2 + bx
+ c. O programa deverá pedir os valores de a, b e c e fazer as consistências, informando ao usuário
nas seguintes situações:
a) Se o usuário informar o valor de A igual a zero, a equação não é do segundo grau e o
programa não deve fazer pedir os demais valores, sendo encerrado;
b) Se o delta calculado for negativo, a equação não possui raízes reais. Informe ao usuário
e encerre o programa;
c) Se o delta calculado for igual a zero a equação possui apenas uma raiz real; informe-a ao
usuário;
d) Se o delta for positivo, a equação possui duas raízes reais; informe-as ao usuário;
13) Chaves foi ao Paraguai e realizou a compra de alguns artigos lá. Com base na tabela abaixo
informe a porcentagem do imposto a ser pago e o valor total.
VALOR IMPOSTO %
Até R$10 3%
De R$10,01 a
R$99,99 5%
De R$100 a
R$299,99 10%
Acima de R$300 30%
14) Faça um programa onde o operador de distribuição dos correios digite o código de destino
impresso nas caixas e o sistema exibe o local para onde a encomenda se destina.
CÓDIGO
DESTINO DESTINO
1 a 5 BRASIL
6 A 9 EUA
10, 11 e 12 RÚSSIA
De 15 a 20 ou de
30 a 35 SUÍCA
13 a 14 AFEGANISTÃO
21 a 29 FRANÇA
15) Um posto está vendendo combustíveis conforme os seguintes descontos:
Álcool:
______________________________________________________________________________________________
Curso Técnico em Informática 48 Programação Java
a. até 20 litros, desconto de 3% por litro
b. acima de 20 litros, desconto de 5% por litro
Gasolina:
c. até 20 litros, desconto de 4% por litro
d. acima de 20 litros, desconto de 6% por litro
Escreva um algoritmo que leia o número de litros vendidos, o tipo de combustível (codificado da
seguinte forma: A-álcool, G- gasolina), calcule e imprima o valor a ser pago pelo cliente sabendo-
se que o preço do litro da gasolina é R$ 2,50 o preço do litro do álcool é R$ 1,90.
4.2 Laços de Repetição
Frequentemente em aplicações é preciso repetir a execução de um bloco de códigos do
programa até que determinada condição seja verdadeira, ou senão até uma quantidade de vezes
seja satisfeita. Para que essas repetições sejam possíveis, utiliza-se os laços de repetições.
A condição a ser analisada para a execução do laço de repetição deverá retornar um valor
booleano. Podendo acontecer de maneira pré definida como acontece no laço for, ou com o final
aberto como ocorre com os laços while e do-while.
4.2.1 Comando While Esta instrução é usada quando não se sabe quantas vezes um determinado bloco de
instruções precisa ser repetido. Com ele, a execução das instruções vai continuar até que uma
condição seja verdadeira.
Na estrutura while pode ter uma condição de termino definida já no início ou não.
Necessariamente ele testa a condição e se caso for verdadeiro executa o bloco, caso seja falso ele
vai para a próxima instrução fora do laço.
While (Condição)
{
Comandos;
}
Uma condição deve ser qualquer expressão valida que tenha como resultado true ou false.
Somente se a condição for verdadeira o corpo do laço de repetição, com seus respectivos
comandos, serão executados. Portanto, o conteúdo será repetido até que esta condição não seja
mais verdadeira.
Exemplo:
Pode ocorrer casos em que o laço de repetição while pode não ser executado. Isso pode
ocorrer quando, na primeira verificação da condição, ela for falsa. Neste cenário, o programa
simplesmente irá “pular” para a execução da próxima instrução após o laço.
Exercícios:
1) Escreva um aplicativo em Java que mostra todos os números ímpares de 1 até 100.
______________________________________________________________________________________________
Curso Técnico em Informática 49 Programação Java
2) Escreva um programa que pergunte ao usuário quantos alunos tem na sala dele.
Em seguida, através de um laço while, peça ao usuário para que entre com as notas de todos os
alunos da sala, um por vez. Por fim, o programa deve mostrar a média, aritmética, da turma.
3) Escreva um programa que pergunta um número ao usuário, e mostra sua tabuada completa (de
1 até 10).
4) Faça um programa que, para um número indeterminado de pessoas: leia a idade de cada uma,
sendo que a idade 0 (zero) indica o fim da leitura e não deve ser considerada. A seguir calcule:
o número de pessoas;
a idade média do grupo;
a menor idade e a maior idade.
5) Crie um programa simulando o acesso a uma conta bancária, onde ele tenha 3 chances para
acertar a senha. Se na quarta vez ele errar, o programa exibe a mensagem de “conta bloqueada”
e, se ele digitar a senha correta exiba a mensagem “bem vindo usuário”.
4.2.2 Comando do-while Com a estrutura do while, as instruções que estiverem dentro do bloco do{} serão
executadas e, logo depois, a condição será testada. Com do while, mesmo que a condição nunca
seja verdadeira, as instruções sempre serão executadas pelo menos uma vez, pois o teste da
condição ocorre no final do laço.
do{
instruções
}while(condição);
O comando do-while deve ser usado quando não se sabe exatamente quantas vezes o
laço deve se repetir, e o bloco de comandos deve ser executado pelo menos uma vez.
Exemplos:
______________________________________________________________________________________________
Curso Técnico em Informática 50 Programação Java
Exercícios:
1) Faça um programa que leia dois números inteiros, o primeiro é o valor inicial de um contador, e
o segundo é o valor final do contador (testar se o valor inicial fornecido é inferior ao valor final).
Usando o comando do-while, escreva na tela uma contagem que comece no primeiro número lido,
escreva os números seguintes colocando sempre apenas um número em cada nova linha da tela,
e terminando a contagem quando chegar ao valor final indicado.
2) Apresentar na tela a tabuada de multiplicação dos números de 1 até 10. O programa deve exibir
o resultado das multiplicações de 1x1, 1x2, ... até 1x10, pedir para o usuário pressionar uma tecla,
e recomeçar com 2x1, 2x2, ... até 2x10, pedir novamente para teclar algo e seguir assim
sucessivamente até chegar em 10x10. Use o comando do-while.
3) Faça um programa para ler 10 valores reais, armazenando estes valores em uma tabela (vetor).
Exibir na tela a média simples dos 10 valores lidos. Faça uma primeira versão deste programa
usando apenas comandos while (faça um laço de leitura de dados e um outro laço para o cálculo
da média). Faça uma segunda versão deste programa usando apenas comandos do-while.
Exemplo de tela de saída:
4.2.3 Comando for
O comando for permite que um certo trecho de programa seja executado um determinado
número de vezes. O laço for pode receber três argumentos, separados por ponto e vírgula e
executa as instruções dentro do bloco {}. Incremente a variável de teste, enquanto a condição for
verdadeira.
______________________________________________________________________________________________
Curso Técnico em Informática 51 Programação Java
Os argumentos são opcionais. Se o teste lógico estiver ausente, e assumido o padrão true,
você pode inicializar mais uma variável, desde que seja do mesmo tipo. O terceiro argumento será
executado ao fim de cada laço e pode ter mais de uma instrução.
O comando for deve ser usado sempre que se souber exatamente quantas vezes o laço
deve ser repetido.
A forma do comando for é a seguinte:
for (comandos de inicialização;condição de teste; incremento/decremento )
{
// comandos a serem repetidos
// comandos a serem repetidos
}
// comandos após o 'for'
Exemplos:
No exemplo a seguir, é testado a condição e após a execução das instruções incrementa x.
No próximo exemplo não apresenta o primeiro e terceiro argumentos, o incremento é feito dentro
do laço for.
Exercícios:
1) Exiba todos os números pares de 10 a 200.
2) Exiba todos os números ímpares existentes entre dois números informados pelo usuário. Dica:
use o operador % para calcular o resto da divisão entre dois números.
3) Escrever um algoritmo que lê 10 valores, um de cada vez, e conta quantos deles estão no inter-
valo [10,20] e quantos deles estão fora do intervalo, escrevendo estas informações.
4.2.4 Comandos de desvio
Os laços em Java, assim como a maioria das linguagens de programação, possuem dois
comandos de desvios: break e continue. Estes comandos funcionam com todos os comandos de
repetição.
O comando break encerra o laço no ponto em que for executado.
______________________________________________________________________________________________
Curso Técnico em Informática 52 Programação Java
Exemplo:
O comando continue desvia o fluxo para o início do laço.
Exemplo:
Obs: Deve-se evitar o comando continue e break, pois seu uso dificulta a legibilidade do código.
O código a seguir cria um laço de repetição entre 0 e 11, através do comando
if(i%2==1)continue, seleciona os valores impares para não serem impressos e finaliza a execução
do comando if(i==12)break.
Exercícios:
1) Crie um programa que se inicia em 1 e deve terminar em mil (1.000), mas dentro desta estrutura
há uma condição: se a variável for igual a 10 ela sai da estrutura de repetição.
2) Uma academia deseja fazer um senso entre seus clientes para descobrir o mais alto, o mais
baixo, o mais gordo e o mais magro, para isto você deve fazer um programa que pergunte a cada
um dos clientes da academia seu código, sua altura e seu peso. O final da digitação de dados deve
ser dado quando o usuário digitar 0 (zero) no campo código. Ao encerrar o programa também de-
vem ser informados os códigos e valores do cliente mais alto, do mais baixo, do mais gordo e do
mais magro, além da média das alturas e dos pesos dos clientes
______________________________________________________________________________________________
Curso Técnico em Informática 53 Programação Java
3) Escreva um programa contendo uma estrutura de repetição que irá contar de 1 a 100, mas
sempre que o número não for múltiplo de 5, o código para apresentar o número na tela será
ignorado e a repetição continuará com o número seguinte, ou seja, apenas os múltiplos de 5 entre
1 e 100 aparecem na tela.
Exercícios:
1) Faça um programa que exiba na tela todos os números entre 50 (inclusive) e 200 (inclusive).
Pode ser utilizado qualquer estrutura de repetição.
2) Faça um programa que exiba na tela todos os números pares existentes entre 1 e 100.
3) Faça um programa que exiba todos os números divisíveis por 5 no intervalo de 1 a 500.
4) Faça um programa que mostre a quantidade de números divisíveis por 3 encontrados no intervalo
de 1 a 1000.
5) Faça um programa que exiba na tela todos os números primos encontrados no intervalo entre 1
e 2000.
6) Faça um programa que solicite ao usuário um número inteiro. Analise este número e informe se
o mesmo par ou ímpar.
7) Faça um programa que solicite ao usuário um número inteiro. Analise este número e informe se
o mesmo primo ou não.
8) Faça um programa que solicite ao usuário um número inteiro. Exiba a raiz quadrada deste
número. Evite utilizar a classe Math ou outra classe ou método especializado nesta operação.
9) Escreva um programa que mostre os números impares e divisíveis por 3 e 5 encontrados no
intervalo de 1 a 1000.
10) Elaborar um programa de solicite ao usuário diversos números inteiros. O usuário irá parar de
informar números inteiros, quando digitar 0 (zero). No final deverá ser exibido a soma dos números
informados.
11) Dado um número inteiro positivo n, imprimir os n primeiros naturais ímpares.
Exemplo: Para n=4 a saída deverá ser 1,3,5,7.
12) Dado o número n de alunos de uma Programação II e suas notas da primeira prova, determinar
a maior e a menor nota obtidas por essa turma (Nota máxima = 100 e nota mínima = 0).
13) Dado um inteiro não-negativo n, informado pelo usuário, determinar n!
14) Dado um inteiro não-negativo n, informado pelo usuário, determinar se este número é primo.
15) Crie um programa que o usuário entre com 2 números, faça a soma entre eles e mostre o
______________________________________________________________________________________________
Curso Técnico em Informática 54 Programação Java
resultado dizendo se o número é par ou ímpar.
16) Um banco concede empréstimo a seus clientes no valor máximo de 30% do valor do seu salário
líquido. Receba o valor do salário bruto, o valor dos descontos e o valor do possível empréstimo de
um cliente, em seguida avise se ele poderá ou não fazer o empréstimo.
17) Crie um programa de contagem crescente, onde não importe a ordem que os valores sejam
digitados. Ex: digitou 1 e 5: o sistema conta de 1 até 5; digitou 5 e 1: o sistema conta de 1 até 5;
18) Faça um programa que some dois valores digitados pelo usuário e, enquanto ele desejar
continuar realizando operações, o sistema vai repetindo. Ex: pressione (1) para continuar ou
qualquer tecla para sair;
19) Faça um programa que exiba os números ímpares de um intervalo citado pelo usuário;
20) Crie um programa que exiba na tela os números múltiplos de 3 entre 0 e 20; use o resto da
divisão por 3;
4.3 Recursividade
A recursividade trabalha de forma similar a um laço de repetição, na verdade tudo que
fazemos em laço, pode ser feito em recursividade. A recursividade é nada mais nada menos do que
uma função dentro da outra e ela deve ser pensada como uma pilha (estrutura de dados onde o
último a entrar, deve ser o primeiro a sair). A estrutura dela consiste em descer até a base fazendo
os cálculos ou rotinas de cada instrução, e então da base até o topo da pilha são empilhados os
resultados de cada instrução e no final o topo contém o resultado que é retornado. Na figura a
seguir, temos um exemplo que é frequentemente usado para explicar a recursividade, podemos
encontrar em diversos livros didáticos, porque é um dos mais fáceis para se entender, estou falando
do fatorial.
Exemplo: Desenvolver um método recursivo para descobrir o fatorial de um número “N”. Supondo
que o N seja igual a 4.
Obs: O “fatorial(4)” só pode ser descoberto depois que o “fatorial(3)” for descoberto, que por sua
vez só poderá ser descoberto depois do fatorial(2) e assim por diante. Por isso vai do topo até a
base, e depois vai empilhando os resultados da base até o topo.
______________________________________________________________________________________________
Curso Técnico em Informática 55 Programação Java
Agora uma ilustração com os valores para fixar o conceito:
O conceito de recursividade como podemos ver anteriormente não é tão difícil, é claro que
na hora da programação é sempre recomendável atenção, organização e fazer o tão “chato”, mas
eficiente teste de mesa, ou seja, fazer o máximo para dar certo, pois a hora de errar é quando
estiver treinando, fazendo exercícios e não deixar para errar quando estiver em um mercado de
trabalho, onde um projeto pode ter mais de 10000 linhas.
A seguir a apresentado a implementação de uma classe Java com o exemplo de
recursividade:
Essa é a função recursiva do fatorial em JAVA. Agora falta implementar um método principal para
testar esta função, para facilitar esse método será criado dentro da classe que já foi criada. Como
a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 56 Programação Java
Estruturas de dados como o próprio nome sugere, é um modo particular de armazenamento
e organização de dados em um computador de modo que estes possam ser usados de forma
eficiente. Sendo um pouco mais abstrato, imagine como seria o mundo real se não existisse o
conceito de “Fila”, tudo seria um caos sem nenhuma ordem ou organização e o mesmo aplica-se
ao mundo digital.
O objetivo não é entrar em detalhes sobre explicações teóricas, mas sim práticas, algumas
estruturas exigem um pouco mais de foco do que outras para serem entendidas, devido ao seu
grau de complexidade. Sendo assim, nem todas as estruturas de dados serão tratadas neste
momento.
5.1 Vetores
Vetores ou arrays são estruturas de dados que armazenam usualmente uma quantidade fixa
de dados de um certo tipo; por esta razão, também são conhecidos como estruturas homogêneas
de dados.
Internamente, um vetor/array armazena diversos valores, cada um associado a um número
que se refere à posição de armazenamento, e é conhecido como índice. Os vetores são estruturas
indexadas, em que cada valor que pode ser armazenado em uma certa posição (índice) é chamado
de elemento do vetor.
Cada elemento do vetor/array pode ser utilizado individualmente de forma direta, ou seja,
pode ser lido ou escrito diretamente, sem nenhuma regra ou ordem preestabelecida, fazendo dos
vetores estruturas de dados de acesso aleatório. O número de posições de um vetor/array
corresponde ao tamanho que ele tem assim, um vetor de tamanho 10 tem esse número de
elementos, isto é, pode armazenar até dez elementos distintos. Os diferentes elementos de um
vetor são distinguidos unicamente pela posição que ocupam no vetor. Cada posição de um vetor é
unicamente identificada por um valor inteiro positivo, linear e sequencialmente numerado.
a[i], corresponde ao i-ésimo elemento do vetor a, sendo que o valor da variável i deve
pertencer ao intervalo dos índices do vetor: ((i >= 0) && (i < a.length)).
O Java como as linguagens C e C++ são linguagens com vetores zero-based, isto é, as
posições do vetor iniciam a numeração a partir do valor 0, portanto, um vetor de tamanho 10 teria
índices iniciados em 0 prosseguindo até o 9.
Na declaração de vetores deverão ser fornecidas três informações:
1) O nome do vetor,
2) O número de posições do vetor (seu tamanho), e
3) O tipo de dado que será armazenado no vetor.
Declaração de um vetor para "inteiros", de nome "vetor", em Java:
int vetor[]; // declaração do vetor
Podemos notar que as declarações de vetores são semelhantes às declarações de variáveis,
os elementos sintáticos que diferenciam as variáveis do tipo vetor das outras variáveis são
Estrutura de dados 5
______________________________________________________________________________________________
Curso Técnico em Informática 57 Programação Java
os colchetes. Embora declarado, o vetor não está pronto para uso, sendo necessário reservar
espaço para seus elementos (uma operação de alocação de memória).
vetor = new int[10]; // alocação de espaço para vetor
Na alocação de espaço, não repetimos os colchetes e utilizamos o operador new (uma palavra
reservada da linguagem) para reservar espaço para 10 (dez) elementos do tipo int.
As duas declarações podem ser combinadas em uma única, mais compacta:
a) declarando um vetor para armazenar 10 números inteiros
int nro = new int[10];
b) declarando um vetor para armazenar 10 valores do tipo real (ou monetários)
double salario = new double[10];
c) declarando um vetor para armazenar as letras do alfabeto
char alfabeto = new char[26];
Obs: Um vetor/array de caracteres é o mesmo que um dado do tipo String.
d) declarando um vetor para armazenar o nome dos 12 meses do ano
String mes = new String[12];
Exemplo:
Representação interna:
V[0] V[1] V[2] V[3] V[4] V[5] V[6] V[7] V[8] V[9]
0 1 2 3 4 5 6 7 8 9
______________________________________________________________________________________________
Curso Técnico em Informática 58 Programação Java
Aplicação Java exemplificando a utilização do tipo de dados vetor:
______________________________________________________________________________________________
Curso Técnico em Informática 59 Programação Java
Resultado da execução do programa:
A classe Math contém diversos métodos estáticos (não exige uma instância da classe para
utilização) destinados a operações numéricas, citando:
static double random(): retorna um valor, do tipo double, "aleatório" no intervalo de 0.0
até 1.0;
static long round(double): retorna um número do tipo long mais próximo (ou
arredondado) do valor do tipo double do argumento.
A utilização combinada dos métodos "random" e "round" possibilita a geração de números
aleatórios, como por exemplo:
a[i] = (int)Math.round(Math.random() * 10); // gera um número inteiro aleatório no intervalo
de 0 até 10
Entendendo a atribuição:
Math.random() retorna um número aleatório, do tipo double, no intervalo de 0.0 até 1.0;
Math.random() * 10 tem como resultado um número no intervalo de 0.0 até 10.0;
Math.round(Math.random() * 10) retorna um número do tipo long mais próximo (ou
arredondado) do resultado;
(int) faz a conversão (ou coerção, em inglês "cast") do tipo long para o tipo int.
______________________________________________________________________________________________
Curso Técnico em Informática 60 Programação Java
A aplicação Java a seguir implementa o método de ordenação por seleção ou Selection Sort:
O resultado da execução deste programa será:
______________________________________________________________________________________________
Curso Técnico em Informática 61 Programação Java
5.1.1 Inicialização de vetores
Java permite a inicialização de vetores no momento da declaração, por exemplo:
String nome[] = {"Juca Bala", "Maria das Dores", "Pedro Bó"};
Isso significa que nome[0] terá o valor Juca Bala, nome[1] terá o valor Maria das Dores, nome[2]
terá o valor Pedro Bó. Nota-se que não é necessário indicar o tamanho do vetor e também fazer a
alocação de espaço através do operador new. O tamanho do vetor será conhecido através do
campo como mostra a aplicação a seguir:
O resultado da execução deste programa será:
A inicialização de vetores na declaração também permite indexar valores predefinidos como no
caso das informações relacionadas aos meses do ano. Conforme o exemplo a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 62 Programação Java
O resultado da execução deste programa será:
5.1.2 Estrutura for aprimorada
Utilizada para percorrer os elementos de um vetor sem utilizar um contador:
for (parâmetro: nomeDoVetor) {
instrução;
}
Onde "parâmetro" tem duas partes:
a) um tipo (deve corresponder ao tipo dos elementos no vetor), e
b) um identificador, por exemplo: int nro.
O identificador representa os valores sucessivos do vetor nas sucessivas iterações da
instrução for. Veja um exemplo na próxima aplicação Java:
O resultado da execução do programa é a seguinte:
Exercícios:
Nesta lista de exercícios em alguns casos é solicitado um número aleatório. Para gerar este número
utilize a função rand(). Por exemplo para gerar um número aleatório entre 0 e 9, deve ser construído
______________________________________________________________________________________________
Curso Técnico em Informática 63 Programação Java
o seguinte comando: rand() % 100
1) Criar um vetor A com 5 elementos inteiros, gerados de forma aleatória. Construir um vetor B de
mesmo tipo e tamanho e com os "mesmos" elementos do vetor A, ou seja, B[i] = A[i]. Exibir os dois
vetores na tela.
2) Criar um vetor A com 10 elementos inteiros, gerados de forma aleatória. Construir um vetor B de
mesmo tipo e tamanho, sendo que cada elemento do vetor B deverá ser o quadrado do respectivo
elemento de A, ou seja:
B[i] = A[i] * A[I]. Exibir os dois vetores na tela.
3) Criar um vetor A com 10 elementos inteiros, gerados de forma aleatória. Construir um vetor B de
mesmo tamanho, sendo que cada elemento do vetor B deverá ser a raiz quadrada do respectivo
elemento de A, ou seja: B[i] = sqrt(A[i]). Exibir os dois vetores na tela.
4) Criar um vetor A com 10 elementos inteiros, gerados de forma aleatória. Construir um vetor B de
mesmo tipo e tamanho, sendo que cada elemento do vetor B deverá ser o respectivo elemento de
A multiplicado por sua posição (ou índice), ou seja: B[i] = A[i] * i. Exibir os dois vetores na tela.
5) Criar dois vetores A e B cada um com 10 elementos inteiros, gerados de forma aleatória.
Construir um vetor C, onde cada elemento de C é a soma dos respectivos elementos em A e B, ou
seja: C[i] = A[i] + B[i]. Exibir os dois vetores na tela.
6) Criar um vetor A com 10 elementos inteiros, gerados de forma aleatória. Construir um vetor B de
mesmo tipo e tamanho, sendo que cada elemento do vetor B deverá ser o resto da divisão do
respectivo elemento de A por 2 (dois), ou seja: B[i] := A[i] % 2. Exiba os dois vetores na tela.
7) Faça um programa que leia 5 nomes e notas de uma turma, Calcular e exibir a média a média
das notas da turma e em seguida exibe a relação de nomes cuja nota é superior a esta média.
8) Faça um programa que leia um conjunto de notas, cuja quantidade seja determinada pelo
usuário. Calcule a média de todas elas. Exiba o conjunto das notas maiores do que a média
calculada. Em seguida, de forma agrupada, exiba o outro conjunto de notas (menores do que a
média).
9) Faça um programa que leia um conjunto de salários, sendo que o usuário determinará a
quantidade de salários informados. Após toda a entrada ter sido realizada, leia o valor de um
reajuste. Em seguida exiba todos os salários já reajustados.
10) Faça um programa de consulta de telefones a partir de um nome informado. Primeiro leia nomes
de pessoas com seus respectivos telefones, sendo a quantidade determinada pelo usuário. Em
seguida pergunte ao usuário qual o nome que ele deseja consultar o telefone. Após sua resposta,
exiba o telefone da pessoa procurada. Informe também se o nome é inexistente no banco de dados.
11) Solicite ao usuário que informe uma frase. Posteriormente descubra quantos caracteres existem
na frase e quantos destes são vogais. Exiba a frase digitada substituindo as vogais por '#', e
______________________________________________________________________________________________
Curso Técnico em Informática 64 Programação Java
apresente a quantidade de caracteres e o número de vogais encontradas.
12) Solicite ao usuário que informe uma sequência de caracteres qualquer. Posteriormente
descubra quantos caracteres existem na sequência e quantos destes são vogais. Em seguida
construa um array contendo somente as vogais. Exiba a sequência de caracteres digitados ao
contrário, e em seguida a lista de vogais.
5.2 Matrizes
A linguagem Java não fornece vetores multidimensionais, mas como um vetor pode ser
declarado e ter qualquer tipo de base, é possível criar vetores de vetores (de vetores etc.),
alcançando assim o mesmo efeito.
Nos exemplos anteriores, foram declarados apenas um bloco de variáveis. Diz-se que esse
vetor é unidimensional, pois é somente um bloco.
Para se ter uma noção de dimensão, deve se observar o array/vetor apenas como uma linha.
Por exemplo, declara-se um array unidimensional com 5 notas de Matemática:
int[] notas = {8.0 , 7.5, 8.5 , 9.0 , 8.0}; Essa nota pode ser representada por uma matriz 1x5, ou seja, uma linha e 5 colunas:
8.0 7.5 8.5 9.0 8.0
A seguir é demonstrado as notas em Física, abaixo das de Matemática. Tem-se uma matriz 2x5, ou
seja, uma matriz de duas linhas e 5 colunas:
8.0 7.5 8.5 9.0 8.0
8.9 9.0 8.6 8.4 8.0
Agora é representado as notas de Química, a seguir as notas de Física.
Tem-se uma matriz 3x5, ou seja, uma matriz de três linhas e 5 colunas:
8.0 7.5 8.5 9.0 8.0
8.9 9.0 8.6 8.4 8.0
6.8 7.1 7.0 7.6 6.5
A sintaxe é exatamente a mesma do array normal, a diferença está no número de colchetes '[]' que
se usa.
No caso, usa-se um par para cada dimensão.
Por exemplo, para declarar a matriz 2x5 do exemplo anterior:
float[][] notas = new float[2][5];
ou
float[][] notas = { {8.0, 7.5, 8.5, 9.0, 8.0 }, {8.9, 9.0, 8.6, 8.4, 8.0 } };
______________________________________________________________________________________________
Curso Técnico em Informática 65 Programação Java
Para declarar a matriz 3x5 do exemplo anterior:
float[][] notas = new float[3][5];
ou
float[][] notas = { {8.0, 7.5, 8.5, 9.0, 8.0}, {8.9, 9.0, 8.6, 8.4, 8.0}, {6.8, 7.1, 7.0, 7.6, 6.5 } };
Note que notas[0] se refere ao array de notas de Matemática.
Note que notas[1] se refere ao array de notas de Física.
Note que notas[2] se refere ao array de notas de Química.
Por exemplo: qual foi a quarta nota de Física do aluno?
Ora, o vetor de Física é notas[1], e a quarta nota é o elemento [3] desse array.
Então a quarta nota de Física do aluno está armazenada em: nota[1][3], que é 8.4
Exemplos:
1) Criar um aplicativo em Java que peça ao usuário para preencher uma matriz 3x3 com valores
inteiros e depois exiba essa matriz.
Obs: A grande novidade, nesse tipo de estrutura são os laços for aninhados, ou seja, um dentro
do outro.
Primeiro cria-se um laço que vai percorrer todas as linhas da matriz. Cada linha deve ser vista como
um vetor de 3 elementos. Dentro de cada linha, é necessário percorrer cada elemento do vetor/array
e fornecer seu valor. Isso é feito através de outro laço for, que ficará responsável pelas 'colunas',
formando os laços aninhados.
Para imprimir, o esquema é exatamente o mesmo. Imprime-se linha por linha, e em cada linha,
imprime-se coluna por coluna.
______________________________________________________________________________________________
Curso Técnico em Informática 66 Programação Java
2) Crie um aplicativo em Java que peça ao usuário para preencher uma matriz 3x2 com valores
inteiros e depois exiba essa matriz.
No exemplo anterior, o número de linhas era igual ao número de colunas, da matriz. Agora será
visto um exemplo diferente, para fixar o conhecimento em arrays multidimensionais.
Como dito no começo, uma matriz, vetor/array multidimensional ou vetor multidimensional nada
mais é que um conjunto de arrays ou conjunto de vetores, array de arrays.
Quando é feito: int[5] para declarar um array de inteiros, está se declarando 5 variáveis do tipo
inteiro.
Quando é feito: int[10][5], está se declarando 10 arrays, e em cada array desses existem 5 inteiros,
ou seja, 10 arrays do tipo do exemplo anterior. Logo, o tamanho desse array – length – é 10. Esta
informação pode ser obtida com o comando: array.length
Assim, uma matriz 3x2 tem tamanho 3.
Uma 4x3 tem tamanho 4, uma 10x123123 tem tamanho 10 etc.
Ou seja, o length de arrays multidimensionais é o número de linhas.
Fazendo uso desse fato nos laços:
Exercícios:
1) Escreva um programa que declara e constrói uma matriz 3x3, de inteiros. Use um laço for para
preencher os elementos da matriz usando valores aleatórios de 0 até 9 (incluindo os valores 0 e
10). Para finalizar, percorra os elementos da matriz e exiba seus valores. A saída do programa
______________________________________________________________________________________________
Curso Técnico em Informática 67 Programação Java
deverá ser parecida com:
3 5 5
5 3 8
1 0 9
2) Escreva um programa que gera uma matriz 4x4, de números inteiros. Posteriormente percorrer
todos os elementos desta matriz duas vezes e exibi-los na ordem original e invertidos (somente na
exibição, ou seja, não é necessário alterar a ordem dos elementos na matriz).
3) Escreva um programa que gere uma matriz 4x3, de números inteiros. Posteriormente percorra
todos os elementos desta matriz a fim exibir a soma de seus valores. O programa deverá exibir
uma saída com a mensagem:
A soma dos valores da matriz é: valor resultante da soma
4) Escreva um programa que declara e constrói uma matriz 5x5, de inteiros, gerados
aleatoriamente. Posteriormente inverta a ordem dos elementos da matriz, usando apenas uma
variável temporária, ou seja, não é permitido usar nenhum método disponível. Sua saída deverá
ser algo como:
Original
1 3 5 6 7
7 3 9 2 4
9 5 1 3 0
2 1 9 5 8
5 8 1 3 0
Invertido
7 6 5 3 1
4 2 9 3 7
0 3 1 5 9
8 5 9 1 2
0 3 1 8 5
5) Escreva um programa que declara e constrói uma matriz 10x10, de inteiros, gerados
aleatoriamente, no intervalo de 0 a 100. Posteriormente selecione todos os números primos desta
matriz e armazene-os em um vetor. Exiba a matriz gerada e o vetor contendo os números primos.
6) Escreva um programa que declara e constrói uma matriz 5x5, de inteiros, gerados
aleatoriamente, no intervalo de 0 a 10. Posteriormente obtenha a soma da diagonal da matriz.
Exiba a matriz gerada e o valor resultante da soma da diagonal.
Ex:
2 3 4 5 6
9 7 5 3 1
1 3 5 7 9
______________________________________________________________________________________________
Curso Técnico em Informática 68 Programação Java
8 6 4 2 3
7 0 5 2 9
Soma da diagonal: 25
7) Escreva um programa que declara e constrói uma matriz 7x7, de inteiros, gerados
aleatoriamente, no intervalo de 0 a 9. Posteriormente obtenha a soma da diagonal inversa da matriz.
Exiba a matriz gerada e o valor resultante da soma da diagonal inversa.
Ex:
2 3 4 5 6 1 9
9 7 5 3 1 2 4
1 3 5 7 9 2 8
8 6 4 2 3 1 7
7 0 5 2 9 8 1
5 6 4 2 3 1 7
3 4 5 2 9 8 1
Soma da diagonal inversa: 36
8) Escreva um programa que declara e constrói uma matriz 5x5, de inteiros pares, gerados
aleatoriamente, no intervalo de 10 a 99. Exiba a matriz gerada.
9) Escreva um programa que declara e constrói uma matriz 4x4, de inteiros primos, gerados
aleatoriamente, no intervalo de 10 a 99. Exiba a matriz gerada.
10) Escreva um programa que declara e constrói uma matriz 6x6, de inteiros impares e divisíveis
por 3 e 7, gerados aleatoriamente, no intervalo de 100 a 999. Exiba a matriz gerada, o menor e
maior elemento sorteado.
6.1 Introdução
O termo Programação Orientada a Objetos foi criado por Alan Kay, autor da linguagem de
programação Smalltalk. Mas mesmo antes da criação do Smalltalk, algumas das ideias da POO já
eram aplicadas, sendo que a primeira linguagem a realmente utilizar estas ideias foi a linguagem
Simula 67, criada por Ole Johan Dahl e Kristen Nygaard em 1967. Note que este paradigma de
programação já é bastante antigo, mas só agora vem sendo aceito realmente nas grandes
empresas de desenvolvimento de Software. Alguns exemplos de linguagens modernas utilizadas
por grandes empresas em todo o mundo que adotaram essas ideias: Java, C#, C++, Object Pascal
(Delphi), Ruby, Python, Lisp, ...
A maioria delas adota as ideias parcialmente, dando espaço para o antigo modelo procedural
de programação, como acontece no C++ por exemplo, onde temos a possibilidade de usar POO,
mas a linguagem não força o programador a adotar este paradigma de programação, sendo ainda
Programação Orientada a Objetos 6
______________________________________________________________________________________________
Curso Técnico em Informática 69 Programação Java
possível programar da forma procedural tradicional. Este tipo de linguagem segue a ideia de utilizar
uma linguagem previamente existente como base e adicionar novas funcionalidades a ela.
Outras são mais "puras", sendo construídas do zero focando-se sempre nas ideias por trás
da orientação a objetos como é o caso das linguagens Smalltalk, Self e IO, onde TUDO é orientado
a objetos.
6.2 Ideias básicas da POO
A POO foi criada para tentar aproximar o mundo real do mundo virtual: a ideia fundamental
é tentar simular o mundo real dentro do computador. Para isso, nada mais natural do que utilizar
Objetos, afinal, nosso mundo é composto de objetos.
Na POO o programador é responsável por moldar o mundo dos objetos, e explicar para estes
objetos como eles devem interagir entre si. Os objetos "conversam" uns com os outros através do
envio de mensagens, e o papel principal do programador é especificar quais serão as mensagens
que cada objeto pode receber, e também qual a ação que aquele objeto deve realizar ao receber
aquela mensagem em específico.
Uma mensagem é um pequeno texto que os objetos conseguem entender e, por questões
técnicas, não pode conter espaços. Junto com algumas dessas mensagens ainda é possível passar
algumas informações para o objeto (parâmetros), dessa forma, dois objetos conseguem trocar
informações entre si facilmente.
A seguir é apresentado um exemplo prático para melhor elucidar este conceito. Um
programador está desenvolvendo um software para uma locadora e essa locadora tem diversos
clientes. Como tenta-se modelar um sistema baseado no sistema real, nada mais obvio do que
existirem objetos do tipo Clientes dentro do nosso programa, e esses Clientes dentro do nosso
programa nada mais serão do que objetos que "simulam" as características e ações no mundo
virtual que um cliente pode realizar no mundo real.
Mais a diante será apresentado um exemplo mais detalhada, mas antes é necessário
especificar mais alguns conceitos.
6.3 Classes
Uma classe é uma abstração que define um tipo de objeto e o que objetos deste determinado
tipo tem dentro deles (seus atributos) e também define que tipo de ações esse tipo de objeto é
capaz de realizar (métodos).
É importante salientar que uma classe não representa nenhum objeto em particular, é
apenas um modelo.
A seguir é como criar uma classe Java, representando a entidade conta corrente. Uma
classe deve definir entre abre e fecha chaves ({ e }) somente atributos, métodos e códigos de
inicialização.
Exemplo: package poo; /*Declaração da classe ContaCorrente
* O nome da classe deve ser igual ao dome do arquivo que a contém. * O nome de uma classe deve iniciar com letra maiúcula*/ public class ContaCorrente { /*Declarando os atributos*/ int conta; int agencia; double saldo;
______________________________________________________________________________________________
Curso Técnico em Informática 70 Programação Java
String titular; /*Métodos de acesso e modificadores =>
* (Não é nescessário explicar por enquanto.)*/ public int getConta() { return conta; } public void setConta(int conta) { this.conta = conta; } public int getAgencia() { return agencia; } public void setAgencia(int agencia) { this.agencia = agencia; } public double getSaldo() { return saldo; } public void setSaldo(double saldo) { this.saldo = saldo; } public String getTitular() { return titular; } public void setTitular(String nome) { this.titular = nome; } }//Nenhuma linha de código de ser definida depois deste simbolo de fecha chaves.
A classe acima representa uma conta corrente com seus atributos métodos de acesso
(getXxx()) e métodos modificadores (setXxx()). Os métodos de acesso e modificadores devem ser
usados pelo programador, para acessar ou alterar os atributos, sem fazê-lo de forma direta. Apesar
de ser possível realizar o acesso de forma direta, as boas práticas e o conceito de encapsulamento
(a ser estudado mais tarde), um atributo deve sempre ser acessado por método de acesso ou
modificador.
A classe ContaCorrente representa a entidade conta corrente, assim com uma tabela no
banco de dados, onde definimos suas colunas (atributos) para receberem seus registros.
Em um método modificador podemos definir regras de validação para os atributos, evitando
que um valor inválido seja atribuído a um atributo. Por exemplo: uma agencia não pode ser
inicializada com um parâmetro com valor menor ou igual a 0 (zero).
6.4 Objetos
Objetos são representações das classes. Para criar um objeto deve ser utilizado o operador
new, conforme a representação a seguir:
Classe nomeDoObjeto = new Classe();
A seguir um exemplo de objetos sendo criados.
______________________________________________________________________________________________
Curso Técnico em Informática 71 Programação Java
Exemplo:
package poo;
public class Principal {
public static void main(String args[]){
ContaCorrente conta1 = new ContaCorrente(); //Crando o objeto conta1
ContaCorrente conta2 = new ContaCorrente(); //Crando o objeto conta2
}
}
Este programa representa apenas como criar um objeto. Se for executado não será exibido
nenhum resultado na tela, já que que o objetivo aqui é apenas apresentar a sintaxe usada para a
criação de objetos.
6.5 Mensagens
Para se fazer uso de um objeto recém-criado, é necessário o envio de mensagens, que é a
forma de comunicação entre objetos. Para tanto é necessário criar um objeto, identificar o método
a ser executado, e se for o caso, identificar os parâmetros que o método recebe ou retorna. Para
enviar uma mensagem a um objeto utiliza-se o seguinte comando.
conta1.setConta(456789);
Neste exemplo está sendo enviado uma mensagem informando ao objeto conta1, o número da
conta.
No exemplo a seguir está sendo informado o valor de todos os atributos do objeto conta1.
package poo;
public class Principal {
public static void main(String args[]){
ContaCorrente conta1 = new ContaCorrente(); //Crando o objeto conta1
conta1.setConta(2156570);
conta1.setAgencia(1579);
conta1.setSaldo(1243.56);
conta1.setTitular("João Aluno");
}
}
6.6 Métodos
Toda classe Java contém pelo menos um método chamado de método construtor (método
com o mesmo nome da classe). O método construtor se não for explicitamente criado pelo
programador, será criado pelo compilador sempre que não tiver sido criado. O método construtor
será visto com maiores detalhes mais adiante.
______________________________________________________________________________________________
Curso Técnico em Informática 72 Programação Java
É importante observar que dentro dos métodos pode-se criar variáveis, mas estas têm
validade (escopo) somente dentro do método que as criou.
Uma classe para ser executável deve conter um método chamado main(), é a partir deste
método que um programa começa a ser executado. Diz-se que uma classe que contém o método
main(), é uma classe principal.
A seguir é mostrado um exemplo onde o usuário informa os dados de 5 contas corrente
diferentes, armazenando-as em um vetor. Para posteriormente recuperá-las e exibi-las na tela.
package poo;
import java.util.Scanner;
public class Principal {
public static void main(String args[]){
ContaCorrente conta = new ContaCorrente(); //Criando o objeto conta
ContaCorrente contas[] = new ContaCorrente[5];//Cria um vetor de contas
correntes com 5 posições
Scanner lerTeclado = new Scanner(System.in);//Cria objeto da classe Scanner
para realizar leitura do teclado.
for(int i=0; i<5; i++){
System.out.println("\n ------------------------------ \n ");
System.out.println("Informe o número da conta : ");
conta.setConta(lerTeclado.nextInt());
System.out.println("Informe o número da agencia : ");
conta.setAgencia(lerTeclado.nextInt());
System.out.println("Informe o saldo da conta : ");
conta.setSaldo(lerTeclado.nextDouble());
lerTeclado.nextLine();//Limpa buffer do teclado
System.out.println("Informe o nome do titular : ");
conta.setTitular(lerTeclado.nextLine());
contas[i]=conta;
}
//Recuperar os dados no vetor
for(int i=0; i<5; i++){
conta=contas[i];
System.out.println("\n ------------------------------ \n ");
System.out.println("Número da conta : "+conta.getConta());
System.out.println("Agência : "+conta.getSaldo());
System.out.println("Saldo : "+conta.getSaldo());
System.out.println("Titular : "+conta.getTitular());
}
}
}
______________________________________________________________________________________________
Curso Técnico em Informática 73 Programação Java
Exercícios:
1) Escreva uma classe que represente um automóvel. Um automóvel tem como atributos o seu
modelo, fabricante, cor, placa e potência (cilindradas). Forneça os métodos de acesso para os
atributos da classe. Posteriormente escreva uma classe principal que faça uso da classe
'Automóvel'. Nesta classe o usuário deverá informar os dados de até 10 automóveis diferentes.
Utilize um vetor para armazenar os automóveis que estão sendo informados.
No final da execução do programa exiba na tela a lista dos automóveis informados.
2) Escreva uma classe que represente um paciente. Um paciente tem como atributos o seu nome,
idade, telefone e convenio. Forneça os métodos de acesso para os atributos da classe.
Posteriormente escreva uma classe principal que faça uso da classe 'Paciente'. Nesta classe o
usuário deverá informar os dados de até 10 pacientes diferentes.
Utilize um vetor para armazenar os pacientes que estão sendo informados.
No final da execução do programa exiba na tela a lista dos pacientes informados.
Para se obter um melhor entendimento sobre o paradigma da programação orientada a objetos, é
fundamental conhecer alguns conceitos que formam os pilares da programação orientada a objetos.
Estes conceitos são: Abstração, encapsulamento, Herança e Polimorfismo.
6.7 Abstração
A abstração aplicada para a definição de entidades do mundo real. Sendo onde são criadas
as classes. Essas entidades são consideradas tudo que é real, tendo como consideração as suas
características e ações.
Como visto anteriormente, uma classe é reconhecida quando tem a palavra reservada
“class”. No exemplo referente a conta corrente, é apresentado a classe “ContaCorrente” com seus
atributos (características) e métodos (ações).
6.8 Encapsulamento
O encapsulamento visa não expor detalhes internos de uma classe, para o usuário, tornando
partes do sistema mais independentes possível. Por exemplo, quando um controle remoto estraga
apenas é trocado ou consertado o controle e não a televisão inteira. Nesse exemplo do controle
remoto, acontece a forma clássica de encapsulamento, pois quando o usuário muda de canal não
se sabe que programação acontece entre a televisão e o controle para efetuar tal ação.
Como um exemplo mais técnico podemos descrever o que acontece em um sistema de
vendas, aonde temos cadastros de funcionários, usuários, gerentes, clientes, produtos entre outros.
Se por acaso acontecer um problema na parte do usuário é somente nesse setor que será realizada
a manutenção não afetando os demais.
Um componente importante neste processo são os modificadores de acesso. Como boas
práticas (best practices) do Java, na maioria das declarações de variáveis de instância são definidos
os seus atributos com a palavra-chave private, para garantir a segurança de alterações acidentais,
sendo somente acessíveis através dos métodos. Essa ação tem como efeito ajudar no
encapsulamento dos dados, preservando ainda mais a segurança e a aplicação de programação
orientada a objetos do Java. Existem três modificadores de acesso: private, protect e public.
Em um processo de encapsulamento os atributos das classes são do tipo private. Para
acessar esses atributos é necessário criar métodos de acesso e modificadores. Estes métodos são
chamados de métodos setters e getters.
______________________________________________________________________________________________
Curso Técnico em Informática 74 Programação Java
Como regra os métodos setters servem para alterar a informação de uma propriedade de
um objeto. E os métodos getters para retornar o valor dessa propriedade.
No exemplo utilizando a classe ContaCorrente, os atributos são declarados como privados (private),
e então gerado os métodos geters e seters.
package poo;
/*Declaração da classe ContaCorrente
* O nome da classe deve ser igual ao dome do arquivo que a contém.
* O nome de uma classe deve iniciar com letra maiúcula*/
public class ContaCorrente {
/*Declarando os atributos*/
private int conta;
private int agencia;
private double saldo;
private String titular;
/*Métodos de acesso e modificadores */
public int getConta() {
return conta;
}
public void setConta(int conta) {
this.conta = conta;
}
public int getAgencia() {
return agencia;
}
public void setAgencia(int agencia) {
this.agencia = agencia;
}
public double getSaldo() {
return saldo;
}
public void setSaldo(double saldo) {
this.saldo = saldo;
}
public String getTitular() {
return titular;
}
public void setTitular(String nome) {
this.titular = nome;
}
}//Nenhuma linha de código de ser definida depois deste simbolo de fecha chaves.
No exemplo a seguir, é instanciado a classe “ContataCorrente”, onde o objeto de referência
“conta”, é usado para invocar os métodos setters, informando algum dado. Ao final, é usado os
______________________________________________________________________________________________
Curso Técnico em Informática 75 Programação Java
métodos getters dentro de um “System.out.println” para gerar a saída dos resultados que foram
passados nos métodos setters.
package poo;
public class Conta {
public static void main(String[] args) {
ContaCorrente conta = new ContaCorrente();
/*Atribuindo valores através dos métodos seters*/
conta.setAgencia(867676);
conta.setConta(5454);
conta.setSaldo(568.9);
conta.setTitular("Pedro Boh");
/*Resgatando os valores através dos métodos geters*/
System.out.println("Agencia :"+conta.getAgencia());
System.out.println("Conta : "+conta.getConta());
System.out.println("Saldo : "+conta.getSaldo());
System.out.println("Titular : "+conta.getTitular());
}
}
Exercícios:
1) Escreva uma classe, aplicando os conceitos de encapsulamento, que represente um aluno. Um
aluno tem como atributos o seu nome, matricula e turma. Forneça os métodos de acesso para os
atributos da classe.
Posteriormente escreva uma classe principal que faça uso da classe 'Aluno'. Nesta classe o usuário
deverá informar os dados de até 15 alunos diferentes.
Utilize um vetor para armazenar os alunos que estão sendo informados.
No final da execução do programa exiba na tela a lista dos alunos informados.
2) Escreva uma classe, aplicando os conceitos de encapsulamento, que represente uma turma.
Uma turma tem como atributos o seu nome, curso e turno. Forneça os métodos de acesso para os
atributos da classe.
Posteriormente escreva uma classe principal que faça uso da classe 'Turma'. Nesta classe o
usuário deverá informar os dados de até 10 turmas diferentes.
Utilize um vetor para armazenar as turmas que estão sendo informadas.
No final da execução do programa exiba na tela a lista das turmas informadas.
3) Escreva uma classe, aplicando os conceitos de encapsulamento, que represente um professor.
Um professor tem como atributos o seu nome, especialidade e curso. Forneça os métodos de
acesso para os atributos da classe.
Posteriormente escreva uma classe principal que faça uso da classe 'Professor'. Nesta classe o
usuário deverá informar os dados de até 15 professores diferentes.
Utilize um vetor para armazenar os professores que estão sendo informados.
______________________________________________________________________________________________
Curso Técnico em Informática 76 Programação Java
No final da execução do programa exiba na tela a lista dos professores informadas.
6.9 Herança
Na Programação Orientada a Objetos o significado de herança tem o mesmo significado
para o mundo real. Assim como um filho pode herdar alguma característica do pai, na Orientação
a Objetos é permitido que uma classe herde atributos e métodos da outra, tendo apenas uma
restrição para a herança. Os modificadores de acessos das classes, métodos e atributos só podem
estar com visibilidade public e protected para que sejam herdados.
Uma das grandes vantagens de usar o recurso da herança é na reutilização do código. Esse
reaproveitamento pode ser acionado quando se identifica que o atributo ou método de uma classe
será igual para as outras. Para efetuar uma herança de uma classe é utilizada a palavra reservada
chamada extends.
Classe pai (superclasse)
package poo.heranca;
import java.util.Date;
public class Funcionario {
protect int id;
protect String nome;
protect String dataContrato;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
______________________________________________________________________________________________
Curso Técnico em Informática 77 Programação Java
this.nome = nome;
}
public String getDataContrato() {
return dataContrato;
}
public void setDataContrato(String dataContrato) {
this.dataContrato = dataContrato;
}
}
Classes filhas (subclasses) Motorista
package poo.heranca;
public class Motorista extends Funcionario{
protect int cnh;
public int getCnh() {
return cnh;
}
public void setCnh(int cnh) {
this.cnh = cnh;
}
}
Engenheiro
package poo.heranca;
public class Engenheiro extends Funcionario{
protect String crea;
public String getCrea() {
return crea;
}
public void setCrea(String crea) {
this.crea = crea;
}
}
Secretária
package poo.heranca;
______________________________________________________________________________________________
Curso Técnico em Informática 78 Programação Java
public class Secretaria extends Funcionario{
protect String formacao;
public String getFormacao() {
return formacao;
}
public void setFormacao(String formacao) {
this.formacao = formacao;
}
}
Classe Principal faz uso das classes filhas.
package poo.heranca;
import java.util.Date;
public class Principal {
/*Criação de atributos estáticos para que não haja necessidade de instanciação de
objetos desta classe.*/
public static Motorista motorista;
public static Engenheiro engenheiro;
public static Secretaria secretaria;
public static void main(String[] args) {
motorista = new Motorista();
motorista.setId(1);//-> atributo herdado da classe pai
motorista.setNome("Pedro Pedroso");//-> atributo herdado da classe pai
motorista.setDataContrato("03/10/2012");//-> atributo herdado da classe pai
motorista.setCnh(45677893);
System.out.println("+-------------------------------------+");
System.out.println("| Dados do Motorista |");
System.out.println("+-------------------------------------+");
System.out.println("| Nome : "+motorista.getNome());
System.out.println("| Data Contratação : "+motorista.getDataContrato());
System.out.println("| CNH : "+motorista.getCnh());
System.out.println("+-------------------------------------+\n");
engenheiro = new Engenheiro();
engenheiro.setId(1);//-> atributo herdado da classe pai
engenheiro.setNome("Ferdinando Martelo");//-> atributo herdado da classe
pai
engenheiro.setDataContrato("09/03/2011");//-> atributo herdado da classe pai
______________________________________________________________________________________________
Curso Técnico em Informática 79 Programação Java
engenheiro.setCrea("CREA-77893");
System.out.println("+-------------------------------------+");
System.out.println("| Dados do Engenheiro |");
System.out.println("+-------------------------------------+");
System.out.println("| Nome : "+engenheiro.getNome());
System.out.println("| Data Contratação : "+engenheiro.getDataContrato());
System.out.println("| CREA : "+engenheiro.getCrea());
System.out.println("+-------------------------------------+\n");
secretaria = new Secretaria();
secretaria.setId(1);//-> atributo herdado da classe pai
secretaria.setNome("Mariete Maricota");//-> atributo herdado da classe pai
secretaria.setDataContrato("22/06/2013");//-> atributo herdado da classe pai
secretaria.setFormacao("Superior");
System.out.println("+-------------------------------------+");
System.out.println("| Dados da Secretária |");
System.out.println("+-------------------------------------+");
System.out.println("| Nome : "+secretaria.getNome());
System.out.println("| Data Contratação :
"+secretaria.getDataContrato());
System.out.println("| Formação : "+secretaria.getFormacao());
System.out.println("+-------------------------------------+\n");
}
}
Exercício:
1) Em um banco existem muitos funcionários. Além dos funcionários comuns há também outros
cargos, como os gerentes. Os gerentes guardam a mesma informação que um funcionário comum,
mas possuem outras informações, além de ter funcionalidades um pouco diferentes. Um gerente
possui uma senha numérica que permite o acesso ao sistema interno do banco, além do número
de funcionários que ele gerencia. De todo funcionário deve ser mantido o nome, cpf, e-mail,
telefone e endereço. Apresente o modelo de classes que melhor represente o cenário descrito.
6.10 Classes abstratas
Uma classe abstrata nada mais é do que uma especificação conceitual para outras classes.
Isso quer dizer que esta classe nunca será instanciada. Uma classe abstrata apenas fornece um
modelo para geração de outras classes. Esta classe nunca está completa, ou seja, servirá apenas
para criação de funcionalidades genéricas de classes filhas. Podemos também chamar as classes
abstratas de super classe. Por exemplo, é sabido que Pessoa Física e Pessoa Jurídica possuem
o atributo nome como uma informação em comum. Dentre dezenas de informações, a mais
comentada que gera uma grande diferença entre as duas
são CPF para Física e CNPJ para Jurídica. Este é um bom motivo para que se defina uma classe
abstrata. Ao invés de definir o atributo nome para as duas classes, o que gera redundância, cria-
______________________________________________________________________________________________
Curso Técnico em Informática 80 Programação Java
se uma classe abstrata e insere um atributo nome dentro dela. Feito isso, haverá a herança das
propriedades para as classes filhas, física e Jurídica, desta maneira ficam definidas dentro
de Física o atributo CPF e para. Jurídica o CNPJ. O atributo nome vem automaticamente
pela super classe.
Exemplo:
Super classe
package poo.heranca.abstracao;
public abstract class Pessoa {
protected int id;
protected String nome;
public Pessoa(String nome){
this.nome=nome;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
Sub classes
package poo.heranca.abstracao;
public class Juridica extends Pessoa{
private String cnpj;
public Juridica(String nome) {
super(nome);//Utiliza o método construtor da super classe
}
public String getCnpj() {
return cnpj;
}
public void setCnpj(String cnpj) {
this.cnpj = cnpj;
}
______________________________________________________________________________________________
Curso Técnico em Informática 81 Programação Java
}
package poo.heranca.abstracao;
public class Fisica extends Pessoa{
private String cpf;
public Fisica(String nome) {
super(nome);//Utiliza o método construtor da super classe
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
}
Exercícios:
1) Criar um modelo hierárquico que contenha as seguintes classes: Veiculo (classe abstrata),
Bicicleta e Automóvel.
Os métodos da classe veículo são todos abstratos e possuem a seguinte assinatura:
public float acelerar(float velocidade);
public void parar();
Estes métodos são implementados nas subclasses Automóvel e Bicicleta. Acrescentar na classe
Automóvel o método public void torcarOleo(float litros).
2) Implemente uma classe abstrata de nome Forma onde são declarados dois métodos abstratos:
float calcularArea();
float calcularPerimetro();
Crie, como subclasse de Forma, uma classe de nome Retângulo cujas instâncias são
caracterizadas pelos atributos lado e altura, ambos do tipo float. Implemente na classe Retângulo
os métodos herdados de Forma e outros que achar necessário.
Crie, como subclasse de Forma, uma classe de nome Círculo cujas instâncias são
caracterizadas pelo atributo raio do tipo float. Implemente na classe Círculo os métodos herdados
de Forma e outros que achar necessário.
Crie, como subclasse de Retângulo, uma classe de nome Quadrado cujas instâncias são
caracterizadas pelos atributos lado e altura com o mesmo valor.
Elabore um programa de teste, onde é declarado um vetor (array), de dimensão 5, do tipo
estático Forma. Nesse vetor devem ser guardadas instancias de Retângulo, Circulo e Quadrado
seguindo uma ordem aleatória. Em seguida percorra o vetor exibindo a área e o perímetro de cada
forma armazenada no vetor.
______________________________________________________________________________________________
Curso Técnico em Informática 82 Programação Java
6.11 Polimorfismo
Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma mesma
superclasse podem invocar métodos que têm a mesma identificação, assinatura, mas
comportamentos distintos, especializados para cada classe derivada, usando para tanto uma
referência a um objeto do tipo da superclasse. O overload não é um tipo de polimorfismo, pois com
overload a assinatura do método obrigatoriamente tem que ter argumentos diferentes, requisito que
fere o conceito de Polimorfismo citado anteriormente.
De forma genérica, polimorfismo significa várias formas. No caso da Orientação a Objetos,
polimorfismo denota uma situação na qual um objeto pode se comportar de maneiras diferentes ao
receber uma mensagem, dependendo do seu tipo de criação.
Polimorfismo também implica que uma operação de uma mesma classe pode ser
implementada por mais de um método. O usuário não precisa saber quantas implementações
existem para uma operação, ou explicitar qual método deve ser utilizado: a linguagem de
programação deve ser capaz de selecionar o método correto a partir do nome da operação, classe
do objeto e argumentos para a operação. Desta forma, novas classes podem ser adicionadas sem
necessidade de modificação de código já existente, pois cada classe apenas define os seus
métodos e atributos. Em Java, o polimorfismo se manifesta apenas em chamadas de métodos.
A decisão sobre qual o método que deve ser selecionado, de acordo com o tipo da classe
derivada, é tomada em tempo de execução, através do mecanismo de ligação tardia. A ligação
tardia ocorre quando o método a ser invocado é definido durante a execução do programa. Através
do mecanismo de sobrecarga, dois métodos de uma classe podem ter o mesmo nome, desde que
suas assinaturas sejam diferentes, entretanto isso não é polimorfismo. Como dito anteriormente,
tal situação não gera conflito, pois o compilador é capaz de detectar qual método deve ser escolhido
a partir da análise dos tipos dos argumentos do método. Nesse caso, diz-se que ocorre a ligação
prematura para o método correto. Em Java, todas as determinações de métodos a executar
ocorrem através de ligação tardia exceto em dois casos:
1) Métodos declarados como final não podem ser redefinidos e, portanto, não são passíveis
de invocação polimórfica da parte de seus descendentes; e
2) Métodos declarados como private são implicitamente finais.
No caso de polimorfismo, é necessário que os métodos tenham exatamente a mesma identificação,
sendo utilizado o mecanismo de redefinição de métodos, que é o mesmo que sobrescrita de
métodos em classes derivadas. A redefinição ocorre quando um método cuja assinatura já tenha
sido especificada recebe uma nova definição, ou seja, um novo corpo, em uma classe derivada. É
importante observar que, quando polimorfismo está sendo utilizado, o comportamento que será
adotado por um método só será definido durante a execução. Embora em geral esse seja um
mecanismo que facilite o desenvolvimento e a compreensão do código orientado a objetos, há
algumas situações onde o resultado da execução pode ser não-intuitivo.
Exemplo:
abstract class Mamífero {
public abstract double obterCotaDiariaDeLeite();
}
______________________________________________________________________________________________
Curso Técnico em Informática 83 Programação Java
class Elefante extends Mamífero {
public double obterCotaDiariaDeLeite(){
return 20.0;
}
}
class Rato extends Mamifero {
public double obterCotaDiariaDeLeite() {
return 0.5;
}
}
class Aplicativo {
public static void main(String args[]){
System.out.println("Polimorfismo\n");
Mamifero mamifero1 = new Elefante();
System.out.println("Cota diaria de leite do elefante: " +
mamifero1.obterCotaDiariaDeLeite());
Mamifero mamifero2 = new Rato();
System.out.println("Cota diaria de leite do rato: " +
mamifero2.obterCotaDiariaDeLeite());
}
}
Exercícios:
1) Defina o que significa uma classe em Programação Orientada a objetos.
2) Defina um Objeto.
3) Quais os três pilares da programação orientada a objetos.
4) O que é uma interface? Qual a sua aplicação?
5) Defina uma classe abstrata.
6) Defina o que são modificadores de acesso.
______________________________________________________________________________________________
Curso Técnico em Informática 84 Programação Java
7) Defina encapsulamento. Qual a sua finalidade?
8) Defina herança em POO.
9) Defina super classe e subclasse.
10) Quantas subclasses uma superclasse pode ter.
11) É possível uma subclasse descender de vaias superclasses?
12) Como funciona a reescrita de métodos?
13) Qual a consequência em declarar um método como final?
14) Qual a função da anotação @override?
15) Depois que um método é reescrito, é possível chamar o método antigo da classe mãe?
16) Defina polimorfismo em POO.
17) Defina como ocorre o acoplamento entre classes.
18) Qual a relação de Herança e acoplamento?
19) Qual a finalidade da palavra-chave super?
20) Diferencie polimorfismo estático e dinâmico.
21) Considere as classes a seguir, presentes em uma aplicação Java orientada a objetos:
______________________________________________________________________________________________
Curso Técnico em Informática 85 Programação Java
Em uma classe principal foram digitadas, no interior do método main, as seguintes linhas:
As linhas que contêm a instrução s = f.calcularSalario( ); demonstram um conceito da orientação a
objetos conhecido como:
a) encapsulamento
b) sobrecarga de métodos
c) polimorfismo
d) método abstratos
e) sobrecarga de construtores
______________________________________________________________________________________________
Curso Técnico em Informática 86 Programação Java
Documentar pontos estratégicos do código fonte, é uma necessidade universal em vários
paradigmas ou plataformas de desenvolvimento. E cada vez mais, é necessário gerar e manipular
de uma forma eficiente todos os comentários em formato de documentação de códigos, visando
com isso, facilitar a reutilização futura desses comentários como fonte geradora de conhecimentos
acerca de uma classe.
Em Java, felizmente, há um recurso do próprio JDK, que facilita todo o trabalho de criação e
manipulação dos comentários, essa ferramenta é denominada de JavaDoc.
De maneira geral o JavaDoc fornece uma linguagem especifica para enriquecer os
comentários que introduzem classes, atributos e métodos.
Seu funcionamento baseia-se na inserção de textos explicativos em forma de um comentário
especial, que antecedem um escopo de uma classe ou método, tendo assim, a responsabilidade
de apresentar o mesmo.
Seu funcionamento é através do uso de marcação de documentos com doclets, gerando
arquivos nos formatos HTML, SGML, XML ou RTF. Tais marcações são feitas através de
comentários, contendo tags especiais que especificam quais informações serão inseridas, com
objetivo de manter uma massa de conhecimento reutilizável em qualquer projeto que faça uso da
classe em questão.
Vale ressaltar, que é possível combinar tags da própria especificação HTML, com as tags
oferecidas pelo JavaDoc, tornando possível à criação de documentos completos gerados a partir
dos comentários do próprio código.
Entendendo a sintaxe
A estrutura básica de um comentário de documentação tem como característica principal, o
uso de uma barra e dois asteriscos (/**) no início e no seu final, possui um asterisco e uma
barra ( */ ). Conforme o exemplo a seguir.
/** Exemplo básico de um comentário em JavaDoc */
/** Exemplo básico de um comentário em JavaDoc
* com mais de uma linha.
*/
Por convenção, sugere-se alocar os blocos de comentários, antes da definição de uma
classe, interface, atributos, ou métodos, dessa forma, cria-se uma introdução conceitual ao referido
elemento do código.
Documentação - JavaDoc 7
______________________________________________________________________________________________
Curso Técnico em Informática 87 Programação Java
Um ponto forte do JavaDoc é o uso de tags especiais a fim de qualificar melhor a informação
contida nos comentários.
Com as tags é possível especificar, por exemplo, o autor, a versão, links, data, exceções
lançadas, lista de argumentos de um método e tipo de retorno de um método.
Essas tags são inseridas dentro do bloco de comentários, antecedidas pelo carctetre @
(arroba), e após o nome da própria tag, insere-se o conteúdo desejado. A seguir, as tags
disponíveis pelo JavaDoc.
Tag Significado
@author Especifica o autor da classe ou do
método em questão.
@deprecated Identifica classes ou métodos obsoletos.
É interessante informar nessa tag, quais
métodos ou classes podem ser usadas
como alternativa ao método obsoleto.
@link Possibilita a definição de um link para
um outro documento local ou remoto
através de um URL.
@param Mostra um parâmetro que será passado
a um método.
@return Mostra qual o tipo de retorno de um
método.
@see Possibilita a definição referências de
classes ou métodos, que podem ser
consultadas para melhor compreender a
ideia daquilo que está sendo comentada.
@since Indica desde quando uma classe ou
métodos foi adicionado na aplicação.
@throws Indica os tipos de exceções que podem
ser lançadas por um método.
@version Informa a versão da classe.
Exemplos:
A seguir alguns exemplos de codificação com o uso de comentários JavaDoc.
______________________________________________________________________________________________
Curso Técnico em Informática 88 Programação Java
Comentário simples
/** Um exemplo de um simples de comentário com o JavaDoc */
Outro exemplo interessante é a possibilidade de inserção de tags HTML, dentro do próprio
comentário JavaDoc. A seguir um exemplo que faz uso das tas<b> e <i> para destacar, trechos
do comentário.
/**Com esta combinação podemos inserir <b>marcações</b> HTML em <i>nossos</i>*/
Comentários em classes
A seguir, um exemplo de classe com atributos e métodos comentados com JavaDoc.
package projetojavadoc;
/**Classe para objetos do tipo Funcionários, onde serão contidos, valores e
métodos para o mesmo.
* @author Maria Felipeta
* @version 1.05
* @since Release 02 da aplicação
*/
public class Funcionarios {
private String matricula;
private Double salario;
/** Método para retorno da matrícula do funcionário
* @return String - Nr da Matrícula*/
public String getMatricula(){
return this.matricula;
}
/** Método para retorno do salário do funcionário
* @return Double - Valor do Salário */
public Double getSalario(){
return this.salario;
}
/**Método para cálculo da diária com base no salário do
* funcionário dividido pelo mês comercial de 30 dias para efeito * de cálculo de
ajuda de custo para viagem.
* @author Pedro Bó
* @param diasViagem int - Valor total das vendas do mês.
______________________________________________________________________________________________
Curso Técnico em Informática 89 Programação Java
* @param valorDeslocamento Double - Valor pago em cada diária despesas
básicas de deslocamento.
* @return Double - Valor da diaria
*/
public Double calculaAjudaCusto(int diasViagem, Double
valorDeslocamento) throwsArithmeticException {
try{
return (this.salario / 30)*diasViagem+valorDeslocamento;
}catch (ArithmeticException ae){
return 0.0;
}
}
/**Método para cálculo do valor da bonificação baseada na
* seguinte faixa de valores: Para vendas menores de
* 25.000,00, o percentual de comissão aplicado será de 5%, e * para valores
iguais ou maiores de 25.000,00, o percentual
* será de 10%
* @author Maria Felipeta
* @param valorVendas - Valor total das vendas do mês
* @return Double - Valor do resultado do cálculo conforme a faixa de
comissões.
*/
public Double calculaBonificacao(Double valorVendas) {
if (valorVendas <25000.00 ){
return this.salario * 0.05;
} else {
return this.salario * 0.10;
}
}
}
Automatizando através do NetBeans
O NetBeans que atualmente encontra-se na versão 8.0.2, oferece recursos nativos na
própria IDE para:
Criar de maneira automática os comentários no mesmo momento da criação de uma classe
em projeto.
Disponibilizar code completion para mostrar as tags JavaDoc disponíveis em cada área
do código.
Gerar a criação de documentos HTML, contendo a documentação feita através dos
comentários em JavaDoc.
______________________________________________________________________________________________
Curso Técnico em Informática 90 Programação Java
Criando um projeto no NetBeans
Vamos agora criar um projeto básico, para isso, abra o NetBeans, clique no menu File/New,
será aberta uma janela para escolher o tipo de projeto desejado, nessa etapa, escolha Java
Application, siga os procedimentos para nomeação e definição dos diretórios onde será
armazenado esse nosso projeto.
Após a conclusão desse processo, se você deixou marcado a opção Create a main class na
tela de construção da aplicação, seu projeto terá uma classe chamada Main, que dentre outras
finalidades, possui um método main para o bloco de execução principal de sua aplicação. Note que
essa classe já foi criada com alguns comentários usando JavaDoc
Para ter a total visão sobre a aplicação do JavaDoc, crie no próprio NetBeans, uma classe
chamada Funcionarios, e codifique-a conforme a listagem mostrada anteriormente.
É importante você notar que o NetBeans possui um recurso de code completion para mostrar
e inserir as tags disponíveis, ou seja, dentro do bloco de comentário, você pode digitar o sinal de
@ (arroba) seguido pelo pelas teclas Ctrl+Espaço, para que seja mostrada uma pequena janela
flutuante estilo menu popup sobre seu código, para que seja escolhida a tag desejada.
Uma vez concluída essa classe, podemos agora, gerar os arquivos HTML em formato de
documentação, para isso, conforme mostra abaixo, clique no menu Build/Generate javadoc for
“seu projeto”.
Após esse processo, será executado automaticamente o navegador padrão de sua máquina,
exibindo um arquivo na estrutura de HTML conteúdo o arquivo JavaDoc gerado, veja na figura a
seguir, um trecho de um arquivo desses, vale ressaltar que, esse arquivo estará armazenado no
sub-diretório \dist\javadoc\ dentro do diretório de seu projeto.
______________________________________________________________________________________________
Curso Técnico em Informática 91 Programação Java
Atualmente, o Java suporta, oficialmente, dois tipos de bibliotecas gráficas: AWT e Swing. A
AWT foi a primeira API para interfaces gráficas a surgir no Java e foi, mais tarde, superada pelo
Swing (a partir do Java 1.2), que possui diversos benefícios em relação a seu antecessor.
As bibliotecas gráficas são bastante simples no que diz respeito a conceitos necessários
para usá-las. A complexidade no aprendizado de interfaces gráficas em Java reside no tamanho
das bibliotecas e no enorme mundo de possibilidades; isso pode assustar, em um primeiro
momento.
AWT e Swing são bibliotecas gráficas oficiais inclusas em qualquer JRE ou JDK. Além
destas, existem algumas outras bibliotecas de terceiros, sendo a mais famosa, o SWT desenvolvida
pela IBM e utilizada no Eclipse e em vários outros produtos.
8.1 Componentes Swing
O pacote javax.swing foi criado em 1997 e inclui os componentes GUI que se tornaram
padrão em Java a partir da versão 1.2 da plataforma Java 2. A maioria dos componentes Swing
(assim são denominados) são escritos, manipulados e exibidos completamente em Java, sendo
conhecidos como componentes Java puros. Isso oferece a eles um maior nível de portabilidade e
flexibilidade. Os nomes de tais componentes recebem um “J”, como, por exemplo: JLabel, JButton,
JFrame, JPanel, etc. Tal peculiaridade se justifica para diferenciar esses componentes dos que
serão mencionados logo adiante. São considerados peso-leve e fornecem funcionalidade e
aparência uniforme em todas as plataforma, sendo denominada de aparência de metal (metal look-
and-feel).
Interface Gráfica 8
______________________________________________________________________________________________
Curso Técnico em Informática 92 Programação Java
8.1.1 Hierarquia das Classes dos Componentes
Mostraremos abaixo a hierarquia de herança das classes que definem atributos e
comportamentos que são comuns a maioria dos componentes Swing. Cada classe é exibida com
o seu pacote:
As operações comuns à maioria dos componentes GUI, tanto Swing como AWT são
definidas na classe Component. Isso inclui métodos relativos à posicionamento, personalização,
tamanho, visibilidade, pintura, registro de tratadores de eventos, ajuste e retorno de estado dos
componentes. Em aplicativos com JFrames e em applets, anexamos os elementos ao painel de
conteúdo, que é um objeto da classe Container. Logo, a classe Container dá suporte à adição e
posicionamento dos componentes ao painel de conteúdo de um contêiner. A classe JComponent,
______________________________________________________________________________________________
Curso Técnico em Informática 93 Programação Java
que define os atributos e comportamentos para suas subclasses, é a superclasse da maioria dos
componentes Swing. Com exceção dos conteiners JFrame e JDialog, todos os demais
componentes Swing cujo nome comece com “J” descendem da classe JComponent.
8.1.2 Portabilidade
As APIs de interface gráfica do Java favorecem, ao máximo, o lema de portabilidade da
plataforma Java. O look-and-feel do Swing é único em todas as plataformas onde roda, seja ela
Windows, Linux, ou qualquer outra. Isso implica que a aplicação terá exatamente a mesma interface
(cores, tamanhos etc) em qualquer sistema operacional.
Grande parte da complexidade das classes e métodos do Swing está no fato da API ter sido
desenvolvida tendo em mente o máximo de portabilidade possível. Favorece-se, por exemplo, o
posicionamento relativo de componentes, em detrimento do uso de posicionamento fixo, que
poderia prejudicar usuários com resoluções de tela diferentes da prevista.
Com Swing, não importa qual sistema operacional, qual resolução de tela, ou qual
profundidade de cores: sua aplicação se comportará da mesma forma em todos os ambientes.
8.1.3 Look And Feel
Look-and-Feel (ou LaF) é o nome que se dá à "cara" da aplicação (suas cores, formatos e
etc.). Por padrão, o Java vem com um look-and-feel próprio, que se comporta exatamente da
mesma forma em todas as plataformas suportadas.
Mas, às vezes, esse não é o resultado desejado. Quando rodamos nossa aplicação no
Windows, por exemplo, é bastante gritante a diferença em relação ao visual das aplicações nativas.
Por isso é possível alterar qual o look-and-feel a ser usado em nossa aplicação.
Além do padrão do Java, o JRE 5 da Sun ainda traz LaF nativos para Windows e Mac OS,
além do Motif e GTK. E, fora esses, você ainda pode baixar diversos LaF na Internet ou até
desenvolver o seu próprio.
Veja esses screenshots da documentação do Swing mostrando a mesma aplicação rodando
com 4 LaF diferentes:
8.1.4 Bases de Estruturação das Interfaces Gráficas
Visto que agora já temos uma ideia espacial concebida, resta-nos analisar a anatomia das
interfaces gráficas em Java, a qual baseia-se nos elementos que serão descritos nestas próximas
seções.
______________________________________________________________________________________________
Curso Técnico em Informática 94 Programação Java
8.1.4.1 Conteiners
Dão suporte à exibição e agrupamento de outros componentes, inclusive outros conteiners.
Eles constituem a base onde os outros elementos são anexados. Precisamente, é o local onde
podemos montar nossa aplicação.
Como veremos, em praticamente todos os nossos exemplos usamos um objeto da classe
Container denominado conteiner. A ele atribuímos uma chamada ao método getContentPane( ),
que devolve uma referência para o painel de conteúdo do aplicativo ou do applet. O painel de
conteúdo compreende a área imediatamente inferior a barra de título de uma janela, estendendo-
se até os limites da mesma.
A classe Container define o método add(Component), para adicionar elementos, e setLayout
(LayoutManager), que configura um gerenciador de leiaute para gerir o posicionamento e
dimensionamento dos mesmos.
Ressalta-se que a disposição dos elementos adicioandos a um contêiner obedece a ordem
em que eles foram anexados e ao gerenciador de leiaute previamente definido. Se um conteiner
não é suficientemente dimensionado para acomodar os componentes anexados a ele, alguns ou
todos os elementos GUI simplesmente não serão exibidos.
Qualquer programa que ofereça uma interface vai possuir pelo menos um conteiner, que pode ser :
JFrame - janela principal do programa;
JDialog - janela para diálogos;
JApplet - janela para Applets.
8.1.4.2 Swing - Mensagens
A classe mais simples do Swing é a JOptionPane que mostra janelinhas de mensagens,
confirmação e erros, entre outras.
Podemos mostrar uma mensagem para o usuário com a seguinte linha:
A classe JFileChooser é a responsável por mostrar uma janela de escolha de arquivos. É
possível indicar o diretório inicial, os tipos de arquivos a serem mostrados, selecionar um ou vários
e muitas outras opções.
Para mostrar a mensagem:
O argumento do showOpenDialog indica qual o componente pai da janela de mensagem
(pensando em algum frame aberto, por exemplo, que não é nosso caso). Esse método retorna
um int indicando se o usuário escolheu um arquivo ou cancelou. Se ele tiver escolhido um,
podemos obter o File com getSelectedFile:
______________________________________________________________________________________________
Curso Técnico em Informática 95 Programação Java
8.1.4.3 Componentes: JFrame, JPanel e JButton
Uma interface gráfica em Java é baseada em dois elementos:
– Containers: servem para agrupar e exibir outros componentes
JFrame e JPanel
– Componentes:
JLabel, JButton, JTextField, JScrollPane, JCheckBox, JComboBox, JRadioButton ,JList,
JTable, JMenuBar, JMenu e JmenuItem
Uma janela é definida através da classe JFrame, que serve como container para outros
componentes, como botões, imagens ou painéis. O JFrame possui atributos que definem uma
janela, como barra de título e borda. O JPanel é um container simples que pode ser utilizado para
acrescentar componentes em uma janela, que será utilizado mais tarde.
8.1.4.4 JFrame
Esta classe define objetos que são frequentemente utilizados para criar aplicativos baseados
em GUI. Eles consistem em uma janela com barra de título e uma borda e fornecem o espaço para
a GUI do aplicativo ser construída. A classe JFrame é uma subclasse de java.awt.Frame, que por
sua vez é subclasse de java.awt.Window. Pelo mecanismo de herança, nota-se que JFrames são
um dos poucos componentes GUI do Swing que não são considerados de peso-leve, pois não são
escritos completamente em Java. Sendo assim, quando possível, devemos devolver ao sistema os
recursos ocupados pela janela, descartando-a. Frisamos que a janela de um programa Java faz
parte do conjunto de componentes GUI da plataforma local e será semelhante as demais janelas,
pois serve-se da biblioteca gráfica do sistema em questão.
A classe JFrame suporta três operações quando o usuário fecha a janela. Por default, a
janela é removida da tela (ocultada) quando o usuário intervém indicando o seu fechamento. Isso
pode ser controlado com o método setDefaultCloseOperation(int), que utiliza como argumento as
constantes da interface WindowConstants (pacote javax.swing) implementada por JFrame:
DISPOSE ON CLOSE: descarta a janela devolvendo os seus recursos ao sistema;
DO NOTHING ON CLOSE: indica que o programador determinará o que fazer quando o
usuário designar que a janela deve ser fechada;
HIDE ON CLOSE: (o default) a janela é ocultada, removida da tela;
EXIT ON CLOSE: determinamos que quando fechamos a JFrame, o aplicativo seja
finalizado. Essa constante é definida na classe JFrame e foi introduzida na versão 1.3 da
Plataforma Java. A janela só será exibida na tela quando o programa invocar o método
______________________________________________________________________________________________
Curso Técnico em Informática 96 Programação Java
setVisible(boolean) com um argumento true, ou o método show( ).
O tamanho da janela é configurado com uma chamada ao método setSize(int x, int y), que
define nos valores inteiros dos argumentos a largura e a altura da mesma. Se não chamarmos esse
método, somente a barra de título será exibida. Também podemos utilizar o método pack( ), que
utiliza os tamanhos preferidos dos componentes anexados ao painel de conteúdo para determinar
o tamanho da janela. Por tamanho preferido, entende-se uma chamada realizada pelos
gerenciadores de leiaute ao método getPreferredSize( ) de cada componente GUI. Esse método
indica o melhor tamanho para os componentes. É herdado da classe java.awt.Component, de modo
que todos 15 os objetos que derivem-se dessa classe podem responder a essa evocação. Ela
devolve um objeto da classe Dimension (pacote java.awt). Podemos fazer uso dos métodos
setMinimumSize(Dimension) e setMaximumSize(Dimension), que estabelecem os tamanhos
extremos dos elementos. O componente não deveria ser maior que o tamanho máximo e nem
menor que o mínimo. Entretanto, esteja consciente de que certos gerenciadores de leiaute ignoram
essa sugestão. Todos os elementos têm um tamanho preferido default, como, por exemplo, um
objeto JPanel, que tem altura e largura de 10 pixels. Se necessitarmos mudar esse tamanho default,
devemos sobrescrever o método getPreferredSize( ), fazendo com que ele retorne um objeto
Dimension que contenha a nova largura e altura do componente, ou usar o método
setPreferredSize(new Dimension( int x, int y)). Sobre o posicionamento, por default, o canto superior
esquerdo da janela é posicionado nas coordenadas (0, 0) da tela, ou seja, no canto superior
esquerdo. Podemos alterar essa característica com o método setLocation(int x, int y). Mais à frente,
discutiremos os eventos gerados pela manipulação de janelas e como tratá-los.
Exemplo instanciando um JFrame:
import javax.swing.*;
public class JanelaJFrame {
public static void main(String[] args) {
JFrame janela = new JFrame("Minha Primeira Janela");
janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //define o que fazer
quando a janela for fechada
janela.setSize(800, 600); //define o tamanho da janela
janela.setVisible(true); //exibe a janela
}
}
______________________________________________________________________________________________
Curso Técnico em Informática 97 Programação Java
8.1.4.5 JDesktopPane e JInternalFrame
São classes que fornecem suporte à criação de interfaces de múltiplos documentos. Uma
janela principal (pai) contém e gerencia outras janelas (filhas). A grande utilidade disso é que
podemos visualizar vários documentos que estão sendo processados em paralelo ao mesmo
tempo, facilitando a edição ou leitura dos mesmos. Um JInternalFrame tem um painel de conteúdo
ao qual os componentes GUI podem ser anexados.
8.1.4.6 JDialog
Usamos a classe JDialog, que é subclasse de java.awt.Dialog para criarmos caixas de
diálogo elaboradas, embora mais limitados que as originadas por JFrames. Em prol da facilidade,
a classe JOptionPane, que está definida no pacote de extensão javax.swing, oferece caixas de
diálogo pré-definidas que permitem aos programas exibir simples mensagens para os usuários.
Cada vez que usamos uma JOptionPane para implementar um diálogo, na verdade estamos
usando uma JDialog nos bastidores. A razão é que JOptionPane são simplesmente um contêiner
que pode automaticamente criar uma JDialog e anexa-la ao seu painel de conteúdo.
Podemos definir se o tamanho de uma JDialog é redimensionável, com o método
setResizable(boolean).
Obviamente, devido a diversidade de funcionalidades e de construtores, para usarmos todas
as potencialidades devemos estudar profundamente as classes em questão. Abaixo mostraremos
alguns métodos estáticos da classe JOptionPane.(todos são precedidos por JOptionPane.) e a
sintaxe mais comumente utilizada para criarmos caixas de diálogo pré-definidas:
showInputDialog(String):Método usado para solicitar a entrada de algum dado em forma de
String. Lembre-se que os valores recebidos devem ser atribuídos à variáveis do tipo String
e convertidos para outros tipos caso desejarmos realizar operações sobre eles.
showMessageDialog(Component, Object, String, int, Icon): Método que exibe uma caixa de
diálogo com texto, ícone, posicionamento e título definidos pelo programador.
Podemos fazer uso dos seguintes valores para as constantes:
JOptionPane.ERROR MESSAGE - Indica mensagem de erro ao usuário;
JOptionPane.INFORMATION MESSAGE - Exibe uma mensagem com informações que
podem ser dispensadas;
JOptionPane.WARNING MESSAGE - Indica mensagem de advertência sobre algum
______________________________________________________________________________________________
Curso Técnico em Informática 98 Programação Java
problema em potencial;
JOptionPane.QUESTION MESSAGE - Impõe uma mensagem que pergunta algo ao usuário;
JOptionPane.PLAIN MESSAGE - Exibe um diálogo que simplesmente contém uma
mensagem sem nenhum ícone.
8.1.4.7 Componentes Atômicos
São os botões, scrollbars, labels, sliders, check boxes, etc. Eles não podem conter outros
elementos.
8.1.4.7.1 JLabel
São rótulos inertes que geralmente informam ou descrevem a funcionalidade de outros
componentes GUI, como por exemplo, campos de texto, ícones, etc. As instruções são mostradas
por meio de uma linha de texto somente leitura, uma imagem, ou ambos. Aqui salientamos o uso
do método setToolTipText(String), o qual fornece dicas de ferramenta a todos os elementos
herdados da classe JComponent. Dessa forma, quando o usuário posicionar o cursor do mouse
sobre algum componente, ficará ciente da função do mesmo.
8.1.4.7.2 Botões
É um componente que quando clicado dispara uma ação específica. Um programa Java
pode utilizar vários tipos de botões, incluindo botões de comando, caixas de marcação, botões de
alternância e botões de opção. Para criarmos algum desses tipos de botões, devemos instanciar
uma das muitas classes que descendem da classe AbstractButton, a qual define muito dos recursos
que são comuns aos botões do Swing. Cita-se, por exemplo, a exibição de texto e imagens em um
botão, o uso de caracteres mnemônicos, dentre outros. Vejamos a hierarquia de classes, partindo
da classe JComponent:
______________________________________________________________________________________________
Curso Técnico em Informática 99 Programação Java
8.1.4.7.3 JButton
É um dos componentes mais familiares e intuitivos ao usuário. Os botões de comando são
criados com a classe JButton e seu pressionamento geralmente dispara a ação especificada em
seu rótulo, que também suporta a exibição de ícones. Também podemos definir dicas de ferramenta
para cada botão, juntamente com mnemônicos, que dão acesso rápido pelo teclado aos comandos
definidas nos botões. Para oferecer maior interatividade visual com a GUI, o JButton oferece a
possibilidade de ícones rollover, os quais mudam de aparência quando o cursor está posicionado
sobre eles, dando a entender que o seu pressionamento resulta em uma ação. Deve-se ter a
mesma atenção com os arquivos de imagem, de acordo com o que foi mencionado anteriormente.
Pressionar um JButton gera eventos ActionEvent que, juntamente com outros eventos, serão
abordados mais à frente.
8.1.4.7.4 JCheckBox
A classe JCheckBox dá suporte à criação de botões com caixa de marcação, sendo que
qualquer número de itens pode ser selecionado. Quando um item é selecionado, um ItemEvent é
gerado. O mesmo pode ser tratado por um objeto que implemente a interface ItemListener. A classe
que fornece as funcionalidades para este objeto deve definir o método itemStateChanged.
______________________________________________________________________________________________
Curso Técnico em Informática 100 Programação Java
8.1.4.7.5 JRadioButton
Os botões de opção, que são definidos na classe JRadioButton, assemelham-se às caixas
de marcação no que concerne aos seus estados (selecionado ou não selecionado). Entretanto,
costumeiramente são usados em grupo no qual apenas um botão de opção pode ser marcado,
forçando os demais botões ao estado não-selecionado.
Os métodos aqui utilizados pouco diferem dos da classe anterior, sendo que a única
novidade é o método getSource( ), que retorna a fonte geradora do evento.
8.1.4.7.6 JTextField
Compreende a área de uma única linha que suporta a inserção ou exibição de texto.
Podemos definir se o texto pode ser manipulado com o método setEditable(boolean), utilizando no
argumento o valor true.
Quando o usuário digita os dados em uma JTexField e pressiona Enter, ocorre um evento de
ação. Esse evento é processado pelo ouvinte de evento registrado que pode usar os dados que
estão no JTexField no momento em que o evento ocorre.
______________________________________________________________________________________________
Curso Técnico em Informática 101 Programação Java
8.1.4.7.7 JPasswordField
É uma subclasse de JTextField e acrescenta vários métodos específicos para o
processamento de senhas. Sua aparência e comportamento quase nada diferem de uma
JTextField, a não ser quando o texto é digitado, pois o mesmo fica ocultado pelos asteriscos. Tal
procedimento se justifica para ocultar os caracteres inseridos, dado que esse campo contém uma
senha.
8.1.4.7.8 JTextArea
É uma área dimensionável que permite que múltiplas linhas de texto sejam editadas com a
mesma fonte. Esta classe é herdada de JTextComponent, que define métodos comuns para
JTextField, JTextArea e outros elementos GUI baseados em texto.
As JTextAreas não têm eventos de ação como os objetos da classe JTextField, cujo o
pressionamento de Enter gera um evento. Então, utiliza-se um outro componente GUI (geralmente
um botão) para gerar um evento externo que sinaliza quando o texto de uma JTextArea deve ser
processado.
______________________________________________________________________________________________
Curso Técnico em Informática 102 Programação Java
8.1.4.7.9 JScrollPane
Objetos dessa classe fornecem a capacidade de rolagem a componentes da classe
JComponent, quando estes necessitam de mais espaço para exibir dados.
JScrollpane (Component, int, int) é o construtor mais elaborado e recebe um componente
(JTextArea por exemplo) como primeiro argumento, definindo qual será o cliente do JScrollPane,
ou seja, para que membro será fornecido as barras de rolagem. Os dois próximos argumentos
definem o comportamento da barra vertical e da horizontal, respectivamente. Para isso, podemos
fazer uso das constantes definidas na interface ScrollPaneConstants que é implementada por
JScrollPane. Vejamos elas:
JScrollPane.VERTICAL SCROLLBAR AS NEEDED;
JScrollPane.HORIZONTAL SCROLLBAR AS NEEDED Indicam que as barras de rolagem
devem aparecer somente quando necessário;
JScrollPane.VERTICAL SCROLLBAR ALWAYS;
JScrollPane.HORIZONTAL SCROLLBAR ALWAYS Indicam que as barras de rolagem
devem aparecer sempre;
JScrollPane.VERTICAL SCROLLBAR NEVER;
JScrollPane.HORIZONTAL SCROLLBAR NEVER Indicam que as barras de rolagem nunca
devem aparecer;
8.1.4.7.10 JSlider
É um marcador que desliza entre um intervalo de valores inteiros, podendo selecionar
qualquer valor de marca de medida em que o marcador repouse. Uma das inúmeras utilidades
desse controle deslizante é restringir os valores de entrada em um aplicativo, evitando que o usuário
informe valores que causem erros.
______________________________________________________________________________________________
Curso Técnico em Informática 103 Programação Java
8.1.4.7.11 JComboBox
Assemelha-se a um botão, porém, quando clicado, abre uma lista de possíveis valores ou
opções. Mais precisamente é uma caixa de combinação que permite ao usuário fazer uma seleção
a partir de uma lista de itens.
Atende-se para que a lista da caixa de combinação, quando aberta, não ultrapasse os limites
da janela da aplicação.
Também é possível digitar nas linhas de uma caixa de combinação. Elas são implementadas
com a classe JComboBox, herdada de JComponent. Tais caixas de combinação geram ItemEvents,
assim como as JCheckBoxes.
8.1.4.7.12 JList
Exibe em uma coluna uma série de itens que podem ser selecionados. A classe JList suporta
listas em que o usuário pode selecionar apenas um item e listas de seleção múltipla, permitindo
que um número qualquer de itens seja selecionado. Fazemos uso do método
setSelectionMode(ListSelectionMode) para definir isso.
Os itens que serão exibidos por uma lista podem ser passados como argumento no momento
da inicialização. A classe JList fornece construtores que recebem Vectors e arrays como
argumentos. Se você inicializar uma lista com um array ou vetor, o construtor implicitamente cria
uma lista modelo default. Ela é imutável, ou seja, você não poderá adicionar, remover ou
sobrescrever os itens. Para criar uma lista onde os itens possam ser modificados, devemos
configurar o modelo de lista chamando o método setModel(ListModel). Para o mesmo propósito,
também é possível instanciar um objeto de uma classe de lista mutável, como DefaultListMode,
adicionar elementos a ele, para depois passa-lo como argumento do construtor de JList.
______________________________________________________________________________________________
Curso Técnico em Informática 104 Programação Java
8.1.4.7.13 JPopupMenus
São menus sensíveis ao contexto, ou seja, em virtude da localização do cursor do mouse,
um clique no botão direito do mesmo dispara um evento que abre um menu flutuante. Tal menu
fornece opções selecionáveis ao determinado componente por sobre o qual o evento de disparo foi
gerado.
8.1.4.7.14 Menus
Muito familiares a nós, os menus talvez sejam os componentes que mais aparecem nas
ferramentas computacionais que utilizamos. Geralmente eles são encontrados no topo da janela
da aplicação, de onde dão suporte à organização e agrupamento de funções afins em um mesmo
contexto visual, o que facilita muito a localização e entendimento por parte do usuário, já que a
estrutura de cada menu está delineada pelas características dos itens.
Os menus, que são instanciados a partir da classe JMenu, são anexados a uma barra de
______________________________________________________________________________________________
Curso Técnico em Informática 105 Programação Java
menus com o método add(JMenu) de JMenuBar, sendo que instancias dessa última classe
comportam-se como conteiners para menus. A classe JMenuBar fornece os métodos necessários
ao gerenciamento da barra onde os menus são anexados. A ordenação dos mesmos depende da
ordem em que foram adicionados, sendo que são “empilhados” horizontalmente da esquerda para
a direita. Evidentemente, só podemos anexar menus à janelas da classe JApplet, JDialog, JFrame
e JInternalFrame, e fazemos isso usando o método setJMenuBar(JMenuBar).
A classe JMenuItem capacita a criação de itens de menu que, por sua vez, devem ser
anexados a um menu. Podemos usar um item de menu para executar alguma ação ou para gerir o
acionamento de um submenu, o qual fornece mais itens que estão relacionados por alguma
característica comum.
8.2 Eventos
Eventos são o resultado da interação do usuário com algum componente GUI. Mover o
mouse, clicá-lo, digitar num campo de texto, selecionar um item de menu, fechar uma janela, clicar
num botão, etc. são interações que enviam eventos para o programa, normalmente realizando
serviços. Eventos também podem ser gerados em resposta a modificações do ambiente, como por
exemplo, quando a janela de um applet é coberta por outra janela. Em outras palavras, define-se
eventos GUI como mensagens (chamadas a métodos) que indicam que o usuário do programa
interagiu com um dos componentes GUI.
8.2.1 Tratamento de Eventos
O mecanismo de tratamento de eventos compreende três partes: a origem, o objeto e o
ouvinte do evento.
8.2.1.1 A Origem do Evento
É o componente GUI em particular com o qual o usuário interage. ´
8.2.1.2 O Objeto Evento
Dada a interação com algum componente, um objeto evento é criado. Ele encapsula as
informações sobre o evento que ocorreu, incluindo uma referência para a origem e demais dados
necessários para que o ouvinte do evento o trate.
______________________________________________________________________________________________
Curso Técnico em Informática 106 Programação Java
8.2.1.3 Ouvinte do Evento
É um objeto de uma classe que implementa uma ou mais das interfaces listeners de eventos
dos pacotes java.awt.event e javax.swing.event. Ele é notificado da ocorrência de um evento e usa
o objeto evento que recebe para, de acordo com seus métodos de tratamento de eventos,
responder ao evento. Para isso o ouvinte deve ser registrado e implementar a interface
correspondente ao(s) evento(s) que deseja tratar. Cada fonte de eventos pode ter mais de um
ouvinte registrado. Analogamente, um ouvinte pode registrar múltiplas fontes de eventos.
Basicamente, quando ocorre um evento (pressionar um JButton, por exemplo), o
componente GUI com o qual o usuário interagiu notifica seus ouvintes registrados chamando o
método de tratamento de evento (como você verá é o ActionPerformed, nesse caso) apropriado de
cada ouvinte. Esse estilo de programação é conhecido como programação baseada em eventos.
8.2.2 Tratadores de Eventos ou Ouvintes (Listeners)
São objetos de qualquer classe que implemente uma interface específica para o tipo de
evento que se deseja tratar. Essa interface é definida para cada classe de eventos.
Para a classe de eventos java.awt.eventFocusEvent existe a interface
java.awt.eventFocusListener, por exemplo.
Vamos explorar esse assunto nestas próximas seções, descrevendo os métodos definidos
por cada interface e em decorrência de quais ações eles são chamados.
8.2.2.1 ActionListener
A partir dessa interface, instanciamos objetos que “sabem” tratar eventos de ação.
public void actionPerformed(ActionEvent)
Invocado quando clicamos em um botão, pressionamos Enter enquanto digitamos em um
campo de texto ou selecionamos um item de menu.
8.2.2.2 FocusListener
Trata de eventos de visibilidade, ou seja, quando o componente fica no foco de ação do
teclado (primeiro plano), ganhando ou perdendo habilidade de receber entradas do mesmo. Os
métodos recebem como argumento um objeto da classe FocusEvent.
public void focusGained(FocusEvent)
Chamado somente depois que o componente ganha o primeiro plano de ação.
public void focusLost(FocusEvent)
Chamado somente depois que o componente perde o foco de ação.
______________________________________________________________________________________________
Curso Técnico em Informática 107 Programação Java
8.2.2.3 ItemListener
Compreende eventos relativos a marcação, onde existe a possibilidade do estado
selecionado e não-selecionado. Por exemplo, as opções de JCheckBox, JCheckBoxItem e
JCombobox.
public itemStateChanged(ItemEvent) Invocado após o componente sofrer um mudança de
estado.
8.2.2.4 KeyListener
Aqui apresentaremos a interface listener de eventos KeyListener, que trata dos eventos de
pressionamento e liberação das teclas. Uma classe que implementa esta interface deve fornecer
definição para os métodos:
public void KeyPressed (KeyEvent) - Chamado quando se pressiona qualquer tecla.
public void KeyReleased (KeyEvent) - Chamado quando se libera qualquer tecla.
public void KeyTyped (KeyEvent) - Chamado quando se pressiona uma tecla de ação ( setas,
Home, End, Page Up, Page Down) ou de função (Num Lock, Caps Lock, Scroll Lock, Pause,
Print Screen).
8.2.2.5 MouseListener
Agora apresentaremos a interface listener de eventos MouseListener, que trata dos eventos
de pressionamento e liberação dos botões do mouse. Uma classe que implementa esta interface
deve fornecer definição para os métodos:
public void mousePressed(MouseEvent) - Chamado quando se pressiona um botão do
mouse com o cursor sobre um componente.
public void mouseClicked(MouseEvent) - Chamado quando se pressiona e libera-se um
botão do mouse sobre um componente, sem mover o cursor.
public void mouseReleased(MouseEvent) - Chamado quando se libera um botão do mouse
depois de ser pressionado. As chamadas para este método são enviadas para o ouvinte de
eventos do componente sobre o qual a operação de arrastar iniciou. Esse evento sempre é
precedido por um evento mousePressed.
public void mouseEntered(MouseEvent) - Chamado quando o cursor do mouse entra nos
limites de um componente.
public void mouseExited(MouseEvent) - Chamado quando o cursor do mouse sai dos limites
de um componente.
______________________________________________________________________________________________
Curso Técnico em Informática 108 Programação Java
8.2.2.6 MouseMotionListener
A interface listener de eventos MouseMotionListener trata dos eventos de “arrasto” do
mouse. Uma classe que implementa esta interface deve fornecer definição para os métodos:
public void mouseDragged(MouseEvent) - Chamado quando se pressiona o botão do mouse
com o cursor sobre um componente e se move o mouse. As chamadas para este método são
enviadas para o ouvinte de eventos do componente sobre o qual a operação de arrastar iniciou.
Esse evento é sempre precedido por uma chamada mousePressed.
public void mouseMoved(MouseEvent) - Chamado quando se move o mouse com o cursor
sobre um componente. Os eventos do mouse podem ser capturados por qualquer componente GUI
que se derive de java.awt.Component (painéis, botões, etc.), sendo que o componente deve ter um
objeto listener registrado. Todos esses métodos recebem um objeto MouseEvent como argumento,
o qual encapsula as informações sobre o evento que ocorreu, incluindo as coordenadas x e y da
posição em que o mesmo se verificou.
8.2.2.7 WindowListener
Todas as janelas geram eventos quando o usuário as manipula. Os ouvintes (listeners) de
eventos são registrados para tratar eventos de janela com o método
addWindowListener(WindowListener) da classe Window.
A interface WindowListener, que é implementada por ouvintes de eventos de janela, fornece
sete métodos para tratar esses eventos, Todos os métodos recebem um objeto da classe
WindowEvent. Vejamos eles:
public void windowActivated(WindowEvent) - Chamado quando o usuário torna uma janela
ativa.
public void windowClosed(WindowEvent) - Chamado depois que a janela é fechada.
public void windowClosing (WindowEvent) - Chamado quando o usuário inicia o fechamento
da janela.
public void windowDesactivated(WindowEvent) - Chamado quando o usuário torna outra
janela a ativa.
public void windowIconified(WindowEvent) - Chamado quando o usuário minimiza a janela.
public void windowDeiconified(WindowEvent) - Chamado quando o usuário restaura uma
janela minimiza.
public void windowOpened(WindowEvent) - Chamado quando uma janela é exibida pela
primeira vez na tela.
8.3 Classes Adaptadoras
A premissa de que uma classe implementa uma interface implica que o programador deverá
definir todos os métodos declarados nessa interface.
Porém, nem sempre é desejável definir todos os métodos. Podemos construir aplicações
que utilizem apenas o método tratador de eventos mouseClicked da interface MouseListener, por
exemplo. Para muitas das interfaces listeners que contém vários métodos, os pacotes
java.awt.event e javax.swing.event fornecem classes adaptadoras de ouvintes de eventos.
Essas classes implementam uma interface e fornecem cada método implementado com um
o corpo vazio. O programador pode criar uma classe que herde da classe adaptadora todos os
métodos com a implementação default (corpo vazio) e depois sobrescrever o(s) método(s)
______________________________________________________________________________________________
Curso Técnico em Informática 109 Programação Java
necessário(o) para o tratamento de eventos.
Vejamos as classes adaptadoras que implementam as respectivas interfaces:
8.4 JavaFX
8.4.1 Introdução
Em um mundo cada vez mais conectado, a Web tornou-se o principal canal de comunicação
e relacionamento. Os softwares começam a seguir a tendência de migrar para essa nova
plataforma, que elimina vários obstáculos, como a distância, e minimiza outros, como o tempo, por
exemplo. Contudo, ainda não se pode afirmar que a Web substitui completamente o Desktop, pois
sua usabilidade é menor.
Com base nisso e na nova tecnologia JavaFX tenta-se unir a dinamicidade da Web e o poder
do Desktop. Essa nova tecnologia usa a plataforma Java como base, o que faz com que sua
Runtime já esteja disponível em mais de 4,5 bilhões de computadores no mundo (SUN, 2009), além
da possibilidade de usar todo o código desenvolvido em Java e sua extensa biblioteca de códigos.
Entre as vantagens de migrar software para a Web, podem-se citar: acesso ao
programa/dados em qualquer lugar conectado à internet, facilidade no compartilhamento de
informações, facilidade na instalação e atualização de software, entre outras (MACORATTI, 2009).
Porém, a sua tecnologia padrão ((X)HTML) não oferece uma experiência de navegação e utilização
tão intuitiva como a que é conseguida em um sistema Desktop (MACORATTI, 2009).
Para suprir a lacuna, busca-se uma alternativa que una o melhor dos dois mundos (COSTA,
2008). As chamadas Rich Internet Applications tentam aproximar a experiência de navegação de
um usuário Web a um usuário Desktop.
8.4.2 Aplicação de internet rica (RICH INTERNET APPLICATION – RIA)
Primeiramente, deve-se descrever o que é o termo “Aplicação de Internet Rica”, em inglês,
Rich Internet Application (RIA). O termo RIA foi cunhado pela empresa Macromedia (incorporada
pela Adobe) para descrever aplicações que tenham características de software Desktop, mas
rodem na Web (ADOBE, 2009).
Algumas das características que permitem classificar um software como RIA são:
a) executar a aplicação em um navegador (lado cliente);
b) manter os dados no servidor de aplicações;
c) executar em uma sandbox.2;
______________________________________________________________________________________________
Curso Técnico em Informática 110 Programação Java
De acordo com Costa (2008), a experiência do usuário com o software é melhor em relação
ao usuário Web convencional, pois várias ações são feitas localmente, o que evita a troca de
informações entre cliente e servidor, tornando a aplicação mais rápida.
O termo riqueza, segundo Web Design Development India (2009), significa que as mídias
suportadas por uma aplicação dessa categoria são amplas e, de modo geral, para ser considerada
rica, a tecnologia deve suportar, entre outras mídias: animações, múltiplas fontes, conferência on-
line, gráficos vetoriais ou rasteirizados, áudio, vídeo e outros.
Segundo Macoratti (2009), o uso de aplicações RIA justifica-se em razão de que ao contrário
de uma aplicação Desktop, as RIAs não necessitam de instalação, sua atualização é feita no
servidor, novas versões são usadas automaticamente, a aplicação é acessível de qualquer
computador conectado à internet, ou seja, o usuário não fica preso a um computador apenas, pois
os dados estão na rede, independência de plataforma (sistema operacional e browser), menor
possibilidade de infecção de vírus nas aplicações, entre outras vantagens.
Podem-se citar vários exemplos de linguagens que permitem implementação RIA, as
principais são:
a) Javascript: foi a primeira linguagem que permitiu execução de código no lado do cliente e
que teve adoção maciça dos navegadores;
b) AJAX (Acrônimo para Asynchronous Javascript and XML) Javascript e XML assíncronos:
conjunto de tecnologias e técnicas que permitem criar aplicações ricas;
c) Adobe Flash, Adobe Flex, Adobe Air: Adobe Flash usa animações. O Adobe Flex cria
interfaces em flash compilando em XML, e o Adobe Air une HTML, Ajax, Flash e PDF;
d) Microsoft Silverlight: concorrente direto do flash, utiliza XML e é baseado na
plataforma .NET 3.0;
e) Applets Java: uma das primeiras aplicações do Java, um dos primeiros RIA, são pequenas
aplicações Java embutidas na página HTML;
f) Aplicativos Java: por meio do protocolo Java Web Start podem ser lançados via browser
aplicativos Java em todo o seu poder;
g) JavaFX: nova Tecnologia da Sun para aplicações RIA.
8.4.3 Sobre JAVAFX
De acordo com Doederlein (2009, p. 19), JavaFX Script é em parte declarativa, o que
significa que ela se preocupa em dizer o que fazer e não como fazer. É orientada a objetos, roda
na Máquina Virtual Java (JVM), utiliza Classes Java, tem tipagem estática.
JavaFX fornece um modelo unificado de desenvolvimento e implantação para a construção
de aplicações ricas que integram mídias, como áudio e vídeo, gráficos, texto rico e serviços Web.
JavaFX permite aos desenvolvedores de criação programarem em um contexto visual, assim,
ajudando-os a trazer suas ideias para a vida mais rápido e melhor.
JavaFX foi elaborado com o conceito de perfil comum, que conforme a Sun (2010), são
componentes reutilizáveis em todos dispositivos suportados, o que permite uma redução do
tamanho do núcleo da plataforma e consequentemente um reuso de APIs internas. Conforme Chen
(2008), nesse perfil, podemos destacar as seguintes características:
a) Apresentação gráfica: A apresentação gráfica representa a interface que será exibida pela
______________________________________________________________________________________________
Curso Técnico em Informática 111 Programação Java
aplicação. Dentre seus elementos destacam-se:
1. Formas geométricas;
2. Linhas;
3. Arcos;
4. Transparência;
5. Preenchimento de cores;
6. Textura;
7. Suporte à exibição em tela cheia;
8. Transformações tais como: girar, redimensionar e inclinar.
b) Apresentação textual: Refere-se ao modo como os textos da interface serão apresentados na
aplicação. Dentre seus elementos destacam-se:
1. Renderização de fontes;
2. Transformações tais como: girar, redimensionar e inclinar.
c) Animação: Permite a criação de forma fácil de conteúdo animado para as aplicações. Dentre
seus elementos destacam-se:
1. Animações tais como: rotação e aproximação;
2. Transições animadas entre componentes.
d) Áudio e vídeo: Compõe a camada de apresentação incorporada de vídeo e áudio. Dentre seus
elementos destacam-se:
1. Suporte a áudio e vídeo digitais;
2. Reprodução, pausa, pesquisa, volume e controle de velocidade;
3. Fluxo de mídia sobre HTTP com utilização de buffer.
Para permitir que o desenvolvedor não se preocupe com peculiaridades de cada dispositivo
suportado, foi desenvolvida uma linguagem de programação que é utilizada para a construção das
aplicações JavaFX. A linguagem JavaFX Script, é de acordo com a Sun Microsystem (2010) ”uma
linguagem de programação de script de alto desempenho que permite criar e disponibilizar a
próxima geração de aplicações avançadas de Internet para desktop, celulares e televisores.”.
8.4.4 Características
Podem-se enumerar várias características da linguagem JavaFX, como:
a) facilita a junção de áudio, vídeo, animação, gráficos e texto. Os gráficos em 2D podem
sofrer transformações em perspectiva 3D (gráficos 3D reais em breve);
b) aspectos da animação avançada incluem timeline, animação por keyframe, e animação
baseada em caminho;
c) pode-se reutilizar bibliotecas Java, o que preserva investimentos feitos nesta tecnologia;
d) instalação fácil;
______________________________________________________________________________________________
Curso Técnico em Informática 112 Programação Java
e) linguagem simples e declarativa;
f) É orientada a objetos;
g) É uma linguagem com estilo funcional, onde as funções podem ser atribuídas a variáveis;
h) É uma linguagem de expressão, ou seja, todo código JavaFX consiste de expressões;
i) É uma linguagem declarativa, o que é conveniente para o desenvolvimento das interfaces
para o usuário;
j) Possui a característica de ser uma linguagem que segue o raciocínio lógico, permitindo
assim a descrição mais fácil das interfaces para o usuário;
k) Permite, de forma simples a separação de modelos e visualizações das interfaces;
l) É uma linguagem fortemente tipada, com capacidades de inferência de tipo básico, ou
seja, o compilador identifica os tipos e reporta quaisquer erros;
m) O código JavaFX Script é compilado para classes Java;
n) Possui quatro tipos de dados: tipos primitivos, de vetores, de função e de classe.
As interfaces do JavaFX utilizam alguns componentes do Swing, interface gráfica padrão do
Java, porém de acordo com Giles (2010) “não é a intenção do JavaFX criar uma simples camada
sobre os componentes Swing/AWT, pois estes não são portáveis para celulares, dispositivos e
televisões, o qual faz parte dos planos do JavaFX.”. A figura abaixo ilustra as classes e camadas
que compõem a arquitetura JavaFX para ambientes desktop, além de demonstrar claramente a
próxima relação com as classes Java.
Ainda conforme Giles (2010), nessa arquitetura, destacam-se os seguintes componentes:
a) Stage: A classe Stage está no topo da hierarquia de interface do usuário para qualquer
aplicação JavaFX. Ela representa o ponto principal de início da aplicação;
b) Scene: Essa classe representa o segundo nível na hierarquia das classes nas aplicações
JavaFX. Ela contém todos os elementos da interface do usuário criada na aplicação, sendo
tais elementos denominados “nós gráficos”. As subclasses que herdam diretamente de
Scene, representam as características de apresentação da aplicação, em que na figura
acima são representadas por:
1. Effects: São efeitos de animação, tais como reflexão e brilho que foram criados
______________________________________________________________________________________________
Curso Técnico em Informática 113 Programação Java
para utilização de forma trivial por parte do desenvolvedor da aplicação;
2. Transitions: São efeitos de transição de componentes da aplicação que são
baseadas em tempo de exibição e permitem transições suaves;
3. Nodes: Em uma aplicação JavaFX, os nós são ditos como os elementos gráficos
da aplicação. A classe Node contém eventos relacionados ao mouse, cursores,
translação na tela por coordenadas;
4. Animation: Essa classe contém as funcionalidades que permitem uma aplicação
JavaFX prover conteúdo de animação, tais como transições por tempo,
rotacionamento.
8.4.5 À linguagem JavaFX script
Segundo Doederlein (2009, p. 19-20), JavaFX lembra bastante Java; pode-se ver em um
código-fonte com sintaxe e declarações conhecidas a um programador Java, como class, import,
package, delimitação de bloco por chaves, etc., porém sua API acrescenta novos termos e
conceitos que serão, posteriormente expostos, de forma resumida. Segundo Weawer et al. (2009,
p. 99), a metáfora do JavaFX é um teatro, há um palco (Stage) e, dentro desse palco, uma ou mais
cenas (Scene).
Segundo Doederlein (2009, p. 40), em um primeiro contato com o código JavaFX Script, um
programador Java5 logo percebe algumas diferenças, como a falta de uma declaração de classe,
e a definição de funções, variáveis e sentenças espalhadas pelo escopo global do Script; o return
é implícito na função; JavaFX utiliza sua própria sintaxe para instanciar novos objetos, chamada de
Objeto Literal, como se pode observar no exemplo abaixo.
nomeDaClasse{
propriedade1: valor
propriedade2: valor
}
Os iniciadores são separados por vírgula, ponto e vírgula ou espaços. As variáveis e constantes
são declaradas da maneira retratada no exemplo a seguir.
var valorInicial : Integer;
def constante : String = “valor”;
A figura abaixo ilustra uma exemplificação de código da linguagem JavaFX Script:
______________________________________________________________________________________________
Curso Técnico em Informática 114 Programação Java
Resultado:
O trecho de código ilustrado acima representa:
a) Linhas 1-9: Cria uma estrutura de diretório com nome “javafxapl”, indica as classes que são
dependências da aplicação e que necessitam fazer parte do escopo para execução normal da
aplicação;
b) Linha 11: Assim como na linguagem Java, nessa linha pode-se observar um comentário de final
de linha. Convém mencionar que o comentário do trecho de código (/* */) também é permitido;
c) Linha 12: É criada uma instância da classe Image que representa a imagem de fundo da
aplicação. A classe Image representa itens gráficos na aplicação e é utilizada para carregar
imagens de diretórios locais ou remotos;
d) Linha 14: É declarado um objeto do tipo Stage que é basicamente a interface de usuário das
aplicações JavaFX, completamente independente do dispositivo;
e) Linhas 15-17: São variáveis de instância que representam as características de largura, altura e
______________________________________________________________________________________________
Curso Técnico em Informática 115 Programação Java
título da aplicação, respectivamente;
f) Linha 18: Essa linha representa uma cena na aplicação, definida pela classe Scene. Essa classe
contém os elementos gráficos da aplicação e que serão apresentados na Stage, que representa
uma janela na aplicação;
g) Linhas 20-23: Esse trecho do código indica a imagem de fundo que será apresentada na
aplicação, sendo que a classe ImageView é utilizada para desenhar as imagens que são
representadas pela classe Image. Além disso, o caractere "[" indica o início de uma sequência
lógica de ações;
h) Linhas 24-30: Essa sequência, definida pela classe Text, exibe na janela da aplicação a palavra
JavaFX com uma fonte Monotype Corsiva em negrito e tamanho de 25 pixels. Além disso, o
caractere "]" indica o fim de uma sequência lógica que foi iniciada pelo caractere "[" na linha 15.
8.4.5.1 Tipos de variáveis
Tipos primitivos de JavaFX têm sempre uma classe de Base e valores-padrão para quando
uma variável é declarada sem um inicializador, não admitem null (exceto para tipos de Classe)
(WEAVER et al., 2009, p. 46), e são tipos de valor, ou seja, para comparar duas Strings, pode-se
usar o operador ==, diferentemente de Java, onde a comparação usando esse operador compararia
as referências ao objeto, em JavaFX é feita uma comparação de valores (DOEDERLEIN, 2009c).
a) Boolean – armazena os valores true ou false (ANDERSON; ANDERSON, 2009, p. 61), é
importante destacar que, diferentemente de Java, os operadores lógicos são escritos literalmente
como and, ore not (WEAVER et al., 2009, p. 47);
b) Integer – tem como Classe de base a classe java.lang.Integer, o valor padrão é 0;
c) Number – tem como classe de base a classe java.lang.Float, o valor padrão é 0.0;
d) String – tem como valor padrão uma String vazia, ou seja, “”. Como os outros tipos de valor,
String não aceita null. Pode ser usada tanto aspas duplas quanto aspas simples para delimitá-lo. A
concatenação de duas Strings em sequência é automática, sem o uso do caractere de soma (+),
ou de vírgula (,). Todos os métodos de java.lang.String, que é a classe de base de String podem
ser usados (WEAVER et al., 2009, p. 55).
e) Duration – é usado para representação de tempo, em animações; ele é criado com um Integer
ou number sucedido por uma unidade de tempo sem espaço entre eles (WEAVER et al., 2009, p.
57). Ao contrário dos outros tipos primitivos de JavaFX que têm classes base em java.lang.*, o tipo
Duration tem como classe base uma classe JavaFX, javafx.lang.Duration (WEAVER et al., 2009, p.
57).
f) Sequences – segundo Anderson e Anderson (2009, p. 21), são coleções de objetos que você
pode acessar sequencialmente. O valor padrão de uma sequence é uma sequence vazia, e o tipo
de uma sequence é o tipo dos seus elementos seguido por colchetes, um exemplo é Boolean[].
Não é possível ter elementos null no interior de uma sequence (WEAVER et al., 2009, p. 59).
8.4.5.2 Características especiais
a) Binding – uma das técnicas mais poderosas de JavaFX (ANDERSON; ANDERSON, 2009, p. 31)
é o recurso de Binding, em uma tradução livre, vinculação. Por meio da palavra-chave bind pode-
se vincular uma variável a outra variável, a uma expressão ou função. Quando você atualiza algum
valor da expressão a qual a variável foi vinculada, o valor do objeto dependente é atualizado, como
______________________________________________________________________________________________
Curso Técnico em Informática 116 Programação Java
é demonstrado abaixo:
var altura = 4;
var base = 3;
function calculaHipotenusa(base, altura){
return Math.sqrt(base*base + altura*altura);
};
var hipotenusa = bind calculaHipotenusa(base, altura);
println(hipotenusa);
base = 30;
println(hipotenusa);
altura = 40;
println(hipotenusa);
b) Expressões de Bloco – conforme Anderson e Anderson (2009, p. 50), JavaFX é uma linguagem
de expressão, o que significa que vários tipos de expressão em JavaFX retornam valores, que
podem ser usados, por exemplo, em uma atribuição. Uma Expressão de Bloco nada mais é do que
um conjunto de expressões delimitadas por colchetes ({ }). O tipo e o valor do retorno são o tipo e
o valor da última expressão do bloco.
c) Expressão IF – também retorna valor, então pode-se associar o resultado de uma expressão if
a uma variável, o retorno da expressão if é do mesmo tipo e valor do retorno da expressão then ou
else, por exemplo;
d) Expressão for – é usada para fazer alguma ação em um determinado número de vezes. Ele
retorna uma sequence formada pelos retornos de cada iteração, essa sequence pode ser
armazenada em uma variável, como se nota na figura abaixo;
var nomeDasPessoas = for (pessoa in pessoas){
“{pessoa.nome} {pessoa.sobrenome}”;
}
e) Expressões while – não retornam valor, elas atuam e têm sintaxe exatamente como no Java;
palavra-chave while, seguida de uma expressão booleana entre parênteses e um bloco para ser
executado enquanto a condição retornar true;
f) Funções – funções em JavaFX são criadas pela palavra-chave function, seguida do nome da
função e de parênteses que delimitam os parâmetros que porventura existam, e, por último, um
bloco delimitado por chaves;
g) Triggers – segundo Weaver et al. (2009, p. 215) as triggers são uma parte opcional de uma
declaração de variável. Ela é caracterizada pelo uso das palavras-chave on replace seguidas de
um bloco de código a ser executado sempre que a variável mudar;
h) Event Handlers – os Nodes de JavaFX contêm variáveis que armazenam funções que são
chamadas quando determinado evento acontece, exemplos de event handlers são:
onMousePressed, onKeyTyped, onMouseEntered.
______________________________________________________________________________________________
Curso Técnico em Informática 117 Programação Java
8.4.5.3 Ambiente web
Durante a década de 90 a tecnologia de Java Applets demonstrava todo potencial no
desenvolvimento de aplicativos que poderiam ser executados diretamente nos navegadores web.
Devido à complexidade, falta de produtividade e escassez de boas ferramentas, a utilização dessa
tecnologia se tornou menos frequente. O avanço no desenvolvimento dos navegadores web e a
concepção do conceito de aplicações ricas para Internet permitiram novos investimentos nessa
área e conforme a Sun (2010), por volta de dezembro de 2008, foi demonstrado a primeira versão
de JavaFX, que tem como objetivo revigorar a plataforma Java no desenvolvimento de aplicativos
com execução do lado do cliente.
O JavaFX foi elaborado para permitir que uma aplicação seja executada em diferentes
ambientes com o mínimo de modificação. Uma aplicação JavaFX desenvolvida para ser executada
dentro do navegador web, necessita da criação de um arquivo JNLP (Java Network Launching
Protocol) e a inserção de uma chamada a aplicação no código HTML (HyperText Markup
Language). A abaixo demonstra um código JavaFX Applet.
O trecho de código ilustrado na acima representa:
a) Linhas 1-5: O trecho de código define o início da linguagem de marcação HTML que possibilitará
a inserção direta do código JavaScript;
b) Linha 6: O arquivo JavaScript “dtfx.js” contém definições para verificar automaticamente
atualizações e geração da tag “<APPLET>”;
c) Linhas 7-17: O código exposto define a configuração da aplicação no navegador web. Nesse
caso, será exibido uma aplicação que possui 200 pixels de altura e 350 pixels de largura, e o início
da aplicação é configurado para o método principal da classe "MeuAplicativo".
O princípio proposto pela plataforma JavaFX é que a aplicação possa ser executada de
forma transparente em todos ambientes. No entanto torna-se evidente que a forma de distribuição
da aplicação deve ser adaptada ao perfil em que será executada. Conforme apresentado nessa
subseção, a aplicação JavaFX para web necessita de uma adaptação na forma de distribuição, que
é resolvido através da utilização do JWS.
______________________________________________________________________________________________
Curso Técnico em Informática 118 Programação Java
8.4.5.4 A aplicação JXplayer
A plataforma JavaFX fornece toda infra-estrutura tecnológica para o desenvolvimento de
aplicações RIA complexas por meio de componentes integrados e simples de usar. Como forma de
verificar a produtividade no desenvolvimento de aplicações JavaFX, foi elaborado um exemplo
funcional, denominado JXPlayer, que tem o intuito de apresentar algumas características da
plataforma.
8.4.5.4.1 Características da aplicação JXPlayer
A aplicação JXPlayer foi desenvolvida para demonstrar que funcionalidades complexas em
outras linguagens, são construídas de forma simples em JavaFX. As funcionalidades da aplicação
são:
Suporte à áudio/vídeo local e remoto (streaming);
Controles de reprodução de áudio/vídeo (avançar/retroceder reprodução, diminuir/aumentar
volume, interromper/finalizar reprodução);
Suporte à aplicação de efeitos em fotos;
Execução de tarefas em segundo plano, por exemplo, escutar música enquanto manipulo
uma foto;
Efeitos de transição entre as telas;
Efeito de ofuscamento de imagem durante reprodução de uma música;
Barras de progressão de áudio e vídeo;
Controles de interfaces com efeitos gráficos.
A figura abaixo ilustra a tela principal da aplicação.
8.4.5.4.2 Ferramentas de apoio ao desenvolvimento
A interface e funcionalidades da aplicação JXPlayer foram desenvolvidas no IDE NetBeans
2008 com o plugin JavaFX Composer 1.10.3. Conforme a Sun Microsystems (2010), JavaFX
Composer é um plugin para o NetBeans que fornece uma infra-estrutura integrada e um ambiente
______________________________________________________________________________________________
Curso Técnico em Informática 119 Programação Java
visual no desenvolvimento das aplicações JavaFX.
A utilização de técnicas de drag-and-drop5 providas pelo ambiente de desenvolvimento
possibilitou uma redução no tempo dedicado a criação da interface gráfica e formatação dos
componentes visuais em tela. Internamente, o plugin gera os códigos necessários para apresentar
os componentes e restringe as alterações apenas para o modo visual no NetBeans. Com isso, as
características dos componentes terão o comportamento e forma definidos pelas funcionalidades
implementadas no plugin, o que muitas das vezes não é suficiente.
Apesar de auxiliar e automatizar a utilização de vários componentes no desenvolvimento do
JXPlayer, o plugin apresentou instabilidade e comportamentos incoerentes. Por exemplo, uma
simples modificação de aparência (alteração de uma Fonte) de um menu impossibilitou toda a
aplicação de ser executada.
O plugin JavaFX Composer fornece uma forma visual e amigável no desenvolvimento de
aplicações JavaFX, que agiliza a criação e integração dos componentes visuais do JavaFX na tela
da aplicação. No entanto, sua instabilidade e rigidez no gerenciamento do código fonte, podem
impedir que ele seja adotado como uma ferramenta principal na elaboração de aplicações JavaFX
mais complexas.
8.4.6 Interface e efeitos gráficos
Conforme mencionado na subseção anterior, as ferramentas de apoio ao desenvolvimento
NetBeans e JavaFX Composer ofereceram a infra-estrutura básica na criação das interfaces
gráficas da aplicação. Como a plataforma JavaFX provê APIs específicas e bem estruturadas para
efeitos e transições, a implementação desses recursos na aplicação foi simples e com poucas
linhas de código. A simplicidade do uso foi devido à utilização da palavra chave bind, que conforme
Weaver (2010) é um arranjo dinâmico que normalmente está associado a uma variável e reflete
suas atualizações. Um exemplo da versatilidade do bind utilizado na aplicação é a redução
dinâmica do brilho e contraste de uma imagem quando uma música está sendo reproduzida.
A criação de interfaces em JavaFX é feita de forma simples e declarativa, portanto não houve
grandes obstáculos na elaboração da parte gráfica da aplicação.
Porém, a utilização do JavaFX Composer restringiu a modelagem dos componentes gráficos
e inviabilizou o desenvolvimento de um aplicativo mais rico em detalhes visuais.
8.4.7 Suporte a áudio e vídeo
Uma parte do escopo da aplicação JXPlayer é permitir que arquivos de mídia possam ser
executados de forma transparente, seja de origem local ou remota (Internet). O JavaFX permitiu
que essas funcionalidades fossem incorporadas a aplicação de forma trivial e rápida, por meio de
sua API de mídia. Contudo, para o diálogo de seleção de arquivos locais, foi necessário utilizar um
componente do Swing, interface gráfica nativa do Java, pois não existe a funcionalidade como
recurso nativo do JavaFX. Isso demonstra que alguns componentes essenciais, por exemplo um
componente de seleção de arquivos, ainda precisam ser incorporados ao JavaFX, além de
demonstrar também a integração com a plataforma Java, pois foi possível utilizar classes nativas
do Java na aplicação.
As classes do JavaFX abstraem toda complexidade na reprodução de arquivos de mídia e
oferecem suporte a vários tipos de arquivos. Incorporar na aplicação a funcionalidade de
5 Conforme a Adobe (2010), drag and drop é a ação de “arrastar e soltar” determinado conteúdo em outro destino.
______________________________________________________________________________________________
Curso Técnico em Informática 120 Programação Java
reprodução de mídias locais e remotas foi trivial, porém a alternância da origem dos arquivos foi
onerosa porque mesmo modificando no objeto da classe a localização da mídia, o arquivo
permanecia o mesmo. A solução encontrada foi utilizar o recurso bind para gerar uma classe
dinâmica associada ao componente de mídia do JavaFX.
As ferramentas de produtividade, NetBeans e JavaFX Composer, e a variedade de APIs
públicas do JavaFX, auxiliaram o desenvolvimento da aplicação JXPlayer e possibilitaram
incorporar funcionalidades que seriam muito complexas de serem agregadas caso fosse necessário
desenvolvê-las por completo. No entanto, a restrição e falta de implementação de alguns
componentes indicam que é necessário um prévio conhecimento da plataforma Java para elaborar
soluções que não estejam nativamente incorporadas ao JavaFX.
Expressão regular é um método formal de se especificar um padrão de texto. É uma
composição de símbolos, caracteres com funções especiais, que agrupados entre si e com
caracteres literais, formam uma sequência, uma expressão.
Uma expressão é interpretada como uma regra, que indica sucesso se uma entrada de
dados qualquer casar com essa regra.
Os símbolos que compõem uma expressão regular (ER), são chamados de meta caracteres,
pois possuem funções especiais.
As ERs servem para dizer algo abrangente de forma especifica. Tal como determinar uma
lista finita de possibilidades de ocorrência de determinados caracteres em uma palavra.
Ex: [rgp]ato → Aceita resultados como rato, pato e gato. Abrange especificamente estas 3 palavras
e mais nada.
Metacaractere Mnemônico
. Ponto
[ ] Lista
[^] Lista negada
? Opcional
* Asterisco
+ Mais
{} Chaves
^ Circunflexo
$ Cifrão
\b Borda
\ Escape
| Ou
Expressões Regulares - Java 9
______________________________________________________________________________________________
Curso Técnico em Informática 121 Programação Java
() Grupo
\1 Retrovisor
Os metacaracteres estão divididos em 4 grupos distintos de acordo com características
comuns entre eles.
Representantes
Meta
caractere
Mnomônico Função
. Ponto Um caractere
qualquer
[...] Lista Lista de caracteres
permitidos
[^...] Lista negada Lista de caracteres
proibidos
Quantificadores
Meta caractere Mnomônico Função
? Opcional Zero ou um
* Asterisco Zero, um ou mais
+ Mais Um ou mais
{n,m} Chaves De n até m
Âncoras
Meta caractere Mnomônico Função
^ Circunflexo Inicio da linha
$ Cifrão Fim da linha
\b Borda Início ou fim da palavra
Outros
Meta caractere Mnomônico Função
\c Escape Torna literal o caractere c
| Ou Ou um ou outro
(…) Grupo Delimita um grupo
\1…\9 Retrovisor Texto casado nos grupos 1..9
______________________________________________________________________________________________
Curso Técnico em Informática 122 Programação Java
Exemplos:
Expressão Casa com
n[ãa]o Não, nao
[Tt]eclado Teclado, teclado
e[sx]tendido estendido, extendido
<[BIP]> <B>, <I>,<P>
b[ip]+ Bi, bip, biipp,bpipipi, biip, bppp, …
9.1 ERs em Java
Java dispõe de mecanismos muito bons para o tratamento de expressões regulares no
pacote java.util.regex. Para um melhor aproveitamento, é aconselhável o estudo da
documentação deste pacote disponível em:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/package-summary.html[/url]
Um objeto da classe Pattern contém a expressão regular desejada que será usada em uma
comparação. Já um objeto da classe Matcher contém os métodos que validarão nossa String, dada
uma expressão regular.
Exemplo:
Pattern padrao = Pattern.compile(“Java*”);
Matcher pesquisa = padrao.matcher(“JavaFree”);
if (pesquisa.matches())
{
System.out.println(“JavaFree Rox”);
}
else
{
System.out.println(“Inconpativel”);
}
O exemplo acima poderia, ainda, ser feito somente com o uso do método boolean
matches (String regex, CharSequence entrada) da classe Pattern, da seguinte
forma:
if (Pattern.matches(“Java*”, “JavaFree”))
{
System.out.println(“JavaFree Rox”);
}
else
{
System.out.println(“Incompativel”);
}
______________________________________________________________________________________________
Curso Técnico em Informática 123 Programação Java
Estes exemplos mostram que é bem fácil trabalhar com expressões regulares em Java.
Exemplo: Validar um Endereço de Email
Fica bem simples, agora, validar um endereço de email (ou outro dado qualquer).
/* Exemplo prático
* Verifica se um endereço de email é válido
* Compilar: javac ValidarEmail.java
* Executar: java ValidarEmail [email protected]
*/
// ————————————————————— classes nativas
import java.util.regex.*;
// ————————————————————— nossa classe
class ValidarEmail
{
public static void main (String[] args)
{
if (args.length < 1) // Falta argumentos de execução
{
System.out.println(“Uso: java ValidarEmail <[email protected]>”);
}
else
{
// Email válido é na forma [email protected] , [email protected], etc. // Tente fazer um expressão mais restringente Pattern padrao = Pattern.compile(“.+@.+\.[a-z]+”); Matcher pesquisa = padrao.matcher(args[0]); if (pesquisa.matches()) { System.out.println(“O email ” + args[0] + ” eh valido!”); } else { System.out.println(“O email ” + args[0] + ” nao eh valido!”); } } }//end main() }//ValidarEmail.class
Vale sempre estudar a documentação das classes. O exemplo dado aqui é bem trivial,
existem outros métodos com outras funcionalidade muito interessantes neste pacote.
______________________________________________________________________________________________
Curso Técnico em Informática 124 Programação Java
Nesta seção será visto como tratar exceções na linguagem Java, entendendo a teoria de
funcionamento desse tipo de estrutura, passando pelos comandos de tratamento e captura até a
customização de exceções para fins específicos.
Quando se cria programas de computador em Java, há possibilidade de ocorrer erros
imprevistos durante sua execução, esses erros são conhecidos como exceções e podem ser
provenientes de erros de lógica ou acesso a dispositivos ou arquivos externos.
10.1 Entendendo as exceções
As exceções ocorrem quando algo imprevisto acontece, elas podem ser provenientes de
erros de lógica ou acesso a recursos que talvez não estejam disponíveis.
Alguns possíveis motivos externos para ocorrer uma exceção são:
Tentar abrir um arquivo que não existe;
Tentar fazer consulta a um banco de dados que não está disponível;
Tentar escrever algo em um arquivo sobre o qual não se tem permissão de escrita;
Tentar conectar em servidor inexistente.
Alguns possíveis erros de lógica para ocorrer uma exceção são:
Tentar manipular um objeto que está com o valor nulo;
Dividir um número por zero;
Tentar manipular um tipo de dado como se fosse outro;
Tentar utilizar um método ou classe não existentes.
Uma forma de tentar contornar esses imprevistos é realizar o tratamento dos locais no código
que podem vir a lançar possíveis exceções, como por exemplo, campo de consulta a banco de
dados, locais em que há divisões, consulta a arquivos de propriedades ou arquivos dentro do
próprio computador.
Para tratar as exceções em Java são utilizados os comandos try e catch.
Sintaxe:
try
{
//trecho de código que pode vir a lançar uma exceção
}
catch(tipo_exceçao_1 e)
{
//ação a ser tomada
}
catch(tipo_exceçao_2 e)
{
//ação a ser tomada
Tratando exceções em Java 10
______________________________________________________________________________________________
Curso Técnico em Informática 125 Programação Java
}
catch(tipo_exceçao_n e)
{
//ação a ser tomada
}
Onde:
try{ … } - Neste bloco são introduzidas todas as linhas de código que podem vir a lançar
uma exceção.
catch(tipo_excessao e) { … } - Neste bloco é descrita a ação que ocorrerá quando a
exceção for capturada.
Tomando como exemplo uma classe que tem um método principal main que tem como seu único
objetivo alterar todas as letras de um frase para maiúsculas utilizando o método toUpperCase() da
classe String, caso a frase esteja nula e se tente usar o método toUpperCase() na mesma será
lançada uma exceção de NullPointerException.
Primeiro vamos ver como ficaria a tal classe sem a utilização do try/catch.
public class aumentaFrase {
public static void main(String args[])
{
String frase = null;
String novaFrase = null;
novaFrase = frase.toUpperCase();
System.out.println("Frase antiga: "+frase);
System.out.println("Frase nova: "+novaFrase);
}
}
Quando este código for executado, o mesmo lançará uma NullPointerException, como poder ser
visto na saída do console quando executamos tal programa.
Exception in thread "main" java.lang.NullPointerException
at aumentaFrase.main(aumentaFrase.java:15)
Ou seja, o mesmo tentou acessar um atributo de um objeto que estava nulo. Para ajudar a melhorar
a situação, deve-se usar o try/catch.
Reformulação do código com try-catch
public static void main(String args[])
{
String frase = null;
String novaFrase = null;
try
{
novaFrase = frase.toUpperCase();
______________________________________________________________________________________________
Curso Técnico em Informática 126 Programação Java
}
catch(NullPointerException e) //Captura da possível exceção.
{
//Tratamento da exceção
System.out.println("A fase inicial está nula, para solucionar tal problema, foi lhe
atribuído um valor default.");
frase = "Frase vazia";
novaFrase = frase.toUpperCase();
}
System.out.println("Frase antiga: "+frase);
System.out.println("Frase nova: "+novaFrase);
}
Quando este código for executado, o mesmo lançará uma NullPointerException, porém esta
exceção será tratada desta vez, sendo a mesma capturada pelo catch{} e dentro deste bloco as
devidas providências são tomadas. Neste caso é atribuído um valor default à variável frase. A saída
deste programa seria a seguinte:
Saída do programa reformulado:
array4
Imagine a seguinte situação: foi aberta uma conexão com o banco de dados para realizar
determinada ação, e no meio deste processo seja lançada alguma exceção, como por exemplo,
NullPointerException ao tentar manipular um determinado atributo de um objeto. Neste caso seria
necessário que mesmo sendo lançada uma exceção no meio do processo a conexão fosse
fechada. Um outro exemplo bom seria a abertura de determinado arquivo para escrita no mesmo,
e no meio deste processo é lançada uma exceção por algum motivo, o arquivo não seria fechado,
o que resultaria em deixar o arquivo aberto.
Quando uma exceção é lançada e é necessário que determinada ação seja tomada mesmo
após a sua captura, utilizamos a palavra reservada finally.
Sintaxe de uso do bloco finally
try
{
//trecho de código que pode vir a lançar uma exceção
}
catch(tipo_exceçao_1 e)
{
//ação a ser tomada
}
catch(tipo_exceçao_2 e)
{
//ação a ser tomada
}
catch(tipo_exceçao _n e)
{
______________________________________________________________________________________________
Curso Técnico em Informática 127 Programação Java
//ação a ser tomada
}
finally
{
//ação a ser tomada
}
Programa aumetaFrase com bloco finally
public class aumentaFrase {
public static void main(String args[])
{
String frase = null;
String novaFrase = null;
try
{
novaFrase = frase.toUpperCase();
}
catch(NullPointerException e)
{
System.out.println("A frase inicial está nula, para solucionar tal problema, foi
lhe atribuído um valor default.");
frase = "Frase vazia";
}
finally
{
novaFrase = frase.toUpperCase();
}
System.out.println("Frase antiga: "+frase);
System.out.println("Frase nova: "+novaFrase);
}
}
Quando este código fosse executado, o mesmo lançaria uma NullPointerException, porém
esta exceção será tratada desta vez, sendo a mesma capturada pelo catch{} e dentro deste bloco
as devidas providências são tomadas. Neste caso é atribuído um valor default à variável frase.
Neste exemplo, mesmo o código lançando uma exceção durante a sua execução e a mesma sendo
capturada pelo catch, uma determinada ação será tomada no bloco finally, neste caso tanto com a
exceção ou não será executada a linha “ novaFrase = frase.toUpperCase();”, tornando todas letras
da frase maiúsculas. A saída deste programa seria a seguinte:
Saída do programa com bloco finally
array4
Utilizando como exemplo uma situação em que não é desejado que uma exceção seja tratada na
própria classe ou método, mas sim em outro que venha lhe chamar. Para solucionar tal situação
utilizamos o comando throws na assinatura do método com a possível exceção que o mesmo
______________________________________________________________________________________________
Curso Técnico em Informática 128 Programação Java
poderá a vir lançar.
Sintaxe de declaração de método com definição de exceções
tipo_retorno nome_metodo() throws tipo_exceção_1, tipo_exceção_2, tipo_exceção_n
{
…
}
Onde:
tipo_retorno – Tipo de retorno do método.
nome_metodo() - Nome do método que será utilizado.
tipo_exceção_1 a tipo_exceção_n – Tipo de exceções separadas por virgula que o seu
método pode vir a lançar.
Definição de exceções que um método pode gerar
public class TesteString {
private static void aumentarLetras() throws NullPointerException //lançando excessão
{
String frase = null;
String novaFrase = null;
novaFrase = frase.toUpperCase();
System.out.println("Frase antiga: "+frase);
System.out.println("Frase nova: "+novaFrase);
}
public static void main(String args[])
{
try
{
aumentarLetras();
}
catch(NullPointerException e)
{
System.out.println("Ocorreu um NullPointerException ao executar o método
aumentarLetras() "+e);
}
}
}
Neste exemplo será lançada uma exceção no método aumetarLetras():
Definição da exceção gerada pelo método aumentarLetras
private static void aumentarLetras() throws NullPointerException
______________________________________________________________________________________________
Curso Técnico em Informática 129 Programação Java
E o mesmo será tratado no método main().
Aplicação da exceção definida
...
try
{
aumentarLetras();
}
catch(NullPointerException e)
{
System.out.println("Ocorreu um NullPointerException ao executar o método
aumentarLetras() "+e);
}
…
Saída do programa atualizado
Ocorreu um NullPointerException ao executar o método aumentarLetras()
java.lang.NullPointerException.
Agora imagine o caso em que seja necessário lançar uma exceção padrão ao invés de uma
especifica. Para resolver este problema, utilizamos o comando throw dentro do bloco catch que
desejamos converter a exceção.
Sintaxe de uso do comando throw:
try
{
//…
}
catch(tipoExcessão_1 e)
{
throw new novoTipoExceçao(e);
}
Onde:
tipoExcessão_1 e – Tipo de exceção que pode ser capturada pelo bloco catch.
NovoTipoExceçao – Tipo de exceção que será lançada.
Exemplo de uso do comando throw:
public class TesteString {
private static void aumentarLetras() throws Exception //lançando exceção
{
String frase = null;
String novaFrase = null;
try
{
novaFrase = frase.toUpperCase();
______________________________________________________________________________________________
Curso Técnico em Informática 130 Programação Java
}
catch(NullPointerException e)
{
throw new Exception(e);
}
System.out.println("Frase antiga: "+frase);
System.out.println("Frase nova: "+novaFrase);
}
public static void main(String args[])
{
try
{
aumentarLetras();
}
catch(Exception e)
{
System.out.println("Ocorreu uma exceão ao executar o método
aumentarLetras() "+e);
}
}
}
Neste exemplo será lançada uma NullPointerException e a mesma será convertida para
Exception e relançada como Exception no método aumentarLetras() e, por fim, a mesma é tratada
no método main().
Saída do programa atualizada
Ocorreu uma exceção ao executar o método aumentarLetras() java.lang.Exception:
java.lang.NullPointerException
Assim como qualquer objeto, em Java também é possível criar suas próprias exceções.
Imagine um cenário em que nenhuma exceção existente faça sentido para ser lançada por você.
Por exemplo, imagine que por algum motivo você precisa que uma exceção seja lançada
quando a letra “B” ou “b” não existe e determinada frase, como não existe nenhuma exceção
específica para este caso será necessário criar uma exceção.
Criando uma exceção para ser lançada toda vez que uma letra “B” ou “B” não é encontrada em
uma determinada frase.
Exemplo de exceção customizada:
public class SemLetraBException extends Exception {
@Override
public String getMessage(){
return "Não existe letra B em sua frase";
}
}
Toda exceção criada deve estender Exception, neste exemplo foi sobrescrito o método
______________________________________________________________________________________________
Curso Técnico em Informática 131 Programação Java
getMessage(), que é exibida no prompt toda vez que a exceção é lançada.
A seguir é apresentado um exemplo que utilizada a exceção criada anteriormente.
Utilizando a exceção customizada:
public class TesteExcecao {
public static void main(String args[]) throws SemLetraBException
{
String frase = "Sou um teste!";
if(!frase.contains("b") || !frase.contains("B"))
throw new SemLetraBException();
}
}
Quando o programa acima fosse executado, uma exceção do tipo SemLetraBException() seria
lançada. Abaixo está a saída exibida no prompt:
Saída do método com a mensagem da exceção customizada:
Exception in thread "main" SemLetraBException: Não existe letra B ou b em sua frase at
TesteExcecao.main(TesteExcecao.java:8)
O tratamento de exceções em Java pode ser considerado bem simples e sua manipulação
pode ser feita de acordo com o que o programador deseja, desde tratá-la no próprio método ou
lança-la para ser tratada em um método que venha chamar o método que lança a exceção.
Muitos sistemas precisam manter as informações com as quais eles trabalham, seja para
permitir consultas futuras, geração de relatórios ou possíveis alterações nas informações. Para que
esses dados sejam mantidos para sempre, esses sistemas geralmente guardam essas informações
em um banco de dados, que as mantém de forma organizada e prontas para consultas.
A maioria dos bancos de dados comerciais são os chamados relacionais, que é uma forma
de trabalhar e pensar diferente ao paradigma orientado a objetos.
O MySQL é o banco de dados que usaremos durante o curso. É um dos mais importantes
bancos de dados relacionais, e é gratuito, além de ter uma instalação fácil para todos os sistemas
operacionais.
O processo de armazenamento de dados é também chamado de persistência. A biblioteca
de persistência em banco de dados relacionais do Java é chamada JDBC, e também existem
diversas ferramentas do tipo ORM (Object Relational Mapping) que facilitam bastante o uso do
JDBC. Neste momento, neste momento o foco esta nos conceitos e no uso do JDBC.
Conectar-se a um banco de dados com Java é feito de maneira elegante. Para evitar que
cada banco tenha a sua própria API e conjunto de classes e métodos, há um único conjunto de
interfaces muito bem definidas que devem ser implementadas. Esse conjunto de interfaces fica
dentro do pacote java.sql e referenciar como JDBC.
Conexão com banco de dados 11
______________________________________________________________________________________________
Curso Técnico em Informática 132 Programação Java
Entre as diversas interfaces deste pacote, existe a interface Connection que define métodos
para executar uma query (como um insert e select), comitar transação e fechar a conexão, entre
outros. Caso queiramos trabalhar com o MySQL, precisamos de classes concretas que
implementem essas interfaces do pacote java.sql.
Esse conjunto de classes concretas é quem fará a ponte entre o código cliente que usa a
API JDBC e o banco de dados. São essas classes que sabem se comunicar através do protocolo
proprietário do banco de dados. Esse conjunto de classes recebe o nome de driver. Todos os
principais bancos de dados do mercado possuem drivers JDBC para que você possa utilizá-los com
Java. O nome driver é análogo ao que usamos para impressoras: como é impossível que um
sistema operacional saiba conversar com todo tipo de impressora existente, precisamos de um
driver que faça o papel de "tradutor" dessa conversa.
Para abrir uma conexão com um banco de dados, é necessário utilizar sempre um driver. A
classe DriverManager é a responsável por se comunicar com todos os drivers que que estão
disponíveis. Para isso, invocamos o método estático getConnection com uma String que indica a
qual banco será estabelecida a conexão.
Essa String - chamada de String de conexão JDBC - que será utilizada para acessar o
MySQL tem sempre a seguinte forma:
jdbc:mysql://ip/nome_do_banco
o ip deve ser substituído pelo IP da máquina do servidor e nome_do_banco pelo nome do banco
de dados a ser utilizado.
Seguindo o exemplo da linha acima e tudo que foi dito até agora, seria possível rodar o
exemplo abaixo e receber uma conexão para um banco MySQL, caso ele esteja rodando na mesma
máquina:
public class JDBCExemplo {
public static void main(String[] args) throws SQLException {
Connection conexao = DriverManager.getConnection(
"jdbc:mysql://localhost/fj21");
System.out.println("Conectado!");
______________________________________________________________________________________________
Curso Técnico em Informática 133 Programação Java
conexao.close();
}
}
Repare que estamos deixando passar a SQLException, que é uma exceptionchecked,
lançada por muitos dos métodos da API de JDBC. Numa aplicação real devemos
utilizar try/catch nos lugares que julgamos haver possibilidade de recuperar de uma falha com o
banco de dados. Também precisamos tomar sempre cuidado para fechar todas as conexões que
foram abertas.
Ao testar o código acima, recebemos uma exception. A conexão não pôde ser aberta. Recebemos
a mensagem:
java.sql.SQLException: No suitable driver found for
jdbc:mysql://localhost/fj21
O sistema ainda não achou uma implementação de driver JDBC que pode ser usada para abrir a
conexão indicada pela URL jdbc:mysql://localhost/fj21.
O que precisamos fazer é adicionar o driver do MySQL ao classpath, o arquivo.jar contendo
a implementação JDBC do MySQL (mysql connector) precisa ser colocado em um lugar visível pelo
seu projeto ou adicionado à variável de ambiente CLASSPATH. Como usaremos o Eclipse, fazemos
isso através de um clique da direita em nosso projeto, Properties/Java Build Path e
em Librariesadicionamos o jar do driver JDBC do MySQL. Veremos isto passo a passo nos
exercícios.
Teoricamente, basta alterar as duas Strings que escrevemos para mudar de um banco para
outro. Porém, não é tudo tão simples assim! O código SQL que veremos a seguir pode funcionar
em um banco e não em outros. Depende de quão aderente ao padrão ANSI SQL é seu banco de
dados.
Isso só causa dor de cabeça e existem projetos que resolvem isso, como é o caso do
Hibernate (www.hibernate.org) e da especificação JPA (Java Persistence API). Veremos um pouco
do Hibernate ao final desse curso e bastante sobre ele no FJ-25.
11.1 Drivers de outros bancos de dados
Os drivers podem ser baixados normalmente no site do fabricante do banco de dados. Alguns
casos, como no Microsoft SQL Server, existem outros grupos que desenvolvem o driver
em http://jtds.sourceforge.net . Enquanto isso, você pode achar o driver do MYSQL (chamado
de mysql connector) no sitehttp://www.mysql.org.
11.2 Fábrica de Conexões
Em determinado momento de nossa aplicação, gostaríamos de ter o controle sobre a
construção dos objetos da nossa classe. Muito pode ser feito através do construtor, como saber
quantos objetos foram instanciados ou fazer o log sobre essas instanciações.
Às vezes, também queremos controlar um processo muito repetitivo e trabalhoso, como abrir
uma conexão com o banco de dados. Tomemos como exemplo a classe a seguir que seria
responsável por abrir uma conexão com o banco:
public class ConnectionFactory {
______________________________________________________________________________________________
Curso Técnico em Informática 134 Programação Java
public Connection getConnection() {
try {
return DriverManager.getConnection(
"jdbc:mysql://localhost/fj21", "root", "");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Poderíamos colocar um aviso na nossa aplicação, notificando todos os programadores a adquirir
uma conexão:
Connection con = new ConnectionFactory().getConnection();
Note que o método getConnection() é uma fábrica de conexões, isto é, ele cria novas conexões
para nós. Basta invocar o método e recebemos uma conexão pronta para uso, não importando de
onde elas vieram e eventuais detalhes de criação. Portanto, vamos chamar a classe
de ConnectionFactory e o método degetConnection.
Encapsulando dessa forma, podemos mais tarde mudar a obtenção de conexões, para, por
exemplo, usar um mecanismo de pooling, que é fortemente recomendável em uma aplicação real.
O Java Persistence API é um framework para camada de persistência dos dados, que
fornece uma camada de comunicação entre a aplicação escrita em Java e o banco de dados.
Algumas facilidades que o JPA oferece são:
Conversão de registros do banco de dados em objetos Java;
Não necessita criar códigos SQL para salvar, alterar ou remover registros do banco de da-
dos;
A aplicação não fica presa a um banco de dados sendo simples a troca.
Além disso, aumenta a produtividade dos desenvolvedores que utilizam o banco de dados,
Java Persistence API - JPA
12
______________________________________________________________________________________________
Curso Técnico em Informática 135 Programação Java
deixando de forma transparente a sua utilização, principalmente por não deixar a programação
Java vinculada a um tipo específico de banco de dados.
Para trazer as informações do banco de dados e convertê-las em classes Java, acaba sendo
um pouco trabalhoso. Quando é usado JDBC puro, há a necessidade de realizar o mapeamento
entre os atributos e colunas do banco de dados. Às vezes é necessário fazer uma conversão do
tipo de dado declarado no banco de dados com o tipo de dado utilizado na classe. O mesmo
processo ocorre quando os objetos Java são salvos no banco de dados.
O JPA utiliza o conceito de mapeamento objeto / relacional (ORM – Object / Relational
Mapping) para fazer ponte entre a base de dados relacional e os objetos Java. A figura a seguir,
mostra o próprio framework que realiza o relacionamento entre os atributos das classes Java com
a tabela do banco de dados.
O JPA cria uma instância da classe Produto para cada linha da tabela Produto, como
mostrado na figura a seguir, e também atribui os valores das propriedades da classe Produto de
acordo com os valores das colunas da tabela. Por padrão o JPA realizará o mapeamento da classe
e atributos com o mesmo nome.
12.1 Entity
Uma Entity (Entidade) é um objeto utilizado para representar uma tabela da base de dados,
sendo que cada instância da entidade corresponde a uma linha da tabela.
A Entity é baseada em uma simples classe Java do tipo Plain Old Java Object (POJO), por-
tanto, nada mais é do que uma classe Java comum, porém com anotações para fornecer informa-
ções mais especificas para o gerenciador das entidades. O exemplo a seguir é uma Entity que
representa um produto.
______________________________________________________________________________________________
Curso Técnico em Informática 136 Programação Java
package pbc.jpa.exemplo1.entity; import java.io.Serializable; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Temporal; import javax.persistence.TemporalType; /** * Classe utilizada para representar a tabela Produto. */ @Entity public class Produto implements Serializable { private static final long serialVersionUID = 4185059514364687794L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String descricao; @Temporal(TemporalType.DATE) private Date dataValidade; private Double peso; public Date getDataValidade() { return dataValidade; } public void setDataValidade(Date dataValidade) { this.dataValidade = dataValidade; } public String getDescricao() { return descricao; } public void setDescricao(String descricao) { this.descricao = descricao; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Double getPeso() { return peso; } public void setPeso(Double peso) { this.peso = peso; } }
Neste exemplo é utilizada a anotação @Entity para definir está classe como uma entidade
do banco de dados. Utilizamos a anotação @Id para definir que o atributo Long id é chave primaria
da tabela Produto; também é definido que o atributo Long id tem seu valor gerado automatica-
mente através da anotação @GeneratedValue. Quando têm atributos que representam datas ou
tempos é necessário adicionar a anotação @Temporal para definir que o atributo Date dataVali-
dade é um campo do tipo Date no banco de dados.
O relacionamento feito entre a classe Java e a tabela do Banco de Dados, ocorre automati-
camente quando o nome da classe é igual ao nome da tabela; o mesmo vale para os atributos que
correspondem às colunas da tabela. Então, quando solicitar ao JPA para salvar, consultar, alterar
ou excluir uma entidade automaticamente será criado o Script SQL para executar a operação.
Esta classe está implementando a interface java.io.Serializable para informar que pode ser
serializada e trafegada pela rede de computadores. Quando as entidades fazem parte de uma apli-
cação console ou desktop não há necessidade de implementar esta interface, a não ser que a
______________________________________________________________________________________________
Curso Técnico em Informática 137 Programação Java
aplicação precise trafegar o objeto desta classe pela rede ou em algum HD. Quando implementada
esta interface também é preciso definir o atributo private static final long serialVersionUID com
um número longo, isto serve para identificar a classe quando o objeto for trafegar via rede.
Observação: o nome das tabelas no banco de dados não é case sensitive quando o banco de
dados é instalado no Windows, no caso do Linux já é case sensitive.
12.1.1 Anotações para Entity
As entidades podem ser melhor detalhadas adicionando mais algumas anotações e suas
propriedades. Estas anotações, podem informar ao JPA que por exemplo, uma entidade não segue
o padrão de nome igual ao da tabela, ou que sua tabela no banco possui um relacionamento de
Um-Para-Muitos com outra tabela, ou ainda, que a tabela utiliza um gerador de ID do tipo SE-
QUENCE para definir o número da chave primária e outras informações que veremos a seguir:
Obrigatoriamente toda entidade do JPA precisa ter pelo menos as anotações javax.persis-
tence.Entity que informa que é uma tabela do banco de dados e javax.persistence.Id que informa
qual o atributo é chave primária da tabela.
12.1.1.1 javax.persistence.Entity
Usado para definir que a classe é uma Entity, por padrão quando o nome da Entity é igual
ao nome da tabela o relacionamento é feito automaticamente pelo JPA. As propriedades da anota-
ção @Entity são listadas na tabela a seguir:
Propriedade Descrição
Name Informa o nome da entidade, por padrão o nome da entidade é nome
da classe. Este nome é utilizado para referenciar a entidade na
consulta.
12.1.1.2 javax.persistence.Table
Define o nome da tabela no banco de dados. As propriedades da anotação @Table são
listadas na tabela a seguir:
Propriedade Descrição
Catalog O catalogo da tabela.
Name O nome da tabela.
Schema O esquema da tabela.
uniqueConstraints Regras que podem ser adicionadas na tabela.
12.1.1.3 javax.persistence.Id
Informa o atributo da Entity que representa a chave primária.
12.1.1.4 javax.persistence.Column Informa as configurações de coluna da tabela, por padrão quando o nome do atributo da
Entity é igual ao nome da coluna da tabela, o relacionamento é feito automaticamente pelo JPA. As
propriedades da anotação @Column são listadas na tabela a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 138 Programação Java
Propriedade Descrição
columnDefinition Definição do tipo da coluna.
insertable Informa se a tabela deve ser incluída no SQL de insert, por
padrão é true.
length Tamanho da coluna, por padrão é 255.
name Nome da tabela que contém está coluna, se não for informado
a coluna assume o nome da tabela da entity.
nullable Informa se o valor pode ser null.
precision Precisão da coluna decimal.
scale Número de casas decimais, usado somente em coluna com
número decimal.
table Nome da tabela que contém está coluna, se não for informado
assume o nome da tabela da entity.
unique Informa se a coluna é chave única.
updatable Informa se a coluna deve ser incluída no SQL de update, por
padrão é true.
12.1.1.5 javax.persistence.SequenceGenerator
Utilizado para representar uma sequência numérica gerada através do banco de dados. As
propriedades da anotação @SequenceGenerator são listadas na tabela a seguir:
Propriedade Descrição
name Nome único para o gerador que pode ser referenciado por uma
ou mais classes que pode ser utilizado para gerar valores de
chave primaria.
allocationSize A quantidade que será incrementada na sequence. O padrão é
50.
initialValue Valor inicial da sequence.
sequenceName Nome da sequence do banco de dados.
12.1.1.6 javax.persistence.GeneratedValue
Define a estratégia para criar o ID, que pode ser tipo AUTO (incrementa automaticamente 1,
2, 3 em sequência) ou SEQUENCE. As propriedades da anotação @GeneratedValue são listadas
na tabela a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 139 Programação Java
Propriedade Descrição
generator Nome do gerador da chave primaria que é especificado na
anotação @SequenceGenerator ou @TableGenerator.
strategy Estratégia de geração de chave primaria que o serviço de
persistência precisa usar para gerar a chave primaria. Seu valor
pode ser obtido através da enum
javax.persistence.GenerationType. Os valores podem ser: AUTO,
IDENTITY, SEQUENCE ou TABLE.
12.1.1.7 javax.persistence.Temporal Utilizado para representar campos de Data e Hora. Nesta anotação podemos definir o tipo
de dado DATE, TIME e TIMESTAMP. As propriedades da anotação @Temporal são listadas na
tabela a seguir:
Propriedade Descrição
value O tipo usado para mapear java.util.Date é java.util.Calendar. Seu valor pode ser obtido através da enum javax.persistence.TemporalType. Os valores podem ser DATE: TIME e TIMESTAMP.
12.1.1.8 javax.persistence.Transient
Informa que o atributo não é persistente.
No exemplo abaixo, será criado uma entity para tabela Usuario a seguir: CREATE TABLE Usuario ( id NUMBER(10) NOT NULL PRIMARY KEY, nome VARCHAR2(100) NOT NULL, dataNasc DATE NOT NULL, email VARCHAR2(150) NOT NULL, ativo NUMBER(1) NOT NULL, comentario VARCHAR2(200) );
Crie a Entity para representar a tabela Usuario:
package pbc.jpa.exemplo1.entity; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Temporal; import javax.persistence.TemporalType; /**
______________________________________________________________________________________________
Curso Técnico em Informática 140 Programação Java
* Entidade utilizada para representar um Usuario. */ @Entity public class Usuario implements Serializable { private static final long serialVersionUID = -8762515448728066246L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(nullable = false) private String nome; @Temporal(TemporalType.DATE) @Column(name="dataNasc", nullable = false) private Date dataNascimento; @Column(nullable = false) private String email; @Column(nullable = false) private Boolean ativo; private String comentario; public Boolean getAtivo() { return ativo; } public void setAtivo(Boolean ativo) { this.ativo = ativo; } public String getComentario() { return comentario; } public void setComentario(String comentario) { this.comentario = comentario; } public Date getDataNascimento() { return dataNascimento; } public void setDataNascimento(Date dataNascimento) { this.dataNascimento = dataNascimento; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } } Foi utilizada a anotação @Entity para informar que a classe Usuario é uma entidade do
banco de dados; também foi definido que a propriedade Long id será o ID da tabela através da
anotação @Id e é informado que seu valor será gerado automaticamente com a anotação @Gene-
ratedValue. Por meio da anotação @Column é especificado quais os atributos não podem
ser null e que o atributo Date dataNascimento está mapeado para a coluna dataNasc da tabela
Usuario.
______________________________________________________________________________________________
Curso Técnico em Informática 141 Programação Java
12.2 EntityManager O EntityManager é um serviço responsável por gerenciar as entidades. Por meio dele é pos-
sível gerenciar o ciclo de vida das entidades, as operações com a base de dados (inserir, atualizar
ou remover), a consulta de entidades, entre outras operações.
Quando uma entidade está associada a um EntityManager, esta entidade está no contexto
em que pode ser persistida, ou seja, que todas as operações realizadas no objeto da entidade são
refletidas no banco de dados. Todas as identidades das entidades são únicas, portanto para cada
registro no banco de dados haverá apenas uma referência no contexto do EntityManager.
O EntityManager pode ser gerenciado de duas formas:
Gerenciado pelo Container;
Gerenciado pela Aplicação.
12.3 Unidade de Persistência A unidade de persistência é utilizada para configurar as informações referentes ao provedor
do JPA (implementação da especificação JPA) e ao banco de dados; também é possível identificar
as classes que serão mapeadas como entidades do banco de dados.
Para definir a unidade de persistência é necessário um arquivo XML chamado persis-
tence.xml, que deve ser criado na pasta META-INF do projeto. Por meio deste arquivo é possível
definir quantas unidades de persistência for necessário para o projeto. Exemplo de unidade de
persistência mapeado para um banco de dados:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ExemploJPAPU" transaction-type ="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>pbc.jpa.exercicio1.modelo.Livro</class>
<properties>
<property name="hibernate.connection.username” value="usuario"/>
<property name="hibernate.connection.password" value="senha"/>
<property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.Oracle-
Driver"/>
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@loca-
lhost:1521:XE"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCa-
cheProvider"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9Dialect"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Neste arquivo persistence.xml a tag persistence-unit define a unidade de persistência, e na
propriedade name qual seu nome (utilizado quando um EntityManager é criado por meio do Entity-
ManagerFactory no contexto Java SE ou quando é realizado injeção de dependência através da
______________________________________________________________________________________________
Curso Técnico em Informática 142 Programação Java
anotação javax.persistence.PersistenceUnit no contexto Java EE). A propriedade transaction-
type informa qual o tipo de transação (RESOURCE_LOCAL ou JTA). Se a aplicação é Java SE,
então, utilize o tipo de transação RESOURCE_LOCAL, assim programaticamente são criadas as
transações com o banco de dados e na aplicação Java EE utilize o JTA que acessa um pool de
conexões em um servidor web.
Em uma unidade de persistência utilize a tag provider para informar qual a API que fornecerá
uma implementação do JPA.
Em uma aplicação Java SE é necessário informar quais as classes são entidades do banco
de dados através da tag class e também informar quais as propriedades necessárias para encontrar
o banco de dados através da tag properties.
Nas aplicações Java EE é possível criar um pool de conexões com o banco de dados no
servidor web; neste caso é aconselhado utilizar o tipo de transação Java Transaction API
(JTA) que é fornecida pelo container EJB. Também é utilizada a tag jta-data-source para informar a
fonte do pool de conexões (nome JNDI). Exemplo de persistence.xml para aplicações Java EE:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ExemploJPAPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/ExemplosJPA</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
12.4 Criando uma unidade de persistência no NetBeans O NetBeans possui uma forma mais simples de criação da unidade de persistência. Clique
com o botão direito no projeto e selecione a opção Novo -> Outro..., na tela de Novo arquivo se-
lecione a categoria Persistence e o tipo de arquivo Unidade de Persistência, conforme a figura a
seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 143 Programação Java
Clique em Próximo > para definir as propriedades do banco de dados. Na tela de Provedor e
banco de dados digite um nome para a unidade de persistência, escolha qual a biblioteca de per-
sistência, defina a conexão com o banco de dados e qual a estratégia para geração de tabelas,
conforme a figura a seguir:
O Arquivos da Unidade de Persistência é utilizado quando a EntityManager é criada. Por
meio deste nome o EntityManager encontrará as configurações do banco de dados.
O Provedor de Persistência é a implementação do JPA utilizada para acessar o banco de
dados; neste exemplo é utilizado o framework Hibernate (JPA 2.0).
Fonte de dados é a forma como será realizada a conexão com o banco de dados. Pode ser
feito de duas maneiras, criada uma conexão direta na aplicação ou criado um pool de cone-
xões no servidor.
Para criar uma nova conexão direta na aplicação clique na caixa de seleção Fonte de Dados e
escolha a opção Nova fonte de dados..., conforme apresentado na figura a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 144 Programação Java
Na tela de Criar fonte de dados informe um Nome JNDI. Esse nome é usado para referenciar a
conexão e também uma Conexão de banco de dados. Caso ainda não tenha uma conexão criada,
escolha na caixa de seleção Conexão de banco de dados a opção Nova Conexão de Banco de
Dados..., conforme apresentado na figura a seguir:
Na tela Assistente de Nova Conexão escolha o Driver chamado Oracle Thin, conforme apresen-
tado na figura a seguir:
Na primeira vez que ele é usado é preciso especificar o driver do banco de dados Oracle. Clique
em Adicionar e escolha o driver ojdbc6.jar, conforme a figura a seguir:
______________________________________________________________________________________________
Curso Técnico em Informática 145 Programação Java
Clique em Próximo para continuar a criação da conexão. Continuando a criação da Nova Conexão
escolha o Nome do Driver, defina o Host (IP), Porta, ID do Serviço, Nome do usuário e Senha,
conforme o exemplo da figura a seguir:
Clique em Testar Conexão caso queira validar se as informações da conexão estão corretas, de-
pois clique em Próximo para continuar e depois clique em Finalizar para terminar a criação da
conexão.
Durante o desenvolvimento de uma aplicação web que acessa banco de dados, pode ser
utilizado um pool de conexões que é criado pelo próprio servidor de aplicações web, ao invés de
criar uma conexão com o banco de dados direto na aplicação é necessário criar um pool de co-
nexões no servidor e depois escolher na Fonte de dados, conforme a figura a seguir:
Neste exemplo será escolhida uma Fonte de Dados que foi criada no servidor GlassFish.
A Estratégia de geração de tabelas permite:
Criar - o JPA cria a estrutura de tabelas no banco de dados;
______________________________________________________________________________________________
Curso Técnico em Informática 146 Programação Java
Apagar e criar – o JPA apaga a estrutura existente e cria uma estrutura nova das tabelas do
banco de dados;
Nenhum – criar manualmente as tabelas do banco de dados.
Depois de criada a unidade de persistência, conforme apresentado na figura a seguir, note que esta
é uma versão visual do arquivo persistence.xml. OBS: caso você utilize o MYSQL os procedimentos
serão o mesmo, porem deverá substituir a fonte de dados pela do Mysql.
Este é o arquivo persistence.xml criado na pasta META-INF do projeto:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ExemplosJPAPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/Oracle</jta-data-source>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle9Dialect"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Para utilizar o Hibernate é necessário adicionar suas bibliotecas no projeto. Para fazer isso
clique com o botão direito no projeto e selecione a opção Propriedades, nesta tela selecione a
______________________________________________________________________________________________
Curso Técnico em Informática 147 Programação Java
categoria Bibliotecas, após isso clique no botão Adicionar biblioteca... e adicione as bibliote-
cas JPA do Hibernate, conforme a figura a seguir:
12.5 EntityManager gerenciado pela Aplicação Nas aplicações Java SE é necessário controlar pela aplicação como deve ser criado o Enti-
tyManager, para isso precisamos fazer os seguintes passos:
1) Utilizando a classe javax.persistence.Persistence podemos utilizar o método createEntityMa-
nagerFactory() que recebe como parâmetro o nome da unidade de persistência (que veremos
mais adiante) que contém as informações sobre o banco de dados para criar uma javax.persis-
tence.EntityManagerFactory.
EntityManagerFactory factory = Persistence.createEntityManagerFactory("UnitName");
2) Através do javax.persistence.EntityManagerFactory podemos utilizar o método createEntity-Manager() para obtermos uma EntityManager.
EntityManager entityManager = factory.createEntityManager();
Exemplo:
package pbc.jpa.exemplo.dao; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence;
______________________________________________________________________________________________
Curso Técnico em Informática 148 Programação Java
/** * Classe utilizada para fazer realizar as operações * de banco de dados sobre a entity Livro. */ public class DAO { private EntityManager entityManager; public EntityManager getEntityManager() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("ExemplosJPAPU"); entityManager = factory.createEntityManager(); factory.close(); } } No exemplo dentro do método getEntityManager() criamos um EntityManagerFactory da
unidade de persistência ExemplosJPAPU através da classe Persistence, depois criamos um En-
tityManager a partir da factory. Quando terminamos de utilizar a EntityManagerFactory é impor-
tante chamar o método close() para liberar os recursos da factory.
12.6 EntityManager gerenciado pelo Container
No desenvolvimento de aplicações Java EE é possível deixar o contêiner EJB injetar a uni-
dade de persistência através da anotação javax.persistence.PersistenceContext.
package pbc.jpa.exemplo.ejb; import javax.ejb.Stateless; import javax.persistence.EntityManager; /** * EJB utilizado para demonstrar o uso da injeção de * dependência do EntityManager. */ @Stateless public class ExemploBean implements ExemploRemote { @PersistenceContext(unitName = "ExercicioJPA1PU") private EntityManager entityManager; }
Este exemplo mostra um componente Session Bean Stateless que utiliza a anotação @Persisten-
ceContext para adicionar uma unidade de persistência no EntityManager. Repare que não é pre-
ciso criar manualmente a EntityManager, pois o container EJB se encarrega de fazer isso e também
atribui seu objeto para a variável com a anotação. A anotação @PersistenceContext possui o atri-
buto unitName para informar que o nome da unidade de persistência é ExemplosJPAPU, definido
na tag persistence-unit do arquivo persistence.xml.
______________________________________________________________________________________________
Curso Técnico em Informática 149 Programação Java
12.7 Interface EntityManager A interface javax.persistence.EntityManager possui a assinatura de métodos manipular as
entidades, executar consultas e outros:
public void persist(Object entity);
Faz uma nova instância gerenciável e persistivel.
entityManager.persist(pessoa);
Neste exemplo o método persist da EntityManager salva a entidade Pessoa no banco de dados.
public <T> T merge(T entity);
Junta o estado da Entity com o estado persistido, por exemplo:
entityManager.merge(pessoa);
Neste exemplo o método merge da EntityManager atualiza a entidade Pessoa no banco de dados.
public void remove(Object entity);
Remove a instância da Entity do banco de dados, por exemplo:
entityManager.remove(pessoa);
Neste exemplo o método remove da EntityManager exclui a entidade Pessoa no banco de dados.
public boolean contains(Object entity);
Verifica se a instância da Entity está em um estado persistível.
public <T> T find(Class<T> entityClass, Object primaryKey);
Procura um registro no banco de dados através da Entity e id (chave primária) da tabela, caso não
encontre retorna null, por exemplo:
Pessoa pessoa = entityManager.find(Pessoa.class, id);
Neste exemplo o método find da EntityManager pesquisa uma entidade pela sua classe e a chave
primária.
public <T> T getReference(Class<T> entityClass, Object primaryKey);
Procura um registro no banco de dados através da Entity e id da tabela, caso não encontre retorna
uma exceção javax.persistence.EntityNotFoundException.
public void flush();
Os métodos persist(), merge() e remove() aguardam a finalização da transação para sincronizar as
entidades com o banco de dados, o método flush() força esta sincronização no momento em que
é chamado.
public void refresh(Object entity);
Verifica se houve alguma alteração no banco de dados para sincronizar com a entidade.
public void clear();
Remove as entidades que estão no estado gerenciável dentro da EntityManager.
public void close();
Fecha a conexão do EntityManager.
______________________________________________________________________________________________
Curso Técnico em Informática 150 Programação Java
public boolean isOpen();
Verifica se o EntityManager está com a conexão aberta.
public EntityTransaction getTransaction();
Obtém uma javax.persistence.EntityTransaction que é uma transação com o banco de dados.
12.7.1 Ciclo de vida da Entity Uma entidade do banco de dados pode passar por quatro estados diferentes que fazem
parte do seu ciclo de vida: novo, gerenciável, desacoplado e removido, conforme a figura a seguir:
Novo (new)
A Entity foi criada, mas ainda não foi persistida no banco de dados. Mudanças no estado da
Entity não são sincronizadas com o banco de dados.
Gerenciado (managed)
A Entity foi persistida no banco de dados e encontra-se em um estado gerenciável. Mudan-
ças no estado da Entity são sincronizadas com o banco de dados assim que uma transação for
finalizada com sucesso.
Removido (removed)
A Entity foi agendada para ser removida da base de dados, esta entidade será removida
fisicamente do banco de dados quando a transação for finalizada com sucesso.
Desacoplado (detached)
A Entity foi persistida no banco de dados, mas encontra-se em um estado que não está
associada ao contexto persistível, portanto as alterações em seu estado não são refletidas na base
de dados.
12.8 DAO (CRUD) utilizando JPA Nesse exemplo, vamos criar uma aplicativo Java (console) chamado Exemplo, para salvar,
alterar, consultar por id e apagar um registro de pessoa, utilizaremos o banco de dados Oracle. Observação: Lembre de adicionar as bibliotecas do Hibernate JPA e Oracle (ojdbc6.jar) no seu projeto ou do Mysql. Vamos criar uma Entity para representar a tabela Pessoa a seguir:
CREATE SEQUENCE PESSOA_SEQ INCREMENT BY 1 START WITH 1 NOCACHE NOCYCLE;
______________________________________________________________________________________________
Curso Técnico em Informática 151 Programação Java
CREATE TABLE Pessoa ( id NUMBER(5) NOT NULL, nome VARCHAR2(100) NOT NULL, dataNasc DATE NOT NULL, email VARCHAR2(150), PRIMARY KEY(ID) );
Criando a entity para representar a tabela Pessoa:
package pbc.jpa.exemplo1.modelo; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Temporal; import javax.persistence.TemporalType; /** * Classe utilizada para representar uma pessoa. */ @Entity @SequenceGenerator(name="PES_SEQ", sequenceName="PESSOA_SEQ", allocationSize=1, initialValue=1) public class Pessoa implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PES_SEQ") private Long id; @Column(nullable = false) private String nome; @Temporal(TemporalType.DATE) @Column(name = "dataNasc", nullable = false) private Date dataNascimento; private String email; public Date getDataNascimento() { return dataNascimento; } public void setDataNascimento(Date dataNascimento) { this.dataNascimento = dataNascimento; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email;
______________________________________________________________________________________________
Curso Técnico em Informática 152 Programação Java
} public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } } Vamos criar o arquivo persistence.xml. O NetBeans possui um wizard que permite de forma
fácil a criação desta unidade de persistência, para isto, clique com o botão direito do mouse no
nome do projeto, selecione a opção Novo -> Outro..., na tela de Novo arquivo selecione a cate-
goria Persistence e o tipo de arquivo Unidade de Persistência.
Na tela de Novo Unidade de persistência, informe:
Nome da unidade de persistência: ExemplosJPAPU
Biblioteca de persistência: Hibernate JPA (1.0)
Conexão com o banco de dados: Aqui vamos criar uma nova conexão com o Oracle, então
selecione a opção Nova conexão com banco de dados...
Na tela Nova Conexão do Banco de Dados, selecione no campo Nome do driver a opção Novo
driver...
Na tela de Novo driver JDBC, clique em Adicionar... e procure pelo arquivo com o driver
do Oracle ou do Mysql (Caso esteja fazendo o uso desse banco), neste caso o arquivo ojdbc6.jar.
Após isso clique em OK para prosseguir.
Voltando na tela Nova Conexão do Banco de Dados, configure as seguintes informações:
Modo de entrada de dados: Entrada direta de URL
Nome do usuário: Informe seu usuário
Senha do usuário: Informe sua senha
URL JDBC: Para conectar no banco de dados utilize a URL jdbc:oracle:thin:@loca-
lhost:1521:XE ou outra de acordo com o local que foi instalado o seu banco de dados.
Clique em OK para prosseguir, a conexão com o banco de dados será testada e apresentará a
mensagem na tela “Conexão estabelecida”. Clique em OK para prosseguir.
Ao clicar em Finalizar será gerado o arquivo persistence.xml.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="ExemplosJPAPU"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>pbc.jpa.exemplo1.modelo.Pessoa</class>
<properties>
<property name="hibernate.connection.username"
value="usuario"/>
______________________________________________________________________________________________
Curso Técnico em Informática 153 Programação Java
<property name="hibernate.connection.password"
value="senha"/>
<property name="hibernate.connection.driver_class"
value="oracle.jdbc.driver.OracleDriver"/>
<property name="hibernate.connection.url"
value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="hibernate.cache.provider_class"
value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle9Dialect"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Vamos criar uma classe PessoaDAO que possui os métodos para manipular (salvar, atualizar, apa-
gar e consultar por id) um objeto Pessoa.
package pbc.jpa.exemplo.dao; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import pbc.jpa.exemplo.modelo.Pessoa; /** * Classe utilizada para fazer realizar as operações de * banco de dados sobre a entity Pessoa. */ public class PessoaDAO { /** * Método utilizado para obter o entity manager. * @return */ private EntityManager getEntityManager() { EntityManagerFactory factory = null; EntityManager entityManager = null; try { //Obtém o factory a partir da unidade de persistência. factory = Persistence.createEntityManagerFactory ("ExemplosJPAPU"); //Cria um entity manager. entityManager = factory.createEntityManager(); //Fecha o factory para liberar os recursos utilizado. } finally { factory.close(); } return entityManager; } /**
______________________________________________________________________________________________
Curso Técnico em Informática 154 Programação Java
* Método utilizado para salvar ou atualizar as * informações de uma pessoa. * @param pessoa * @return * @throws java.lang.Exception */ public Pessoa salvar(Pessoa pessoa) throws Exception { EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); System.out.println("Salvando a pessoa."); /* Verifica se a pessoa ainda não está salva no banco de dados. */ if(pessoa.getId() == null) { entityManager.persist(pessoa); } else { pessoa = entityManager.merge(pessoa); } // Finaliza a transação. entityManager.getTransaction().commit(); } finally { entityManager.close(); } return pessoa; } /** * Método que apaga a pessoa do banco de dados. * @param id */ public void excluir(Long id) { EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); /* Consulta a pessoa na base de dados através do seu ID. */ Pessoa pessoa = consultarPorId(id); System.out.println("Excluindo a pessoa: " + pessoa.getNome()); // Remove a pessoa da base de dados. entityManager.remove(pessoa); // Finaliza a transação. entityManager.getTransaction().commit(); } finally { entityManager.close(); } } /** * Consulta o pessoa pelo ID.
______________________________________________________________________________________________
Curso Técnico em Informática 155 Programação Java
* @param id * @return o objeto Pessoa. */ public Pessoa consultarPorId(Long id) { EntityManager entityManager = getEntityManager(); Pessoa pessoa = null; try { pessoa = entityManager.find(Pessoa.class, id); } finally { entityManager.close(); } return pessoa; } }
O método salvar recebe o objeto Pessoa que será salvo, neste exemplo usaremos este método
para salvar uma nova pessoa ou atualizar os dados de uma pessoa.
Mas como sabemos quando temos que salvar e quando tem que atualizar, basta olhar o
atributo id da classe Pessoa, se o id for null significa que é um novo objeto que ainda não foi salvo
no banco de dados, então utilizaremos o método persist da EntityManager para salva-lo, caso o id
tenha algum valor então significa que o objeto já foi salvo anteriormente, portanto ele deve ser
atualizado então utilizaremos o método merge da EntityManager para atualiza-lo.
Note que como vamos salvar ou atualizar os dados, precisamos criar uma transação, com o
método getTransaction() do EntityManager obtemos um objeto EntityTransaction com ele pode-
mos iniciar a transação através do método begin(), finalizar a transação com sucesso através do
método commit() ou desfazer as alterações em caso de erro com o método rolback(). Este mesmo
conceito de transação será utilizado no método excluir.
O método excluir não precisa receber todos os dados da Pessoa, recebendo apenas o seu
ID através do parâmetro Long id, podemos utilizar o método find do EntityManager para consul-
tar os dados da Pessoa, depois com o objeto Pessoa consultado podemos usar o método re-
move do EntityManager para apagar os dados da Pessoa.
O método consultarPorId recebe um objeto Long chamado id, com o ID da tabela Pessoa,
utilizando o método find do EntityManager passamos a classe da entidade Pessoa.class e
seu id para que possamos consultar os dados da Pessoa.
Vamos criar uma classe PessoaDAOTeste para testarmos os métodos da classe PessoaDAO:
package pbc.jpa.exemplo1.teste;
import java.util.Calendar;
import java.util.GregorianCalendar;
import pbc.jpa.exemplo1.dao.PessoaDAO;
import pbc.jpa.exemplo1.modelo.Pessoa;
/**
* Classe utilizada para testar os métodos do PessoaDAO.
*/
public class PessoaDAOTeste {
public static void main(String[] args) throws Exception {
Pessoa pessoa = new Pessoa();
______________________________________________________________________________________________
Curso Técnico em Informática 156 Programação Java
pessoa.setId(1L);
pessoa.setNome("Rafael Sakurai");
Calendar data = new GregorianCalendar();
data.set(Calendar.YEAR, 1983);
data.set(Calendar.MONTH, 11);
data.set(Calendar.DAY_OF_MONTH, 26);
pessoa.setDataNascimento(data.getTime());
pessoa.setEmail("[email protected]");
PessoaDAO dao = new PessoaDAO();
System.out.println("Salvando a pessoa: "
+ pessoa.getNome());
pessoa = dao.salvar(pessoa);
pessoa.setNome("Rafael Guimarães Sakurai");
pessoa = dao.salvar(pessoa);
System.out.println("Alterando a pessoa: "
+ pessoa.getNome());
Pessoa pessoa2 = dao.consultarPorId(pessoa.getId());
System.out.println("Consultando: " + pessoa2.getNome());
System.out.println("Removendo a pessoa: "
+ pessoa.getId());
dao.excluir(pessoa.getId());
}
}
Neste teste vamos criar um objeto pessoa e salva-lo, depois vamos altera o nome da pessoa, va-
mos consultar a pessoa pelo id e no final vamos apagar o registro da pessoa.
12.9 Estratégia de SEQUENCE para gerar ID
O banco de dados possui um tipo de objeto que pode ser criado internamente chamado
SEQUENCE (sequência) e que pode ser associado a um contador. Cada vez que o seu próximo
valor é solicitado ocorre um incremento deste valor. Para gerar o ID da entidade é possível utilizar
a estratégia de SEQUENCE também, associando a sequência criada no banco de dados com o
gerador de ID.
No exemplo, a seguir, será criada uma entidade que utiliza uma SEQUENCE para gerar o id
referente a chave primária da tabela. Primeiro será criada a sequência USUARIO_SEQ no banco
de dados:
CREATE SEQUENCE USUARIO_SEQ INCREMENT BY 1 START WITH 1 NOCACHE NOCYCLE;
A seguir, crie a entidade Usuario que utilizará está sequência para gerar o ID.
package pbc.jpa.exemplo.sequence.modelo; import java.io.Serializable;
______________________________________________________________________________________________
Curso Técnico em Informática 157 Programação Java
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; import javax.persistence.Table; /** * Classe utilizada para demonstrar o uso da SEQUENCE. */ @Entity @Table(name = "USUARIO") @SequenceGenerator(name="USU_SEQ", sequenceName="USUARIO_SEQ", initialValue=1, allocationSize=1) public class Usuario implements Serializable { private static final long serialVersionUID = -4023522856316087762L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USU_SEQ") private Long id; private String nome; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } }
A anotação @SequenceGenerator vai indicar qual a sequência do banco de dados, qual o valor
inicial e a quantidade que esta sequência é incrementada.
name = informa o apelido da sequence exemplo "USU_SEQ";
sequenceName = informa o nome da sequência criada no banco de dados, por exemplo:
"USUARIO_SEQ";
initialValue = informa o valor inicial da sequência, por exemplo: 1;
allocationSize = informa a quantidade que será incrementada na sequência, o padrão (de-
fault) é 50, neste exemplo foi definido que será incrementado de 1 em 1.
A anotação @GeneratedValue nesse caso está usando a estratégia de SEQUENCE então ele vai
procurar a sequência que tem o apelido "USU_SEQ" e faz uma consulta no banco para pegar seu
resultado:
SELECT USUARIO_SEQ.NEXTVAL FROM DUAL;
strategy = informa o tipo de estratégia que será utilizado nesse exemplo Generation-
Type.SEQUENCE;
generator = informa o apelido da sequence nesse exemplo "USU_SEQ".
______________________________________________________________________________________________
Curso Técnico em Informática 158 Programação Java
12.10 Utilizando chave composta A chave composta define que vários atributos serão utilizados para definir a chave de uma
entidade, com isso, acabamos tendo uma restrição onde os atributos da chave composta não po-
dem ser repetidos.
No JPA quando precisamos definir uma chave composta precisamos criar uma classe sepa-
rada apenas com os atributos que fazem parte da chave composta e precisamos utilizar a anota-
ção javax.persistence.Embeddable.
Neste exemplo vamos criar uma entidade Telefone que possui uma chave composta pelos
atributos ddd e número do telefone, pois não pode ter o mesmo número de telefone para mais de
1 cliente.
Para declarar a chave composta vamos criar uma classe chamada TelefonePK com os atri-
butos ddd e numero:
package pbc.jpa.exemplo.chave.composta.modelo; import java.io.Serializable; import javax.persistence.Embeddable; /** * Esta classe representa a composição da chave do * telefone, está chave é composta por ddd + numero * do telefone. */ @Embeddable public class TelefonePK implements Serializable { private static final long serialVersionUID = -637018809489152388L; private Short ddd; private String numero; public Short getDdd() { return ddd; } public void setDdd(Short ddd) { this.ddd = ddd; } public String getNumero() { return numero; } public void setNumero(String numero) { this.numero = numero; } @Override public String toString() { return "("+ getDdd() + ") " + getNumero(); } }
Observação: Sobrescrevi o método toString() para imprimir de forma mais amigável a chave com-
posta.
Note que adicionamos a anotação @Embeddable na classe TelefonePK para informar que
está classe será adicionado em outra entidade.
______________________________________________________________________________________________
Curso Técnico em Informática 159 Programação Java
Para adicionarmos a chave composta na entidade, vamos criar um atributo do tipo da classe
que possui a anotação @Embeddable e vamos adicionar a anotação javax.persistence.Em-
beddedId neste atributo.
Na entidade Telefone vamos declarar um atributo chamado id do tipo TelefonePK para re-
presentar a chave composta:
package pbc.jpa.exemplo.chave.composta.modelo; import java.io.Serializable; import javax.persistence.EmbeddedId; import javax.persistence.Entity; /** * Classe utilizada para representar o telefone de um cliente. * Nesta classe abordamos o uso da chave composta através * da anotação @EmbeddedId. */ @Entity public class Telefone implements Serializable { private static final long serialVersionUID = 5999236902534007386L; @EmbeddedId private TelefonePK id; private String cliente; public String getCliente() { return cliente; } public void setCliente(String cliente) { this.cliente = cliente; } public TelefonePK getId() { return id; } public void setId(TelefonePK id) { this.id = id; } } Agora vamos criar a classe TelefoneDAO para executar as operações de Salvar, Alterar,
Consultar por chave composta e apagar o telefone:
package pbc.jpa.exemplo.chave.composta.dao; import javax.persistence.EntityExistsException; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import pbc.jpa.exemplo.chave.composta.modelo.Telefone; import pbc.jpa.exemplo.chave.composta.modelo.TelefonePK; /** * Classe utilizada para testar as operações Salvar, * Altera, Consultar por Id e Apagar o registro de * um telefone. */ public class TelefoneDAO {
______________________________________________________________________________________________
Curso Técnico em Informática 160 Programação Java
public EntityManager getEntityManager() { EntityManagerFactory factory = null; EntityManager entityManager = null; try { factory = Persistence.createEntityManagerFactory ("ExemplosJPAPU"); entityManager = factory.createEntityManager(); } finally { factory.close(); } return entityManager; } public Telefone consultarPorId(TelefonePK id) { EntityManager entityManager = getEntityManager(); Telefone telefone = null; try { telefone = entityManager.find(Telefone.class, id); } finally { entityManager.close(); } return telefone; } public Telefone salvar(Telefone telefone) throws Exception { EntityManager entityManager = getEntityManager(); try { entityManager.getTransaction().begin(); entityManager.persist(telefone); entityManager.flush(); entityManager.getTransaction().commit(); /*Esta exceção pode ser lançada caso já exista um registro com a mesma chave composta. */ } catch (EntityExistsException ex) { entityManager.getTransaction().rollback(); throw new Exception("Este telefone já está registrado para outro cliente."); } catch (Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } return telefone; } public Telefone atualizar(Telefone telefone)
______________________________________________________________________________________________
Curso Técnico em Informática 161 Programação Java
throws Exception { EntityManager entityManager = getEntityManager(); try { entityManager.getTransaction().begin(); entityManager.merge(telefone); entityManager.flush(); entityManager.getTransaction().commit(); } catch (Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } return telefone; } public void apagar(TelefonePK id) { EntityManager entityManager = getEntityManager(); try { entityManager.getTransaction().begin(); Telefone telefone = entityManager.find(Telefone.class, id); entityManager.remove(telefone); entityManager.flush(); entityManager.getTransaction().commit(); } catch (Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } } } No método consultarPorId precisamos agora passar um atributo da chave composta Tele-
fonePK para que possamos localizar um telefone.
No método salvar vamos receber o objeto Telefone que será salvo, note que estamos tra-
tando a exceção javax.persistence.EntityExitsException que será lançada caso tentamos salvar
duas entidades com o mesmo id, neste caso com o mesmo ddd e número de telefone.
Criamos agora um método atualizar separado apenas para atualizar o telefone, pois pode-
mos criar um Telefone e alterar o nome do cliente, mas não podemos criar dois telefones com o
mesmo ddd e número de telefone.
No método apagar precisamos receber um objeto que representa a chave composta Tele-
fonePK, desta forma podemos localizar o objeto Telefone para que possamos apagá-lo.
Nesta classe TelefoneDAOTeste vamos testar todas as operações da classe TelefoneDAO
declarada acima:
package pbc.jpa.exemplo.chave.composta.dao; import pbc.jpa.exemplo.chave.composta.modelo.Telefone; import pbc.jpa.exemplo.chave.composta.modelo.TelefonePK;
______________________________________________________________________________________________
Curso Técnico em Informática 162 Programação Java
/** * Classe utilizada para testar as operações da * classe TelefoneDAO. */ public class TelefoneDAOTeste { public static void main(String[] args) throws Exception { /* Cria uma chave composta. */ TelefonePK pk = new TelefonePK(); pk.setDdd((short) 11); pk.setNumero("1111-1111"); /* Cria um telefone. */ Telefone tel = new Telefone(); tel.setId(pk); tel.setCliente("Sakurai"); TelefoneDAO dao = new TelefoneDAO(); System.out.println("Salvando o telefone: " + pk); dao.salvar(tel); System.out.println("Consultando o telefone: " + pk); Telefone tel2 = dao.consultarPorId(pk); System.out.println("Cliente " + tel2.getCliente()); try { System.out.println("Tentando salvar o mesmo número de telefone para outro cliente."); Telefone tel3 = new Telefone(); tel3.setId(pk); tel3.setCliente("Rafael"); dao.salvar(tel3); } catch (Exception ex) { System.out.println(ex.getMessage()); } System.out.println("Alterando o cliente:"); tel.setCliente("Rafael"); dao.atualizar(tel); System.out.println("Apagando o registro do telefone:"); dao.apagar(pk); } }
Exercícios:
Neste exercício vamos abordar como criar uma aplicação CRUD (salvar, alterar, consultar e
excluir) do Livro utilizando o Java Persistence API.
Crie o seguinte banco de dados: CREATE SEQUENCE LIVRO_SEQ INCREMENT BY 1
START WITH 1 NOCACHE NOCYCLE; CREATE TABLE Livro ( id number(5) NOT NULL,
______________________________________________________________________________________________
Curso Técnico em Informática 163 Programação Java
titulo varchar2(200) NOT NULL, autor varchar2(200) NOT NULL, isbn varchar2(50) NOT NULL, paginas number(5) NOT NULL, preco number(10,2) NOT NULL, PRIMARY KEY(id) );
Crie um Projeto Java chamado ExercicioJPA1, adicione as bibliotecas Hibernate JPA e Driver da Oracle (ojdbc6.jar ou ojdbc7.jar) ou Driver do Mysql e crie:
Uma classe entity para representar um Livro com os atributos id, titulo, autor, isbn, paginas e preco.
package pbc.jpa.exercicio1.modelo; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.SequenceGenerator; import javax.persistence.Id; import javax.persistence.SequenceGenerator; /** * Classe utilizada para representar uma Entity Livro. */ @Entity @SequenceGenerator(name = "LIVRO_SEQ", sequenceName = "LIVRO_SEQ", initialValue = 1, allocationSize = 1) public class Livro implements Serializable { private static final long serialVersionUID = 2405106626392673061L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "LIVRO_SEQ") @Column(nullable = false) private Long id; @Column(nullable = false) private String titulo; @Column(nullable = false) private String autor; @Column(nullable = false) private String isbn; @Column(nullable = false) private Integer paginas; @Column(nullable = false) private Double preco; public String getAutor() { return autor; }
______________________________________________________________________________________________
Curso Técnico em Informática 164 Programação Java
public void setAutor(String autor) { this.autor = autor; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public Integer getPaginas() { return paginas; } public void setPaginas(Integer paginas) { this.paginas = paginas; } public Double getPreco() { return preco; } public void setPreco(Double preco) { this.preco = preco; } public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } }
Crie uma classe LivroDAO com os seguintes métodos:
o getEntityManager() – que cria um EntityManager
o salvar() – chame o método do EntityManager que realize a operação de salvar ou
alterar um livro.
o consultarPorId() – chame o método do EntityManager que realize a operação de
consultar passando o atributo da chave primaria.
o excluir() – chame o método do EntityManager que realize a operação de remover
um livro.
package pbc.jpa.exercicio1.dao;
import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import pbc.jpa.exercicio1.modelo.Livro; /** * Classe utilizada para fazer realizar as operações de * banco de dados sobre a entity Livro. */ public class LivroDAO {
______________________________________________________________________________________________
Curso Técnico em Informática 165 Programação Java
/** * Método utilizado para obter o entity manager. * @return */ private EntityManager getEntityManager() { EntityManagerFactory factory = null; EntityManager entityManager = null; try { //Obtém o factory a partir da unidade de persistência. factory = Persistence.createEntityManagerFactory ("ExercicioJPA1PU"); //Cria um entity manager. entityManager = factory.createEntityManager(); //Fecha o factory para liberar os recursos utilizado. } finally { factory.close(); } return entityManager; } /** * Método utilizado para salvar ou atualizar as * informações de um livro. * @param livro * @return * @throws java.lang.Exception */ public Livro salvar(Livro livro) throws Exception { EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); System.out.println("Salvando o livro."); /* Verifica se o livro ainda não está salvo no banco de dados. */ if(livro.getId() == null) { entityManager.persist(livro); } else { livro = entityManager.merge(livro); } // Finaliza a transação. entityManager.getTransaction().commit(); } finally { entityManager.close(); } return livro; } /** * Método que exclui o livro do banco de dados. * @param id */ public void excluir(Long id) {
______________________________________________________________________________________________
Curso Técnico em Informática 166 Programação Java
EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); // Consulta o livro na base de dados através do seu ID. Livro livro = entityManager.find(Livro.class, id); System.out.println("Excluindo o livro: " + livro.getTitulo()); // Remove o livro da base de dados. entityManager.remove(livro); // Finaliza a transação. entityManager.getTransaction().commit(); } finally { entityManager.close(); } } /** * Consulta o livro pelo ID. * @param id * @return */ public Livro consultarPorId(Long id) { EntityManager entityManager = getEntityManager(); Livro livro = null; try { livro = entityManager.find(Livro.class, id); } finally { entityManager.close(); } return livro; } }
Vamos criar um arquivo persistence.xml dentro da pasta META-INF para guardar as configura-
ções do banco de dados. Neste arquivo também vamos informar a Entity Livro.
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="ExercicioJPA1PU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>pbc.jpa.exercicio1.modelo.Livro</class> <properties> <property name="hibernate.connection.username" value="usuario"/> <property name="hibernate.connection.password"
______________________________________________________________________________________________
Curso Técnico em Informática 167 Programação Java
value="senha"/> <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/> <property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:XE"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9Dialect"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>
Para testar as operações sobre a entidade Livro, vamos criar a classe LivroTeste que utiliza o LivroDAO para fazer uso da EntityManager para gerenciar a entity Livro.
package pbc.jpa.exercicio1.teste; import pbc.jpa.exercicio1.dao.LivroDAO; import pbc.jpa.exercicio1.modelo.Livro; /** * Classe utilizada para testar a persistência da * entity Livro. */ public class LivroTeste { public static void main(String[] args) { try { Livro livro = new Livro(); livro.setAutor("Rafael Guimarães Sakurai"); livro.setIsbn("111-11-1111-111-1"); livro.setPaginas(439); livro.setPreco(30.90); livro.setTitulo("Guia de estudos SCJA."); LivroDAO dao = new LivroDAO(); livro = dao.salvar(livro); System.out.println("ID do livro salvo: " + livro.getId()); /* * PARA FAZER - Teste a consulta, alteração * e exclusão do livro. */ } catch (Exception ex) { ex.printStackTrace(); } } }
Agora só testar e terminar de implementar.
______________________________________________________________________________________________
Curso Técnico em Informática 168 Programação Java
Exericios:
1) Crie uma aplicação Swing utilizando JPA para fazer o CRUD (salvar, alterar, consultar e excluir)
da tabela Produto a seguir:
CREATE TABLE Produto (
id number(5) NOT NULL PRIMARY KEY,
nome varchar2(200) NOT NULL,
preco number(10,2) NOT NULL,
dataValidade date,
qtdEstoque number(5)
);
2) Crie uma aplicação Swing ou Console utilizando o JPA para fazer o CRUD (salvar, consultar,
alterar e excluir) de duas entidades a sua escolha.
12.11 Relacionamento entre entidades Os relacionamentos também podem ser:
Unidirecional
A partir de uma entidade, é possível encontrar outra entidade, mas o contrario não acontece,
nesse exemplo a Entidade A conhece a Entidade B, mas o contrario não acontece.
Bidirecional
Ambas entidades se conhecem, nesse exemplo a Entidade A conhece a Entidade B e vice-
versa.
Esses relacionamentos são definidos de acordo com a necessidade do negocio, não existe uma regra que sempre tem que ser unidirecional ou bidirecional.
12.12 Os quatro tipos de cardinalidade Um-para-Um (OneToOne) - Este relacionamento informa que há apenas um registro da
entidade relacionado com um registro de outra entidade.
Exemplo de relacionamento Um-para-Um unidirecional:
Script do banco de dados:
CREATE TABLE Mensagem ( id number(5) NOT NULL PRIMARY_KEY, assunto varchar2(200) NOT NULL, dataEnvio date NOT NULL, mensagemcorpo_id number(5) );
______________________________________________________________________________________________
Curso Técnico em Informática 169 Programação Java
CREATE TABLE MensagemCorpo ( id number(5) NOT NULL PRIMARY KEY, descricao varchar2(200) );
Modelo UML:
Neste exemplo definimos que uma Mensagem possui uma MensagemCorpo, então desta
forma a Mensagem sabe qual é seu MensagemCorpo, mas o contrario não existe, a Mensa-
gemCorpo não tem a necessidade de conhecer qual a Mensagem está associado a ele, ou seja,
temos um relacionamento unidirecional.
Primeiramente podemos mostrar apenas uma listagem de Mensagens, mas não tem neces-
sidade por enquanto de mostrar o conteúdo de todas as mensagens e depois caso eu queira ler o
conteúdo da mensagem podemos através dela chegar até seu corpo utilizando o atributo do tipo
MensagemCorpo.
Código fonte das classes com o relacionamento:
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import java.util.Date; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Temporal; import javax.persistence.TemporalType; /** * Classe utilizada para representar uma Mensagem. */ @Entity public class Mensagem implements Serializable { private static final long serialVersionUID = 1912492882356572322L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;
______________________________________________________________________________________________
Curso Técnico em Informática 170 Programação Java
private String assunto; @Temporal(TemporalType.DATE) private Date dataEnvio; @OneToOne(cascade=CascadeType.ALL) private MensagemCorpo mensagemCorpo; public String getAssunto() { return assunto; } public void setAssunto(String assunto) { this.assunto = assunto; } public Date getDataEnvio() { return dataEnvio; } public void setDataEnvio(Date dataEnvio) { this.dataEnvio = dataEnvio; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public MensagemCorpo getMensagemCorpo() { return mensagemCorpo; } public void setMensagemCorpo(MensagemCorpo mensagemCorpo) { this.mensagemCorpo = mensagemCorpo; } }
Na classe Mensagem utilizamos a anotação javax.persistence.OneToOne para definir o relacio-
namento de um-para-um entre as classes Mensagem e MensagemCorpo.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * Classe utilizada para representar o corpo de uma * mensagem. */ @Entity public class MensagemCorpo implements Serializable { private static final long serialVersionUID = 986589124772488369L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;
______________________________________________________________________________________________
Curso Técnico em Informática 171 Programação Java
private String descricao; public String getDescricao() { return descricao; } public void setDescricao(String descricao) { this.descricao = descricao; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
A classe MensagemCorpo é uma entidade normal que não conhece a classe Mensagem. Note que não precisamos criar nenhuma referencia para informar que o
atributo mensagemCorpo da classe Mensagem referencia a coluna mensagemcorpo_id da tabela
Mensagem.
O JPA possui alguns padrões para facilitar o mapeamento entre a classe Java e a tabela do
banco de dados, quando criamos uma coluna de chave estrangeira seguindo o padrão nometa-
bela_chaveprimaria, o mapeamento é feito automaticamente pelo JPA, ou seja, o atributo Mensa-
gemCorpo mensagemCorpo é automaticamente associado com a coluna mensagemcorpo_id.
javax.persistence.OneToOne - Esta anotação define uma associação com outra entidade que
tenha a multiplicidade de um-para-um. A tabela a seguir mostra as propriedades da anotação
@OneToOne.
Propriedade Descrição
cascade As operações que precisam ser refletidas no alvo da associação.
fetch Informa se o alvo da associação precisa ser obtido apenas quando for necessário ou se sempre deve trazer.
mappedBy Informa o atributo que é dono do relacionamento.
optional Informa se a associação é opcional.
targetEntity A classe entity que é alvo da associação.
Quando precisamos especificar um mapeamento que não é padrão do JPA, podemos utilizar a
anotação javax.persistence.JoinColumn, por exemplo se a tabela Mensagem e MensagemCorpo
fossem:
CREATE TABLE Mensagem ( id number(5) NOT NULL PRIMARY KEY, assunto varchar2(200), dataEnvio date, ID_MENSAGEMCORPO number(5) ); CREATE TABLE MensagemCorpo (
______________________________________________________________________________________________
Curso Técnico em Informática 172 Programação Java
MC_ID number(5) NOT NULL PRIMARY_KEY, descricao varchar2(200) );
Poderíamos utilizar o JoinColumn para criar a associação:
@OneToOne(cascade=CascadeType.ALL) @JoinColumn(name="ID_MENSAGEMCORPO", referencedColumnName="MC_ID") private MensagemCorpo mensagemCorpo; javax.persistence.JoinColumn - esta anotação é utilizada para especificar a coluna utilizada na
associação com outra entity. A tabela a seguir apresenta as propriedades da anotação @JoinCo-
lumn.
Propriedade Descrição
columnDefinition Definição do tipo da coluna.
insertable Informa se a coluna é incluída no SQL de INSERT.
name Informa o nome da coluna de chave estrangeira.
nullable Informa se a coluna pode ser null.
referencedColumnName Nome da coluna que é referenciada pela coluna da chave estrangeira.
table Nome da tabela que contém a coluna.
unique Informa se a propriedade é chave única.
updatable Informa se a coluna é incluída no SQL de UPDATE.
Um-para-Muitos (OneToMany) - Este relacionamento informa que o registro de uma entidade está
relacionado com vários registros de outra entidade.
Exemplo de relacionamento Um-para-Muitos unidirecional:
Script do banco de dados:
CREATE TABLE Aula ( id number(5) NOT NULL PRIMARY KEY, titulo varchar2(45) NOT NULL, data date NOT NULL ); CREATE TABLE Tarefa ( id number(5) NOT NULL PRIMARY KEY, titulo varchar2(45) NOT NULL, descricao varchar2(45) NOT NULL, aula_id number(5) );
______________________________________________________________________________________________
Curso Técnico em Informática 173 Programação Java
Modelo UML:
Neste exemplo definimos que uma Aula possui uma lista de Tarefa, portanto a aula pode não ter
tarefa, pode ter apenas uma tarefa ou pode ter varias tarefas, uma Tarefa não precisa saber de
qual Aula ela está associada, portanto temos um relacionamento unidirecional.
Código fonte das classes com o relacionamento:
Na classe Aula utilizamos a anotação javax.persistence.OneToMany no atributo tarefas, para in-
formar que uma Aula está associada com várias tarefas.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import java.util.Date; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Temporal; import javax.persistence.TemporalType; /** * Classe utilizada para representar uma aula. */ @Entity public class Aula implements Serializable { private static final long serialVersionUID = -6745032908099856302L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String titulo; @Temporal(TemporalType.DATE) private Date data; @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name="aula_id")
______________________________________________________________________________________________
Curso Técnico em Informática 174 Programação Java
private List<Tarefa> tarefas; public Date getData() { return data; } public void setData(Date data) { this.data = data; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public List<Tarefa> getTarefas() { return tarefas; } public void setTarefas(List<Tarefa> tarefas) { this.tarefas = tarefas; } }
javax.persistence.OneToMany - esta anotação define uma associação com outra entidade que
tenha a multiplicidade de um-para-muitos.
Propriedade Descrição
cascade As operações que precisam ser refletidas no alvo da associação.
fetch Informa se o alvo da associação precisa ser obtido apenas quando for necessário ou se sempre deve trazer.
mappedBy Informa o atributo que é dono do relacionamento.
targetEntity A classe entity que é alvo da associação.
A classe Tarefa é uma entidade normal que não conhece a classe Aula.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; /** * Classe utilizada para representar as tarefas * aplicadas em uma aula. */ @Entity public class Tarefa implements Serializable { private static final long serialVersionUID = 2952630017127173988L; @Id
______________________________________________________________________________________________
Curso Técnico em Informática 175 Programação Java
@GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String titulo; private String descricao; public String getDescricao() { return descricao; } public void setDescricao(String descricao) { this.descricao = descricao; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } }
Muitos-para-Um (ManyToOne) - este relacionamento informa que existem muitos registros de uma
entidade associados a um registro de outra entidade.
Exemplo de relacionamento Um-para-Muitos e Muitos-para-Um bidirecional:
Script do banco de dados:
CREATE TABLE Pessoa ( id number(5) NOT NULL PRIMARY KEY, nome varchar2(200) NOT NULL, cpf varchar2(11) NOT NULL ); CREATE TABLE Telefone ( id number(5) NOT NULL PRIMARY KEY, tipo varchar2(200) NOT NULL, numero number(8) NOT NULL, pessoa_id number(5) );
Modelo UML:
______________________________________________________________________________________________
Curso Técnico em Informática 176 Programação Java
Neste exemplo definimos que uma Pessoa possui uma lista de Telefones e um Telefone está as-
sociado a uma Pessoa, portanto temos um relacionamento bidirecional.
Código fonte das classes com o relacionamento:
Na entidade Pessoa definimos que uma pessoa possui vários telefones através do atri-
buto List<Telefone> telefones e adicionamos a anotação javax.persistence.OneToMany para in-
formar que o relacionamento de Pessoa para Telefone é de Um-para-Muitos, note que nesta ano-
tação definimos a propriedade mappedBy como "pessoa" que é para informar que o atributo com
o nome pessoa na entity Telefone que é dona do relacionamento.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; /** * Classe utilizada para representar uma Pessoa. */ @Entity public class Pessoa implements Serializable { private static final long serialVersionUID = -1905907502453138175L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String nome; private String cpf; @OneToMany(mappedBy="pessoa", cascade=CascadeType.ALL) private List<Telefone> telefones; public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List<Telefone> getTelefones() { return telefones; } public void setTelefones(List<Telefone> telefones) { this.telefones = telefones; } }
______________________________________________________________________________________________
Curso Técnico em Informática 177 Programação Java
Na entidade Telefone definimos o atributo Pessoa pessoa e adicionamos a anotação ja-
vax.persistence.ManyToOne para definir que o relacionamento de Telefone para Pessoa é de
Muitos-para-Um.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; /** * Classe utilizada para representar um Telefone. */ @Entity public class Telefone implements Serializable { private static final long serialVersionUID = 7526502149208345058L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String tipo; private Integer numero; @ManyToOne private Pessoa pessoa; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getNumero() { return numero; } public void setNumero(Integer numero) { this.numero = numero; } public Pessoa getPessoa() { return pessoa; } public void setPessoa(Pessoa pessoa) { this.pessoa = pessoa; } public String getTipo() { return tipo; } public void setTipo(String tipo) { this.tipo = tipo; } }
javax.persistence.ManyToOne - esta anotação define uma associação com outra entidade que
tenha a multiplicidade de muitos-para-um.
Propriedade Descrição
______________________________________________________________________________________________
Curso Técnico em Informática 178 Programação Java
cascade As operações que precisam ser refletidas no alvo da associação.
Fetch Informa se o alvo da associação precisa ser obtido apenas quando for
necessário ou se sempre deve trazer.
optional Informa se a associação é opcional.
targetEntity A classe entity que é alvo da associação.
Também podemos adicionar uma tabela para realizar o relacionamento unidirecional de um-
para-muitos e o relacionamento muitos-para-muitos, normalmente utilizamos está alternativa como
uma forma de normalizar os dados evitando duplicar o conteúdo dos registros.
Nesse exemplo queremos utilizar a entidade Telefone com as entidades Pessoa e Aluno,
dessa forma Pessoa possui uma lista de Telefones e Aluno possui uma lista de Telefones, mas o
telefone não sabe para quem ele está associado. Este tipo de relacionamento é unidirecional de
um-para-muitos.
Na base de dados iremos criar as tabelas Pessoa, Telefone e Aluno, também iremos criar duas
tabelas de associação chamadas Pessoa_Telefone e Aluno_Telefone:
CREATE TABLE Pessoa ( id number(5) NOT NULL PRIMARY KEY, nome varchar2(200) NOT NULL, cpf varchar2(11) NOT NULL ); CREATE TABLE Aluno ( id number(5) NOT NULL PRIMARY_KEY, nome varchar2(200) NOT NULL, matricula number(5) NOT NULL ); CREATE TABLE Telefone ( id number(5) NOT NULL PRIMARY KEY, tipo varchar2(200) NOT NULL, numero number(5) NOT NULL ); CREATE TABLE Pessoa_Telefone ( pessoa_id number(5), telefone_id number(5) ); CREATE TABLE Aluno_Telefone (
______________________________________________________________________________________________
Curso Técnico em Informática 179 Programação Java
aluno_id number(5), telefone_id number(5) ); Na entidade Pessoa definimos que uma pessoa possui vários telefones através do atri-
buto List<Telefone> telefones e adicionamos a anotação javax.persistence.OneToMany para in-
formar que o relacionamento de Pessoa para Telefone é de Um-para-Muitos.
Para informar que vamos utilizar a tabela PESSOA_TELEFONE para realizar a associação
entre as tabelas PESSOA e TELEFONE utilizamos a anotação javax.persistence.JoinTable.
Para informar que a coluna PESSOA_ID da tabela PESSOA_TELEFONE é a coluna chave estrangeira para a tabela PESSOA e para informar que a coluna TELEFONE_ID da tabela PES-SOA_TELEFONE é a chave estrangeira para a tabela TELEFONE utilizamos a anotação ja-vax.persistence.JoinColumn.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; /** * Classe utilizada para representar uma Pessoa. */ @Entity public class Pessoa implements Serializable { private static final long serialVersionUID = -1905907502453138175L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String nome; private String cpf; @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinTable(name="PESSOA_TELEFONE", joinColumns={@JoinColumn(name = "PESSOA_ID")}, inverseJoinColumns={@JoinColumn(name = "TELEFONE_ID")}) private List<Telefone> telefones; public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } public Long getId() { return id; } public void setId(Long id) { this.id = id; }
______________________________________________________________________________________________
Curso Técnico em Informática 180 Programação Java
public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List<Telefone> getTelefones() { return telefones; } public void setTelefones(List<Telefone> telefones) { this.telefones = telefones; } }
javax.persistence.JoinTable - esta anotação é utilizada para definir uma tabela que será utilizada
na associação de um-para-muitos ou de muitos-para-muitos.
Propriedade Descrição
catalog O catalogo da tabela.
inverseJoinColumns Chave estrangeira para realizar a associação com a tabela que não é dona do relacionamento.
joinColumns Chave estrangeira para realizar a associação com a tabela que é dona do relacionamento.
name Nome da tabela de associação.
schema Esquema da tabela.
uniqueConstraints Regras que podem ser adicionadas na tabela.
Na entidade Aluno definimos que um aluno possui vários telefones através do atri-
buto List<Telefone> telefones e adicionamos a anotação javax.persistence.OneToMany para in-
formar que o relacionamento de Aluno para Telefone é de Um-para-Muitos.
Para informar que vamos utilizar a tabela ALUNO_TELEFONE para realizar a associação
entre as tabelas ALUNO e TELEFONE utilizamos a anotação javax.persistence.JoinTable.
Para informar que a coluna ALUNO_ID da tabela ALUNO_TELEFONE é a coluna chave
estrangeira para a tabela ALUNO e para informar que a coluna TELEFONE_ID da tabela
ALUNO_TELEFONE é a chave estrangeira para a tabela TELEFONE utilizamos a anotação ja-
vax.persistence.JoinColumn.
package pbc.jpa.exemplo.modelo; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; /** * Classe utilizada para representar uma entidade Aluno.
______________________________________________________________________________________________
Curso Técnico em Informática 181 Programação Java
*/ @Entity public class Aluno { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String nome; private Long matricula; @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinTable(name="ALUNO_TELEFONE", joinColumns={@JoinColumn(name = "ALUNO_ID")}, inverseJoinColumns={@JoinColumn(name = "TELEFONE_ID")}) private List<Telefone> telefones; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Long getMatricula() { return matricula; } public void setMatricula(Long matricula) { this.matricula = matricula; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List<Telefone> getTelefones() { return telefones; } public void setTelefones(List<Telefone> telefones) { this.telefones = telefones; } }
Agora vamos declarar a entidade Telefone, note que esta entidade não conhece as associações
que são criadas para ela.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * Classe utilizada para representar um Telefone. */ @Entity public class Telefone implements Serializable { private static final long serialVersionUID = 7526502149208345058L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;
______________________________________________________________________________________________
Curso Técnico em Informática 182 Programação Java
private String tipo; private Integer numero; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getNumero() { return numero; } public void setNumero(Integer numero) { this.numero = numero; } public String getTipo() { return tipo; } public void setTipo(String tipo) { this.tipo = tipo; } }
Para testar o cadastro de Aluno e Telefone vamos criar a classe AlunoDAO para salvar, alterar,
consultar por id e apagar os registro do aluno e telefone.
package pbc.jpa.exemplo.dao; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import pbc.jpa.exemplo.modelo.Aluno; /** * Classe DAO para manipular as informações do * Aluno no banco de dados. */ public class AlunoDAO { private EntityManager getEntityManager() { EntityManagerFactory factory = null; EntityManager entityManager = null; try { //Obtem o factory a partir da unidade de persistência. factory = Persistence.createEntityManagerFactory ("UnidadeDePersistencia"); //Cria um entity manager. entityManager = factory.createEntityManager(); } finally { factory.close(); } return entityManager; } public Aluno consultarPorId(Long id) { EntityManager entityManager = getEntityManager(); Aluno aluno = null; try { aluno = entityManager.find(Aluno.class, id); } finally {
______________________________________________________________________________________________
Curso Técnico em Informática 183 Programação Java
entityManager.close(); } return aluno; } public Aluno salvar(Aluno aluno) { EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); System.out.println("Salvando as informações do aluno."); /* Verifica se o aluno ainda não está salvo no banco de dados. */ if(aluno.getId() == null) { entityManager.persist(aluno); } else { aluno = entityManager.merge(aluno); } // Finaliza a transação. entityManager.getTransaction().commit(); } catch(Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } // Retorna o aluno salvo. return aluno; } public void apagar(Long id) { EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); // Consulta o aluno na base de dados através do seu ID. Aluno aluno = entityManager.find(Aluno.class, id); System.out.println("Excluindo o aluno: " + aluno.getNome()); // Remove o aluno da base de dados. entityManager.remove(aluno); // Finaliza a transação. entityManager.getTransaction().commit(); } catch(Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } } }
Vamos criar a classe AlunoDAOTeste que utiliza a classe AlunoDAO para salvar, alterar, consultar
por id e apagar os registros de aluno e telefone:
______________________________________________________________________________________________
Curso Técnico em Informática 184 Programação Java
package pbc.jpa.exemplo.dao; import java.util.ArrayList; import java.util.List; import pbc.jpa.exemplo.modelo.Aluno; import pbc.jpa.exemplo.modelo.Telefone; /** * Classe utilizada para testar as operações do * banco de dados referente ao Aluno. */ public class AlunoDAOTeste { public static void main(String[] args) { AlunoDAO dao = new AlunoDAO(); //Cria uma aluno. Aluno aluno = new Aluno(); aluno.setNome("Rafael"); aluno.setMatricula(123456L); //Cria o telefone residencial do aluno. Telefone telefone = new Telefone(); telefone.setTipo("RES"); telefone.setNumero(12345678); //Cria o telefone celular do aluno. Telefone telefone2 = new Telefone(); telefone2.setTipo("CEL"); telefone2.setNumero(87654321); //Cria uma lista de telefones e guarda dentro do aluno. List<Telefone> telefones = new ArrayList<Telefone>(); telefones.add(telefone); telefones.add(telefone2); aluno.setTelefones(telefones); System.out.println("Salva as informações do aluno."); aluno = dao.salvar(aluno); System.out.println("Consulta o aluno que foi salvo."); Aluno alunoConsultado = dao.consultarPorId(aluno.getId()); System.out.println(aluno.getNome()); for(Telefone tel : aluno.getTelefones()) { System.out.println(tel.getTipo() + " - " + tel.getNumero()); } //Cria o telefone comercial do aluno. Telefone telefone3 = new Telefone(); telefone3.setTipo("COM"); telefone3.setNumero(55554444); //Adiciona o novo telefone a lista de telefone do aluno. alunoConsultado.getTelefones().add(telefone3);
______________________________________________________________________________________________
Curso Técnico em Informática 185 Programação Java
System.out.println("Atualiza as informações do aluno."); alunoConsultado = dao.salvar(alunoConsultado); System.out.println(alunoConsultado.getNome()); for(Telefone tel : alunoConsultado.getTelefones()) { System.out.println(tel.getTipo() + " - " + tel.getNumero()); } System.out.println("Apaga o registro do aluno."); dao.apagar(alunoConsultado.getId()); } }
Quando executamos a classe AlunoDAOTeste temos a seguinte saída no console:
Salva as informações do aluno: Hibernate: insert into Aluno (matricula, nome) values (?, ?) Hibernate: insert into Telefone (numero, tipo) values (?, ?) Hibernate: insert into Telefone (numero, tipo) values (?, ?) Hibernate: insert into ALUNO_TELEFONE (ALUNO_ID, TELEFONE_ID) values (?, ?) Hibernate: insert into ALUNO_TELEFONE (ALUNO_ID, TELEFONE_ID) values (?, ?)
Consulta o aluno que foi salvo: Hibernate: select aluno0_.id as id21_1_, aluno0_.matricula as matricula21_1_, aluno0_.nome as nome21_1_, telefones1_.ALUNO_ID as ALUNO1_3_, telefone2_.id as TELEFONE2_3_, telefone2_.id as id18_0_, telefone2_.numero as numero18_0_, telefone2_.tipo as tipo18_0_ from Aluno aluno0_ left outer join ALUNO_TELEFONE telefones1_ on aluno0_.id=telefones1_.ALUNO_ID left outer join Telefone telefone2_ on telefones1_.TELEFONE_ID=telefone2_.id where aluno0_.id=?Rafael RES - 12345678 CEL - 87654321
Atualiza as informações do aluno:
Hibernate: select aluno0_.id as id38_1_, aluno0_.matricula as matricula38_1_, aluno0_.nome as nome38_1_, telefones1_.ALUNO_ID as ALUNO1_3_, telefone2_.id as TELEFONE2_3_, telefone2_.id as id35_0_, telefone2_.numero as numero35_0_, telefone2_.tipo as tipo35_0_ from Aluno aluno0_ left outer join ALUNO_TELEFONE telefones1_ on aluno0_.id=telefones1_.ALUNO_ID left outer join Telefone telefone2_ on telefones1_.TELEFONE_ID=telefone2_.id where aluno0_.id=? Hibernate: insert into Telefone (numero, tipo) values (?, ?) Hibernate: delete from ALUNO_TELEFONE where ALUNO_ID=? Hibernate: insert into ALUNO_TELEFONE (ALUNO_ID, TELEFONE_ID) values (?, ?) Hibernate: insert into ALUNO_TELEFONE (ALUNO_ID, TELEFONE_ID) values (?, ?)
______________________________________________________________________________________________
Curso Técnico em Informática 186 Programação Java
Hibernate: insert into ALUNO_TELEFONE (ALUNO_ID, TELEFONE_ID) values (?, ?) Rafael RES - 12345678 CEL - 87654321 COM - 55554444
Apaga o registro do aluno: Hibernate: select aluno0_.id as id55_1_, aluno0_.matricula as matricula55_1_, aluno0_.nome as nome55_1_, telefones1_.ALUNO_ID as ALUNO1_3_, telefone2_.id as TELEFONE2_3_, telefone2_.id as id52_0_, telefone2_.numero as numero52_0_, telefone2_.tipo as tipo52_0_ from Aluno aluno0_ left outer join ALUNO_TELEFONE telefones1_ on aluno0_.id=telefones1_.ALUNO_ID left outer join Telefone telefone2_ on telefones1_.TELEFONE_ID=telefone2_.id where aluno0_.id=? Hibernate: delete from ALUNO_TELEFONE where ALUNO_ID=? Hibernate: delete from Telefone where id=? Hibernate: delete from Telefone where id=? Hibernate: delete from Telefone where id=? Hibernate: delete from Aluno where id=?
Muitos-para-Muito (ManyToMany) - este relacionamento informa que muitos registros de uma
entidade estão relacionados com muitos registros de outra entidade:
Script do banco de dados:
CREATE TABLE Projeto ( id number(5) NOT NULL PRIMARY_KEY, nome varchar2(200) NOT NULL ); CREATE TABLE Funcionario ( id number(5) NOT NULL PRIMARY_KEY, nome varchar2(200) NOT NULL ); CREATE TABLE Projeto_Funcionario ( projeto_id number(5), funcionario_id number(5) );
Note que nesse caso precisamos utilizar uma tabela intermediária entre Projeto e Funcionario, para evitar duplicar dados (normalização) desnecessários no banco de dados. Através da tabela Pro-jeto_Funcionario criamos o relacionamento entre Projeto e Funcionario.
______________________________________________________________________________________________
Curso Técnico em Informática 187 Programação Java
Modelo UML:
Neste exemplo definimos que um Projeto tem vários funcionários, e um Funcionario participa de vários projetos, portanto temos um relacionamento bidirecional de muitos-para-muitos. Código fonte das classes com o relacionamento:
A entidade Projeto possui um relacionamento de muitos-para-muitos com a entidade Fun-cionario, para definir esta associação utilizamos a anotação javax.persistence.ManyToMany, note que utilizamos a propriedade mappedBy da anotação ManyToMany para informar que o Pro-jeto é o dono do relacionamento.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToMany; /** * Classe utilizada para representar um projeto. */ @Entity public class Projeto implements Serializable { private static final long serialVersionUID = 1081869386060246794L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String nome; @ManyToMany(mappedBy="projetos", cascade=CascadeType.ALL) private List<Funcionario> desenvolvedores; public List<Funcionario> getDesenvolvedores() { return desenvolvedores; } public void setDesenvolvedores(List<Funcionario> desenvolvedores) { this.desenvolvedores = desenvolvedores; } public Long getId() { return id; }
______________________________________________________________________________________________
Curso Técnico em Informática 188 Programação Java
public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } }
javax.persistence.ManyToMany - esta anotação define uma associação com outra entidade que
tenha a multiplicidade de muitos-para-muitos.
Propriedade Descrição
cascade As operações que precisam ser refletidas no alvo da associação.
fetch Informa se o alvo da associação precisa ser obtido apenas quando for necessário ou se sempre deve trazer.
mappedBy Informa o atributo que é dono do relacionamento.
targetEntity A classe entity que é alvo da associação.
A entidade Funcionario possui um relacionamento de muitos-para-muitos com a entidade
Projeto, para definir esta associação utilizamos a anotação javax.persistence.ManyToMany.
Para informar que vamos utilizar a tabela PROJETO_FUNCIONARIO para realizar a asso-
ciação entre PROJETO e FUNCIONARIO utilizamos a anotação javax.persistence.JoinTable.
Para informar que a coluna PROJETO_ID da tabela PROJETO_FUNCIONARIO é a coluna
chave estrangeira para a tabela PROJETO e para informar que a coluna FUNCIONARIO_ID da
tabela PROJETO_FUNCIONARIO é a chave estrangeira para a tabela FUNCIONARIO utilizamos
a anotação javax.persistence.JoinColumn.
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; /** * Classe utilizada para representar um Funcionário. */ @Entity public class Funcionario implements Serializable { private static final long serialVersionUID = -9109414221418128481L; @Id
______________________________________________________________________________________________
Curso Técnico em Informática 189 Programação Java
@GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String nome; @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name="PROJETO_FUNCIONARIO", joinColumns={@JoinColumn(name="PROJETO_ID")}, inverseJoinColumns={@JoinColumn(name="FUNCIONARIO_ID")}) private List<Projeto> projetos; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List<Projeto> getProjetos() { return projetos; } public void setProjetos(List<Projeto> projetos) { this.projetos = projetos; } }
12.13 Cascade Type
Com o CascadeType podemos definir a forma como serão propagadas as operações em
cascata de uma Entity para suas referencias.
PERSIST – Quando salvar a Entidade A, também será salvo todas as Entidades B associa-
das.
MERGE – Quando atual as informações da Entidade A, também será atualizado no banco
de dados todas as informações das Entidades B associadas.
REMOVE – Quando remover a Entidade A, também será removida todas as entidades B
associadas.
REFRESH – Quando houver atualização no banco de dados na Entidade A, todas as enti-
dades B associadas serão atualizadas.
ALL – Corresponde a todas as operações acima (MERGE, PERSIST, REFRESH e RE-
MOVE).
12.14 FetchType Com o FetchType podemos definir a forma como serão trazidos os relacionamentos, pode-
mos fazer de duas formas:
______________________________________________________________________________________________
Curso Técnico em Informática 190 Programação Java
EAGER - Traz todas as entidades que estão relacionadas, ou seja, se a Entidade A possui
um relacionamento com a Entidade B, então quando consultar a Entidade A, também será
consultado suas referencias na Entidade B.
LAZY - Não traz as entidades que estão relacionadas, ou seja, se a Entidade A possui um
relacionamento com a Entidade B, então quando consultar a Entidade A só serão retornadas
as informações referentes a esta Entidade.
Exemplo de relacionamento LAZY, desse modo o corpo da mensagem é consultado apenas
quando houver a necessidade:
@Entity public class Mensagem { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String assunto; @Temporal(TemporalType.DATE) private Date dataEnvio; @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY) private MensagemCorpo mensagemCorpo; }
Nesse exemplo utilizamos a enum FetchType.LAZY no relacionamento um-para-um para
informar que quando consultarmos a entidade Mensagem, não queremos consultar a entidade Men-
sagemCorpo ao mesmo tempo.
Exercícios: Neste exercício vamos abordar como funciona os relacionamentos entre as entidades, va-
mos utilizar o relacionamento entre as entidades Cliente e Endereco, quando salvar o cliente tam-
bém deve salvar o endereço e quando o cliente for consultado deve trazer também as informações
do endereço.
Crie o seguinte banco de dados:
CREATE SEQUENCE CLI_SEQ INCREMENT BY 1 START WITH 1 NOCACHE NOCYCLE; CREATE SEQUENCE END_SEQ INCREMENT BY 1 START WITH 1 NOCACHE NOCYCLE; CREATE TABLE ENDERECO ( id number(5) NOT NULL PRIMARY KEY, estado VARCHAR2(50) NOT NULL, cidade VARCHAR2(50) NOT NULL, bairro VARCHAR2(50) NOT NULL, logradouro VARCHAR2(50) NOT NULL, complemento VARCHAR2(50) NOT NULL ); CREATE TABLE CLIENTE (
______________________________________________________________________________________________
Curso Técnico em Informática 191 Programação Java
id number(5) NOT NULL PRIMARY KEY, nome VARCHAR2(100) NOT NULL, endereco_id number(5) NOT NULL );
Crie um projeto Java chamado ExercicioJPA4, adicione as bibliotecas Hibernate JPA e Driver da
Oracle (ojdbc6.jar) ou do Mysql (Caso tenha optado por esse banco de dados) e crie:
Classe entity para representar um endereço com os atributos id, estado, cidade, bairro, lo-
gradouro e complemento.
package pbc.jpa.exercicio4.modelo; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.SequenceGenerator; /** * Classe utilizada para representar um Endereço. */ @Entity @SequenceGenerator(name = "ENDERECO_SEQ", sequenceName = "END_SEQ", initialValue = 1, allocationSize = 1) public class Endereco implements Serializable { private static final long serialVersionUID = 5331450149454053703L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ENDERECO_SEQ") private Long id; private String estado; private String cidade; private String bairro; private String logradouro; private String complemento; public String getBairro() { return bairro; } public void setBairro(String bairro) { this.bairro = bairro; } public String getCidade() { return cidade; } public void setCidade(String cidade) { this.cidade = cidade; } public String getComplemento() { return complemento; } public void setComplemento(String complemento) {
______________________________________________________________________________________________
Curso Técnico em Informática 192 Programação Java
this.complemento = complemento; } public String getEstado() { return estado; } public void setEstado(String estado) { this.estado = estado; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLogradouro() { return logradouro; } public void setLogradouro(String logradouro) { this.logradouro = logradouro; } }
Classe entity para representar um cliente com id, nome e endereço, note que vamos utilizar
a anotação javax.persistence.OneToOne para definir o relacionamento de um-para-um en-
tre as entidades Cliente e Endereco.
package pbc.jpa.exercicio4.modelo; import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.SequenceGenerator; /** * Classe utilizada para representar um Cliente. */ @Entity @SequenceGenerator(name = "CLIENTE_SEQ", sequenceName = "CLI_SEQ", initialValue = 1, allocationSize = 1) public class Cliente implements Serializable { private static final long serialVersionUID = 4521490124826140567L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CLIENTE_SEQ") private Long id; private String nome; @OneToOne(cascade=CascadeType.ALL) private Endereco endereco; public Endereco getEndereco() { return endereco; } public void setEndereco(Endereco endereco) {
______________________________________________________________________________________________
Curso Técnico em Informática 193 Programação Java
this.endereco = endereco; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } }
Crie o arquivo persistence.xml dentro da pasta META-INF do projeto, note que neste ar-quivo vamos informar qual o banco de dados iremos utilizar e quais classes são entidades do banco:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="ExercicioJPA4PU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>pbc.jpa.exercicio3.modelo.Endereco</class> <class>pbc.jpa.exercicio3.modelo.Cliente</class> <properties> <property name="hibernate.connection.username" value="usuario"/> <property name="hibernate.connection.password" value="senha"/> <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/> <property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:XE"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9Dialect"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>
Crie a classe ClienteDAO que será responsável por utilizar o EntityManager para manipu-
lar (salvar, alterar, remover e consultar por id) as informações referentes ao Cliente.
package pbc.jpa.exercicio4.dao; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import pbc.jpa.exercicio4.modelo.Cliente; import pbc.jpa.exercicio4.modelo.Endereco;
______________________________________________________________________________________________
Curso Técnico em Informática 194 Programação Java
/** * Classe utilizada para fazer as operações de * banco de dados sobre a entity Cliente. */ public class ClienteDAO { /** * Método utilizado para obter o entity manager. * @return */ private EntityManager getEntityManager() { EntityManagerFactory factory = null; EntityManager entityManager = null; try { //Obtém o factory a partir da unidade de persistencia. factory = Persistence.createEntityManagerFactory ("ExercicioJPA4PU"); //Cria um entity manager. entityManager = factory.createEntityManager(); } finally { factory.close(); } return entityManager; } /** * Método que salva ou atualiza as informações do cliente. * @param cliente * @return * @throws java.lang.Exception */ public Cliente salvar(Cliente cliente) throws Exception { EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); System.out.println("Salvando as informações do cliente."); /* Verifica se o cliente ainda não está salvo no banco de dados. */ if(cliente.getId() == null) { entityManager.persist(cliente); } else { cliente = entityManager.merge(cliente); } // Finaliza a transação. entityManager.getTransaction().commit(); } catch(Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } // Retorna o cliente salvo.
______________________________________________________________________________________________
Curso Técnico em Informática 195 Programação Java
return cliente; } /** * Método que apaga as informações do cliente * do banco de dados. * @param id */ public void apagar(Long id) { EntityManager entityManager = getEntityManager(); try { // Inicia uma transação com o banco de dados. entityManager.getTransaction().begin(); // Consulta o cliente na base de dados através do seu ID. Cliente cliente = entityManager.find(Cliente.class, id); System.out.println("Excluindo o cliente: " + cliente.getNome()); // Remove o cliente da base de dados. entityManager.remove(cliente); // Finaliza a transação. entityManager.getTransaction().commit(); } catch(Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } } /** * Consulta o cliente pelo ID. * @param id * @return */ public Cliente consultarPorId(Long id) { EntityManager entityManager = getEntityManager(); Cliente cliente = null; try { //Consulta o cliente pelo ID. cliente = entityManager.find(Cliente.class, id); } finally { entityManager.close(); } //Retorna o cliente consultado. return cliente; } }
Vamos desenvolver a interface gráfica em SWING que será responsável por chamar o ClienteDAO
para executar as operações no banco de dados.
______________________________________________________________________________________________
Curso Técnico em Informática 196 Programação Java
Código fonte da tela de cadastro do cliente.
Observação: este código não está completo, ele possui apenas implementado o código dos botões.
package pbc.jpa.exercicio4.tela; import javax.swing.JOptionPane; import pbc.jpa.exercicio4.dao.ClienteDAO; import pbc.jpa.exercicio4.modelo.Cliente; import pbc.jpa.exercicio4.modelo.Endereco; /** * Classe utilizada para representar o cadastro do Cliente. */ public class CadastroCliente extends javax.swing.JFrame { private static final long serialVersionUID = -6011351657657723638L; public CadastroCliente() { initComponents(); } /** * Código para montar a tela. */ @SuppressWarnings("unchecked") private void initComponents() { //Código que monta a tela mostrada na imagem anterior. } /** * Botão que salva as informações do cliente. * * @param evt */ private void botaoSalvarActionPerformed( java.awt.event.ActionEvent evt) { try { //Cria um objeto endereco;
______________________________________________________________________________________________
Curso Técnico em Informática 197 Programação Java
Endereco e = new Endereco(); e.setEstado(this.estado.getText()); e.setCidade(this.cidade.getText()); e.setBairro(this.bairro.getText()); e.setLogradouro(this.logradouro.getText()); e.setComplemento(this.complemento.getText()); //Cria um objeto cliente. Cliente c = new Cliente(); c.setNome(this.nome.getText()); c.setEndereco(e); //Salva o cliente. ClienteDAO dao = new ClienteDAO(); c = dao.salvar(c); JOptionPane.showMessageDialog(this, "Cliente " + c.getId() + " - " + c.getNome(), "INFORMAÇÃO", JOptionPane.INFORMATION_MESSAGE); limparDados(); } catch (Exception ex) { JOptionPane.showMessageDialog(this, ex.getMessage(), "ERRO", JOptionPane.ERROR_MESSAGE); } } /** * Botão que consulta as informações do cliente. * * @param evt */ private void botaoConsultarActionPerformed( java.awt.event.ActionEvent evt) { try { ClienteDAO dao = new ClienteDAO(); Cliente c = dao.consultarPorId(Long.valueOf(this.id.getText())); if(c != null) { this.nome.setText(c.getNome()); this.estado.setText(c.getEndereco().getEstado()); this.cidade.setText(c.getEndereco().getCidade()); this.bairro.setText(c.getEndereco().getBairro()); this.logradouro.setText(c.getEndereco().getLogradouro()); this.complemento.setText(c.getEndereco().getComplemento()); } else { limparDados(); JOptionPane.showMessageDialog(this, "Cliente não foi encontrado!", "ERRO", JOptionPane.ERROR_MESSAGE); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(this, "O campo código precisa ser um número inteiro",
______________________________________________________________________________________________
Curso Técnico em Informática 198 Programação Java
"ERRO", JOptionPane.ERROR_MESSAGE); } } /** * Botão para limpar as informações do formulario * para cadastrar um novo cliente. * * @param evt */ private void botaoNovoActionPerformed( java.awt.event.ActionEvent evt) { limparDados(); } /** * Botão para remover as informações referentes a um cliente. * * @param evt */ private void botaoApagarActionPerformed( java.awt.event.ActionEvent evt) { try { ClienteDAO dao = new ClienteDAO(); dao.excluir(Long.valueOf(this.id.getText())); limparDados(); JOptionPane.showMessageDialog(this, "As informações do cliente foram apagadas do sistema.", "INFORMAÇÃO", JOptionPane.INFORMATION_MESSAGE); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(this, "O campo código precisa ser um número inteiro", "ERRO", JOptionPane.ERROR_MESSAGE); } } /** * Limpa os dados do formulario. */ private void limparDados() { this.id.setText(null); this.nome.setText(null); this.estado.setText(null); this.cidade.setText(null); this.bairro.setText(null); this.logradouro.setText(null); this.complemento.setText(null); } /** * @param args the command line arguments */ public static void main(String args[]) {
______________________________________________________________________________________________
Curso Técnico em Informática 199 Programação Java
java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new CadastroCliente().setVisible(true); } }); } private javax.swing.JTextField bairro; private javax.swing.JButton botaoApagar; private javax.swing.JButton botaoConsultar; private javax.swing.JButton botaoNovo; private javax.swing.JButton botaoSalvar; private javax.swing.JTextField cidade; private javax.swing.JTextField complemento; private javax.swing.JTextField estado; private javax.swing.JTextField id; private javax.swing.JLabel labelBairro; private javax.swing.JLabel labelCadastroCliente; private javax.swing.JLabel labelCidade; private javax.swing.JLabel labelCodigo; private javax.swing.JLabel labelComplemento; private javax.swing.JLabel labelEstado; private javax.swing.JLabel labelLogradouro; private javax.swing.JLabel labelNome; private javax.swing.JTextField logradouro; private javax.swing.JTextField nome; }
Exercicio:
Neste exercício vamos desenvolver uma aplicação swing para implementar o seguinte requisito
de sistema:
Precisamos controlar as vendas de instrumentos musicais, desenvolva uma aplicação para ca-
dastrar, alterar, consultar pelo código e remover os instrumentos musicais (marca, modelo e
preço). Também devemos cadastrar as vendas feitas para um cliente, onde o cliente (nome, cpf e
telefone) pode comprar diversos instrumentos musicais. Não temos a necessidade de controlar o
estoque dos produtos, pois apenas será vendido os itens que estão nas prateleiras.
12.15 Consultas com JPAQL
Utilizando JPA podemos também adicionar consultas personalizadas, para criação das con-
sultas utilizamos a Java Persistence API Query Language (JPAQL) que é uma linguagem muito
similar ao Structured Query Language (SQL) com a diferença que é mais voltado para orientação
a objetos, onde facilita a navegação pelos objetos. Nesse exemplo vamos abordar o seguinte ce-
nário, empréstimo de livros para os clientes da biblioteca, temos as seguintes tabelas:
______________________________________________________________________________________________
Curso Técnico em Informática 200 Programação Java
Script do banco de dados:
CREATE TABLE Livro ( id number(5) NOT NULL, titulo varchar2(200) NOT NULL, autor varchar2(200) NOT NULL, isbn varchar2(20) NOT NULL, paginas number(5) NOT NULL, PRIMARY KEY(id) ); CREATE TABLE Cliente ( id number(5) NOT NULL, nome varchar2(200) NOT NULL, cpf varchar2(14) NOT NULL, telefone varchar2(9) NOT NULL, PRIMARY KEY(id) ); CREATE TABLE Emprestimo ( id number(5) NOT NULL, livro_id number(5) NOT NULL, cliente_id number(5) NOT NULL, dataEmprestimo date NOT NULL, dataDevolucao date, PRIMARY KEY(id) ); INSERT INTO Livro (id, titulo, autor, isbn, paginas) VALUES (1, 'Almoçando com Java', 'Sakurai', '111-11-1111-111-1', 325);
______________________________________________________________________________________________
Curso Técnico em Informática 201 Programação Java
INSERT INTO Livro (id, titulo, autor, isbn, paginas) VALUES (2, 'Classes Java em fila indiana', 'Cristiano', '222-22-2222-222-2', 120); INSERT INTO Livro (id, titulo, autor, isbn, paginas) VALUES (3, 'Java em todo lugar', 'Sakurai', '333-33-3333-333-3', 543); INSERT INTO Livro (id, titulo, autor, isbn, paginas) VALUES (4, 'Viajando no Java', 'Cristiano', '444-44-4444-444-4', 210); INSERT INTO Cliente (id, nome, cpf, telefone) VALUES (1, 'Marcelo', '333.333.333-33', '9999-8888'); INSERT INTO Cliente (id, nome, cpf, telefone) VALUES (2, 'Ana', '222.222.222-22', '7777-6666');
Utilizando o EJB-QL podemos criar diversas formas de consultas, onde podemos especificar as
projeções, associações, restrições e outros. Exemplos de consultas:
Consultar todos os empréstimos:
SELECT e FROM Emprestimo e
Consultar a quantidade de empréstimo por livro:
SELECT count(e) FROM Emprestimo e WHERE e.livro.id = :id Consultar os empréstimos por titulo do livro:
SELECT e FROM Emprestimo e, Livro l WHERE e.livro.id = l.id AND l.titulo LIKE :titulo As consultas podem ser criadas junto com as entidades:
package pbc.jpa.exemplo.modelo; import java.io.Serializable; import java.util.Date; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Temporal; import javax.persistence.TemporalType; /**
______________________________________________________________________________________________
Curso Técnico em Informática 202 Programação Java
* Classe utilizada para representar o emprestimo * de um livro para um cliente. */ @NamedQueries({ @NamedQuery(name = "Emprestimo.consultarTodos", query= "SELECT e FROM Emprestimo e"), @NamedQuery(name = "Emprestimo.qtdEmprestimosPorLivro", query = " SELECT count(e) " + " FROM Emprestimo e " + " WHERE e.livro.id = :id "), @NamedQuery(name = "Emprestimo.consultarTodosPorTituloLivro", query = " SELECT e " + " FROM Emprestimo e, Livro l " + " WHERE e.livro.id = l.id " + " AND l.titulo LIKE :titulo ") }) @Entity public class Emprestimo implements Serializable { private static final long serialVersionUID = 7516813189218268079L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @ManyToOne(cascade=CascadeType.REFRESH, fetch=FetchType.EAGER) private Livro livro; @ManyToOne(cascade=CascadeType.REFRESH, fetch=FetchType.EAGER) private Cliente cliente; @Temporal(TemporalType.DATE) private Date dataEmprestimo; @Temporal(TemporalType.DATE) private Date dataDevolucao; public Cliente getCliente() { return cliente; } public void setCliente(Cliente cliente) { this.cliente = cliente; } public Date getDataDevolucao() { return dataDevolucao; } public void setDataDevolucao(Date dataDevolucao) { this.dataDevolucao = dataDevolucao; } public Date getDataEmprestimo() { return dataEmprestimo; } public void setDataEmprestimo(Date dataEmprestimo) { this.dataEmprestimo = dataEmprestimo; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Livro getLivro() { return livro; } public void setLivro(Livro livro) { this.livro = livro; }
______________________________________________________________________________________________
Curso Técnico em Informática 203 Programação Java
}
12.15.1 Interface Query
A interface Query é responsável por:
Fazer as consultas;
Executar updates;
Passar parâmetros para consulta;
Pegar um simples resultado;
Pegar uma lista de resultados.
Para executar uma consulta utilizamos a interface javax.persistence.Query e criamos uma Query a
partir do EntityManager, exemplo:
public List<Emprestimo> consultarTodos() {
EntityManager em = getEntityManager();
Query query = em.createNamedQuery("Emprestimo.consultarTodos");
return query.getResultList();
}
Nesse exemplo estamos utilizando a EntityManager para criar uma consulta nomeada atra-
vés do método getNamedQuery e passamos o nome da consulta "Emprestimo.consultarTo-
dos" declarado na entidade.
Através da EntityManager podemos utilizar o método createQuery para criar a consulta e já decla-
rar todo o código dela, podendo criar uma consulta um pouco mais personalizada:
Query query = em.createQuery("SELECT c FROM Cliente c");
Também podemos criar uma consultas nativa para uma base de dados especifica:
Query query = em.createNativeQuery("SELECT * FROM Cliente");
Para executar uma consulta podemos ter como resposta um simples objeto ou uma lista de obje-tos.
Neste exemplo vamos executar uma consulta que retorna uma lista de objetos:
Query query = em.createNamedQuery("Cliente.consultarTodosClientes"); List<Cliente> clientes = (List<Cliente>) query.getResultList(); Quando utilizamos o método getResultList da interface Query é retornado uma lista de entidades.
Consulta que retorna um único objeto:
Query query = em.createNamedQuery("Emprestimo.qtdEmprestimosPorLivro"); Long quantidade = (Long) query.getSingleResult();
______________________________________________________________________________________________
Curso Técnico em Informática 204 Programação Java
Quando utilizamos o método getSingleResult da interface Query é retornado apenas um
objeto. Este método pode lançar também a exceção javax.persistence.NoResultExcep-
tion quando a consulta não retorna nenhum resultado ou também uma exceção javax.persis-
tence.NonUniqueResultException quando você espera retornar apenas um objeto e a consulta
acaba retornando mais de um objeto.
Através da interface Query podemos passando parâmetros para a consulta através do mé-
todo setParameter:
public List<Emprestimo> consultarTodosPorTituloLivro (String tituloLivro) { EntityManager entityManager = getEntityManager(); Query query = entityManager.createNamedQuery ("Emprestimo.consultarTodosPorTituloLivro"); query.setParameter("titulo", tituloLivro); return query.getResultList(); }
Exemplo de classe DAO que executa as operações: salvar, alterar, remover, consultar por id, con-
sultar todos os empréstimos, consultar a quantidade de empréstimos de um livro e consultar todos
os empréstimos de um livro.
package pbc.jpa.exemplo.dao; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import pbc.jpa.exemplo.modelo.Emprestimo; /** * Classe utilizada para representar as * operações sobre a entidade emprestimo. */ public class EmprestimoDAO { public EntityManager getEntityManager() { EntityManagerFactory factory = null; EntityManager entityManager = null; try { factory = Persistence.createEntityManagerFactory ("UnidadeDePersistencia"); entityManager = factory.createEntityManager(); } finally { factory.close(); } return entityManager; } public Emprestimo consultarPorId(Long id) {
______________________________________________________________________________________________
Curso Técnico em Informática 205 Programação Java
EntityManager entityManager = getEntityManager(); Emprestimo emprestimo = null; try { emprestimo = entityManager.find(Emprestimo.class, id); } finally { entityManager.close(); } return emprestimo; } public Emprestimo salvar(Emprestimo emprestimo) { EntityManager entityManager = getEntityManager(); try { entityManager.getTransaction().begin(); if(emprestimo.getId() == null) { entityManager.persist(emprestimo); } else { entityManager.merge(emprestimo); } entityManager.flush(); entityManager.getTransaction().commit(); } catch (Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } return emprestimo; } public void apagar(Long id) { EntityManager entityManager = getEntityManager(); try { entityManager.getTransaction().begin(); Emprestimo emprestimo = entityManager. find(Emprestimo.class, id); entityManager.remove(emprestimo); entityManager.flush(); entityManager.getTransaction().commit(); } catch (Exception ex) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } } public List<Emprestimo> consultarTodos() { EntityManager entityManager = getEntityManager(); Query query = entityManager.createNamedQuery ("Emprestimo.consultarTodos"); return query.getResultList();
______________________________________________________________________________________________
Curso Técnico em Informática 206 Programação Java
} public Long getQtdEmprestimosPorLivro(Long id) { EntityManager entityManager = getEntityManager(); Query query = entityManager.createNamedQuery ("Emprestimo.qtdEmprestimosPorLivro"); query.setParameter("id", id); return (Long) query.getSingleResult(); } public List<Emprestimo> consultarTodosPorTituloLivro (String tituloLivro) { EntityManager entityManager = getEntityManager(); Query query = entityManager.createNamedQuery ("Emprestimo.consultarTodosPorTituloLivro"); query.setParameter("titulo", tituloLivro); return query.getResultList(); } }
Exercícios:
Seguindo como base o exercício anterior, agora vamos criar uma aplicação para realizar a
venda de um produto para um cliente.
Utilize as tabelas da figura a seguir para modelar o sistema.
Crie as entidades Produto, Cliente e Venda, DAOs e uma classe para teste.
Observação: Se quiser pode começar com uma carga prévia de clientes e produtos fazendo assim
apenas a parte das vendas.
Após isso amplie a aplicação para que seja possível vender vários produtos para um cliente.
______________________________________________________________________________________________
Curso Técnico em Informática 207 Programação Java
O que é o iReport? O iReport é uma ferramenta poderosa, intuitiva e fácil de usar que constrói relatórios
para JasperReports. O iReport é desenvolvido 100% em Java. Essa ferramenta permite ao
usuário gerar relatórios complexos com imagens, gráficos e subrelatórios. O iReport é integrado
com o JfreeChart, uma das bibliotecas Java de geração de gráficos mais difundidas. Com o iReport
é possível gerar relatórios em vários formatos incluindo
PDF, HTML, XML, XLS, CVS, entre outros.
O que é o JasperReports
JasperReport é a biblioteca de classes que torna possível gerar os relatórios.
O iReport é apenas uma interface gráfica que faz uso do JasperReports.
São as classes e métodos disponibilizados pelo JasperReports que serão usados para
efetivamente gerar e exportar os relatórios.
Instalando o iReport O iReport está disponível para download no site da SourceForge.net. O iReport e o
JasperReports são projetos dessa comunidade de desenvolvedores de software livre. O endereço
para download é:
http://ireport.sf.net
Para que o iReport funcione corretamente no seu sistema é necessário que você tenha a versão
mais atualizada do JDK instalada no seu sistema.
Caso você ainda não tenha o Java Development Kit (JDK) instalado no seu computador, você pode
fazer o download no site da Sun:
http://java.sun.com
A instalação do iReport é bastante simples. É preciso apenas descompactar o
arquivo .zip que você baixou do site da SourceForge.net. Ao descompactar esse arquivo ele
já vai criar toda a estrutura de diretórios necessários para que o iReport funcione. Uma vez
descompactado, basta executar o arquivo iReport.bat (para Windows), ou iReport.sh (para Linux),
que o iReport irá ser exeutado.
13.1 Acesso ao banco de Dados
Antes de mais nada devemos criar uma conexão com nossa fonte de dados:
1. Selecione o menu Datasources >> Connection/Datasources. A janela que aparece lista
todas as fontes de dados e conexões JDBC que você define. Clique no botão New para criar
uma nova conexão (ou datasource).
Relatórios
13
______________________________________________________________________________________________
Curso Técnico em Informática 208 Programação Java
2. Na janela que aparece escolha o tipo de conexão (no nosso caso Database JDBC
Connection). Na mesma janela dê um nome à conexão. Por exemplo, “BibliotecaPessoal
FB”.
3. No campo “JDBC Driver”, selecione o driver do seu banco. Caso não esteja listado, como
no nosso caso, especifique um de acordo com o seu SGBD. Para o Firebird, digite
“org.firebirdsql.jdbc.FBDriver”, lembrando que o driver deve estar no classpath.
4. Em “JDBC URL” digitamos o caminho para a nossa base de dados:
“jdbc:firebirdsql:localhost/3050:c://db//Acervo.fdb”
Obs.: A sintaxe da URL difere de SGBD para SGBD, consulte a documentação de seu banco
para saber a sintaxe exata. Repare também no caminho para a base de dados.
5. Em “Server Address” digite o caminho para servidor de banco de dados, no nosso caso
“localhost”.
Em “Database”, entre com o nome do banco (Acervo.fdb) ou do alias. Entramos, então, com
o user “sysdba” e password “masterkey”. Temos a possibilidade de salvar a senha marcando
a opção “Save password”.
______________________________________________________________________________________________
Curso Técnico em Informática 209 Programação Java
6. Para testarmos a conexão clicamos no botão “Test”. Não esqueça que o SGBD precisa
estar rodando.
Se tudo ocorreu bem a seguinte mensagem irá aparecer:
7. O próximo passo é ir ao menu “Build >> Set active connection”, escolhendo na janela que
aparece a conexão com a base que iremos utilizar para preencher o relatório, no nosso caso:
“BibilotecaPessoal FB”.
Obs.: É importante salientar que a configuração de uma conexão dentro do iReport não é
obrigatória, pois podemos utilizá-lo apenas para criar o design do relatório e compilá-lo. As tarefas
______________________________________________________________________________________________
Curso Técnico em Informática 210 Programação Java
de preenchimento, exportação para um formato (pdf, por exemplo), e visualização, ficam de
responsabilidade de uma classe Java. Porém, é conveniente, até mesmo para a realização dos
testes, termos um único ambiente que além de permitir a definição do layout, também permita
visualizarmos, em diversos formatos, o resultado do design e preenchimento do relatório através
de um simples botão (Run): . Para isso, é necessário que a conexão JDBC esteja funcionando.
13.2 iReport Wizard
Vamos criar o nosso primeiro relatório utilizando o Wizard do iReport. No menu File selecione
o item “Report Wizard”. A janela de diálogo irá guiar o processo para geração de um relatório. No
passo 1, conforme mostra a figura abaixo, devemos colocar qual o SQL que vamos usar para gerar
esse relatório. No nosso exemplo, vamos listar todo o conteúdo da tabela vendas.
No passo 2, vamos selecionar as colunas que desejamos mostrar no relatório. Vamos selecionar
todos os campos, conforme mostra a seguir
No passo 3, podemos escolher se queremos agrupar o resultado por alguma coluna. Nesse primeiro
exemplo vamos deixar em branco e seguir para o passo 4, conforme mostra a figura abaixo:
______________________________________________________________________________________________
Curso Técnico em Informática 211 Programação Java
No passo 4, vamos selecionar o layout do relatório. O iReport já tem alguns layouts default para
serem selecionados. Os layouts podem ser tabular ou dispostos em colunas. Vamos escolher
tabular e o layout classicT.xml, conforme mostra a figura a seguir.
No passo 5 basta clicar finish para finalizar a criação do seu relatório, conforme mostra a figura.
Agora para visualizar o seu relatório recém gerado, selecione no menu “Build”, a opção “JRViewer
preview”.
______________________________________________________________________________________________
Curso Técnico em Informática 212 Programação Java
Após selecionar o item mostrado na figura acima, clique no menu “Build” e selecione a opção
“Execute report (using active conn.)”. Vai aparecer uma janela pedindo para salvar o relatório. Salve
o relatório e a visualização deve aparecer, como mostra a figura abaixo.
Pronto você acaba de construir o primeiro relatório utilizando o iReport.
Exercícios: 1. Utilizando o Wizard do iReport, crie um relatório que liste todos os produtos e quantidades desses
produtos e a quantidade de cada um deles agrupados por estado.
2. Utilizando o Wizard do iReport, crie um relatório que apresente o total das quantidades de
produtos em cada estado. Utilize o SQL abaixo para efetuar a pesquisa:
• SELECT UF, SUM(QTDE) AS TOTAL FROM VENDAS GROUP BY UF
3. Com o Wizard do iReport crie um relatório “columnar” que mostre o nome e o preço dos produtos
da tabela produto.
a. Clique em File | Report Wizard;
b. Entre o comnado SQL “select * from produto”;
c. Clique Next;
d. Selecione as colunas “preco” e “nome” e clique Next;
e. Clique Next novamente;
f. Selecione “Columnar” da combobox de layout e clique no template classicC.xml. Clique
Next.
g. Clique em Finish;
h. Salve o relatório com o nome a sua escolha;
______________________________________________________________________________________________
Curso Técnico em Informática 213 Programação Java
i. Para visualizar o relatório clique em Build | Execute report (usinf active conn.).
13.3 Modelo Relatório iReport 13.3.1 Estrutura de um relatório
Os relatório do JasperReports gerados pelo iReport tem a seguinte estrutura conforme
mostra a tabela abaixo.
As sessões 1. Título e 11. Sumário são exibidas apenas uma vez em todo o relatório. As
sessões 2. Cabeçalho da Página e 10. Rodapé da Página repetem a cada nova página. As sessões
3. Cabeçalho Coluna e 9. Rodapé Coluna repetem a cada nova coluna dentro da página. As
sessões 4, 5, 7 e 8 repetem de acordo com mudanças dos campos de 6. Detalhe. Pode haver
quantos grupos se deseje, inclusive zero. Essas sessões são chamadas faixas (bands). Então
temos a faixo deTítulo, a faixa de Cabeçalho de Página, a faixa de Detalhe, etc. Dentro dessas
faixas é que são inseridos os elementos do relatório, tais como os rótulos, campos, imagens,
gráficos, etc.
A figura abaixo mostra as faixas de título, cabeçalho de página, cabeçalho de coluna,
detalhe, rodapé de página.
Na faixa de título temos o campo de texto estático “Clasic Report Template”. A faixa de
cabeçalho da página está em branco apenas para dar espaço entre o título e o cabeçalho da coluna.
Na faixa cabeçalho da coluna temos os campos de texto estáticos “UF”, “Produto” e “QTDE”. Na
faixa de detalhe temos campos de referência aos valores retornados pela consulta SQL $F{UF},
$F{Produto} e $F{QTDE}. Não se preocupe com o que isso quer dizer, vamos explicar em seguida.
O importante é identificar as faixas. Na faixa de rodapé de página, estão as funções de data e
paginação. Como os elementos já estão dispostos nas faixas, fica mais difícil indentificá-las. Se
não houvesse nenhum elemento no relatório as faixas ficariam como demonstra figura a seguir.
______________________________________________________________________________________________
Curso Técnico em Informática 214 Programação Java
Note as demais faixas não aparecem porque eles estão “escondidas”. Para visualizar todas as
faixas de um relatório, clique no menu principal “View” e seleciona a opção “Bands”. A janela de
diálogo mostrada na figura 5.3 vai aparecer. Note que ela lista todas as faixas desse relatório. As
faixas com altiura zero ficam escondidas. As faixas com tamanho maior que zero aparecem no
relatório. Na figura abaixo, a faixa de detalhe tem altura igual a 19.
Assim se você quer mostrar alguma faixa que não está aparecendo ou você está precisando
de mais espaço, aumente a altura da faixa. Depois é só colocar os elementos que desejar.
13.3.2 Variáveis, Parâmetros e campos
Como vocês visto nas figuras acima, apareceu várias expressões como $F{UF}
$V{PAGE_NUMBER}. Mas o que são essas expressões? $F{} é uma referências as colunas (ou
campos) retornados pela consulta SQL do relatório. Assim se seu SQL tiver como retorno uma
coluna UF, $F{UF} referencia essa coluna. As colunas resultantes do SQL são mapeadas para os
campos do nosso relatório. $V{} indica um parâmetro passado para a query SQL do relatório. Os
paramêtros são uteis para cue possamos executar a query de acordo com a seleção do usuário.
Por exemplo, para trazer o resultado das vendas de apenas um estado podemos criar um parâmetro
na consulta SQL para trazer os resultados do estado indicado. Para criar um parâmetro clique no
menu principal “View” e selecione a opção “Report Parameters”.Então vai aparecer:
______________________________________________________________________________________________
Curso Técnico em Informática 215 Programação Java
Clique no Botão “New”. Uma nova janela vai aperecer conforme mostra a figura abaixo. Preencha
o campo “Parameter Name” com “estado”. O campo “Class Type” com “java.lang.String”. Marque o
campo “Is For Prompting”, assim quando você executar o relatório dentro do iReport ele vai
perguntar qual o valor vc quer passar para esse parâmetro. O campo “Default value expression”
indica um valor padrão a ser usado caso o valor para o parâmetro estado não seja passado ao
relatório. Preencha esse campo com “ “SP” ”. O campo “Parameter Description” contém a descrição
do que esse parâmetro representa. Clique em OK e depois feche a janela de parâmetros.
Clique no menu principal “View” e selecione “Report Query”. Agora altere o sql do relatório
para select * from vendas where uf = $P{estado}. Agora execute o seu relatório clicando no menu
principal “Build” e selecionando a opção “Execute Report (using active conn.)”. A janela da figura a
seguir deve aparecer, perguntando qual o valor do parâmetro estado. Preencha com “MG” e o
resultado do relatório deve ser o que mostra na sequência.
______________________________________________________________________________________________
Curso Técnico em Informática 216 Programação Java
13.3.3 Arquivos gerados pelo iReport Agora que você já viu os detalhes da interface gráfica, é preciso entender o que o iReport
faz para gerar esses relatórios. Salve o seu relatório corrente. Clique no menu principal em “File” e
selecione “Save”. Veja que ele vai salvar o nosso relatório com a extensão .jrxml (JasperReports
XML). Esse arquivo é um documento padrão XML. Ele contém as configurações do nosso relatório.
Esse XML é utilizado pelo JasperReports para gerar um arquivo binário com a extensão .Jasper
que é o arquivo utilizado pelo JasperReports para efetivamente gerar o nosso relatório. O
arquivo .jrxml é muito complexo. Por isso editá-lo manualmente seria no mínimo trabalhoso e nada
produtivo, já que teriamos que descrever em forma de XML tudo aquilo que pode ser feito de forma
gráfica através do iReport. Uma das vantagens de se ter o relatório descrito num documento XML
é que ele é facilmente alterável. Por exemplo, se o nome da sua empresa mudar, e você tiver 100
relatórios aonde fazer a alteração. Basta mandar substituir em seus arquivos .jrxml o nome velho
da empresa pelo novo, compilar os .jrxml novamente e você já terminou a sua tarefa.
Exercicio:
Crie um relatório que recebe como parâmetro um preço mínimo e um preço máximo e mostre
todos os produtos nessa faixa de preço.
a) Clique em File | Report Wizard
b) Entre o comando SQL “select * from produto” e clique Next
c) Selecione a coluna “Nome” e clique Next
d) Clique Next novamente
e) Selecione o layout “Tabular” da combobox e o template classicT.xml
f) Clique Next e depois Clique em Finish
g) Clique em “View | Report Parameters”
h) Clique no botão New
i) No campo parameter name digite mínimo.
j) Mude o parameter class type para double
k) Marque “is for Prompting”. Clique em OK.
l) Clique em New novamente
m) No campo parameter name digite maximo.
n) Mude o parameter class type para double
o) Marque “is for Prompting”. Clique em OK.
p) Feche a janela de Parameters
q) Clique em “View | Report Query”
r)Adicione a query a cláusula “where preco > $P{minimo} and preco < $P{maximo}”. O seu
comando SQL deve ficar assim: “select * from produto where preco > $P{minimo} and preco <
$P{maximo}”
______________________________________________________________________________________________
Curso Técnico em Informática 217 Programação Java
s) Salve o relatório.
t) Para visualizar, clique em Build | Execute Report (using active conn.)
u) O iReport vai perguntar o valor mínimo e máximo. Entre com os valores (“0” e “999999”,
por exemplo) e veja o resultado.
v) Execute novamente, mas agora mude os valores de mínimo e máximo (0 e 500) e veja se
o relatório muda.
13.4 Criando um relatório
Até agora vimos como criar um relatório a partir do iReport Wizard. Agora vamos criar um
relatório desde o começo. Para tanto, clique em “File” no menu principal e selecione a opção “New
Document”. A janela da figura abaixo irá aparecer. Nela é possível escolher o tamanho, definir as
margens, a orientação do relatório e o nome. Dê o nome de “MeuRelatorio” e clique no botão OK.
Um novo relatório em branco vai ser criado como mostra a figura a seguir. Nele podemos
ver que algumas faixas já aparecem com tamanhos pré-definidos. Agora basta colocar os
elementos que desejarmos nas faixas para montar o nosso relatório.
______________________________________________________________________________________________
Curso Técnico em Informática 218 Programação Java
A figura abaixo mostra alguns botões da barra de ferramenta que vamos utilizar. Da
esquerda para a direita, são eles: Imagem Texto Estático, Campo de texto, SubRelatório, Gráfico
e Código de Barra.
Clique no botão de texto estático, arraste o cursor sobre a faixa de Título para inserir o
elemento de texto estático. Dê um duplo clique sobre o elemento recém inserido e a janela da figura
abaixo deve aparecer. Nela você pode alterar todas as propriedades desse elemento. Mude o texto
para “Meu Relatório” e aumente o tamanho da fonte para 20.
Veja como ficou sobrando espaço na banda de título diminua o tamanho da faixa de título.
Aproveite e diminua a faixa de Cabeçalho de Pagina (page header) para altura 10, pois também
não vamos utilizá-la. Insira mais três elementos de texto estático na faixa de Cabeçalho de Coluna
(columnHeader). Mude o texto para “ID”, “Descrição” e “Preço”. Para podermos inserir dados nesse
relatório vamos listar a tabela de produto. Para tanto clique no menu “View” e selecione “Report
Query”. Entre o comando SQL “select * from produto” e clique no botão OK. Agora clique no botão
de campo de texto ( o botão com a letra F estilizada). Insira três campos na faixa de Detalhe (detial).
Para poder referenciar uma coluna da nossa consulta SQL, temos que dar duplo clique sobre o
elemento de campo de texto inserido. Uma janela como mostra a figura 6.5 vai abrir, clique na aba
“text field”. No campo Text Field Expression, entre a referência da coluna. Por exemplo, a coluna
ID da consulta SQL acima é referenciada com a expressão $F{ID}. Faça o mesmo para os outros
dois campos. Referencia a coluna “nome” e “preco”. Cuide para colocar o tipo de dado correto no
cmapo “Textfield Expression Class” para evitar erros. Repare que a expressão vai ficar verde
quando você entrar uma expressão válida.
______________________________________________________________________________________________
Curso Técnico em Informática 219 Programação Java
Agora esconda as demais faixas (colocando sua altura para zero), menos a faixa de Rodapé
de Página (pageFooter). Na faixa de rodapé de página, vamos colocar a data e o número da página.
Para tanto adicione dois novos campos de texto na faixa de rodapé de página. Dê duplo clique
sobre o campo de texto da data. Clique na aba “Text Field”, troque o Textfield Expresion Class para
java.lang.Date e no campo “Textfield expression” entre o comando “new Date()”. Dê duplo clique no
o outro campo de texto e clique na aba “Text Field”. Mude o “Textfield Expression Class” para
java.lang.Integer e no campo “Textfield expression” coloque a referência a variável do número da
página, $V{PAGE_NUMBER}. Para visualizar as variáveis pré-disponíveis (builtin) em todos os
relatórios basta clicar no menu “View” e selecionar “Report Variables”. O seu relatório agora deve
aparecer como o dá figura abaixo. Clique no menu “Build” e selcione “Execute Report (using active
conn.)” e veja o resultado.
______________________________________________________________________________________________
Curso Técnico em Informática 220 Programação Java
13.5 Gerando o seu relatório em formato PDF
Você pode gerar o seu relatório e salvar o resultado em um arquivo PDF. O JasperReports
é capaz de salvar o seu relatório em um arquivo PDF sem complicações. No código 8.1 temos o
exemplo de como salvar o nosso relatório a partir de uma aplicação Java padrão. Para tanto basta
carregar o arquivo .JASPER gerado pelo iReport e os métodos da biblioteca JasperReports fazem
o resto do serviço.
import net.sf.jasperreports.engine.*; import net.sf.jasperreports.view.*; import java.sql.*; import java.util.*; public class Visualizador{ private static final String driver = “oracle.jdbc.driver.OracleDriver”; private static final String url = “jdbc:oracle:thin:@localhost:1521:MYDATABASE”; private static final String login = “java”; private static final String Senha = “java”; private static final String pdf = “relatorio.pdf”; private static final String relat = “classic.jasper”; public static void main (String args[])throws Exception{ Class.forName(driver); Connection conn = DriverManager.getConnection(url,login,senha); HashMap parametros = new HashMap(); //Executa o relatório JasperPrint impressao = JasperFillManager.fillReport( relat, parametros, conn); //Exibe o relatório JasperViewer viewer = new JasperViewer(impressao,true); Viewer.show(); //Salva o relatorio no arquivo JasperExportManager.exportReportToPdfFile(impressao,pdf); } }
______________________________________________________________________________________________
Curso Técnico em Informática 221 Programação Java
No código a seguir, temos um exemplo de como mostrar um relatório em formato PDF numa página JSP. Assim você pode mostrar seus relatórios na Web.
<%@ page errorPage="error.jsp" %> <%@ page import="datasource.*" %> <%@ page import="net.sf.jasperreports.engine.*" %> <%@ page import="java.util.*" %> <%@ page import="java.io.*" %> <% String url = “jdbc:oracle:thin:@localhost:1521:MYDATABASE”; String login = “java”; String Senha = “java”; File reportFile = new File(application.getRealPath("classic.jasper")); if (!reportFile.exists()) throw new JRRuntimeException("Arquivo classic.jasper não encontrado."); //Abre conexão com o banco de dados Class.forName(driver); Connection conn = DriverManager.getConnection(url,login,senha); Map parameters = new HashMap(); parameters.put("ReportTitle", "Address Report"); parameters.put("BaseDir", reportFile.getParentFile()); byte[] bytes = JasperRunManager.runReportToPdf( reportFile.getPath(), parameters, conn ); response.setContentType("application/pdf"); response.setContentLength(bytes.length); ServletOutputStream ouputStream = response.getOutputStream(); ouputStream.write(bytes, 0, bytes.length); ouputStream.flush(); ouputStream.close(); %>
13.6 Gerando o seu relatório em formato HTML
Se você quiser exibir os seus relatórios diretamente na sua aplicação Web em formato HTML, o código a seguir, mostra como fazer isso.
<%@ page import="net.sf.jasperreports.engine.*" %> <%@ page import="net.sf.jasperreports.engine.util.*" %> <%@ page import="net.sf.jasperreports.engine.export.*" %> <%@ page import="java.util.*" %> <%@ page import="java.io.*" %> <% String url = “jdbc:oracle:thin:@localhost:1521:MYDATABASE”; String login = “java”; String Senha = “java”; File reportFile = new
______________________________________________________________________________________________
Curso Técnico em Informática 222 Programação Java
File(application.getRealPath("/reports/WebappReport.jasper")); if (!reportFile.exists()) throw new JRRuntimeException("Arquivo WebappReport.jasper não encontrado."); JasperReport jasperReport = (JasperReport)JRLoader.loadObject(reportFile.getPath()); //Abre conexão com o banco de dados Class.forName(driver); Connection conn = DriverManager.getConnection(url,login,senha); Map parameters = new HashMap(); parameters.put("ReportTitle", "Relatorio Web"); parameters.put("BaseDir", reportFile.getParentFile()); JasperPrint jasperPrint = JasperFillManager.fillReport( jasperReport, parameters, conn ); JRHtmlExporter exporter = new JRHtmlExporter(); Map imagesMap = new HashMap(); session.setAttribute("IMAGES_MAP", imagesMap); exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out); exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap); exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "image.jsp? image="); exporter.exportReport(); %> Como você pode observar no código acima, o relatório gerado no iReport,
WebappReport.jasper, é carregado (JRLoader.loadObject(...)) e logo após executado
(JasperFillManager.fillReport(...)). Após o relatório executado, ele é expotardo para o formato
HTML. Objeto exporter é setado em seus parâmetros, indicando qual é o relatório a ser exportado
(jasperPrint) e para onde deve ser exportado (out – a página JSP). O comando exportReport( )
realiza por fim a exportação.
Exercícios:
1 – Crie uma aplicação Java que visualize o relatório gerado pelo iReport (.jasper) e depois salve
o mesmo em um arquivo em fomrato PDF. Abra o PDF para conferir o seu relatório.
2 – Crie uma aplicação Web. Construa uma página JSP que carregue o relatório gerado pelo iReport
e mostra como formato PDF.
3 – Crie uma outra página JSP na sua aplicação Web que mostra o conteúdo do seu relatório
diretamente na página JSP com formato HTML.
4 - Experimente passar parâmetros para a sua query através das páginas JSP. Não esqueça de
carregar um relatório que aceita parâmetros e lembre o nome do parâmetro a ser usado.
______________________________________________________________________________________________
Curso Técnico em Informática 223 Programação Java
O que é Thread ? O conceito de thread está intimamente ligado ao conceito de processo, assim é fundamental
entender o que são processos, como eles são representados e colocados em execução pelo
Sistema Operacional, para em seguida entender as threads. Dessa forma segue uma breve defini-
ção de Processo e posteriormente a de Thread.
Definição de Processo:
“Um processo é basicamente um programa em execução, sendo constituído do código ex-
ecutável, dos dados referentes ao código, da pilha de execução, do valor do contador de programa
(registrador PC), do valor do apontador do apontador de pilha (registrador SP), dos valores dos
demais registradores do hardware, além de um conjunto de outras informações necessárias à ex-
ecução dos programas.” Tanenbaum
Podemos resumir a definição de processo dizendo que o mesmo é formado pelo seu espaço
de endereçamento lógico e pela sua entrada na tabela de processos do Sistema Operacional. As-
sim um processo pode ser visto como uma unidade de processamento passível de ser executado
em um computador e essas informações sobre processos são necessárias para permitir que vários
processos possam compartilhar o mesmo processador com o objetivo de simular paralelismo na
execução de tais processos através da técnica de escalonamento, ou seja, os processos se reve-
zam (o sistema operacional é responsável por esse revezamento) no uso do processador e para
permitir esse revezamento será necessário salvar o contexto do processo que vai ser retirado do
processador para que futuramente o mesmo possa continuar sua execução.
Definição de Thread: “Thread, ou processo leve, é a unidade básica de utilização da CPU, consistindo de : contador
de programa, conjunto de registradores e uma pilha de execução. Thread são estruturas de ex-
ecução pertencentes a um processo e assim compartilham os segmentos de código e dados e os
recursos alocados ao sistema operacional pelo processo. O conjunto de threads de um processo é
chamado de Task e um processo tradicional possui uma Task com apenas uma thread.” Silber-
schatz
O conceito de thread foi criado com dois objetivos principais: Facilidade de comunicação entre
unidades de execução e redução do esforço para manutenção dessas unidades. Isso foi conse-
guido através da criação dessas unidades dentro de processos, fazendo com que todo o esforço
para criação de um processo, manutenção do Espaço de endereçamento lógico e PCB, fosse apro-
veitado por várias unidades processáveis, conseguindo também facilidade na comunicação entre
essas unidades.
Dessa forma o escalonamento de threads de um mesmo processo será facilitado pois a troca
de contexto entre as threads exigirá um esforço bem menor. Sendo que ainda assim, ocorrerá o
escalonamento de processos, pois outros processos poderão estar sendo executado paralelamente
ao processo que possui as threads. Podemos concluir então que a real vantagem é obtida no es-
calonamento de threads de um mesmo processo e na facilidade de comunicação entre essas thre-
ads.
Threads em Java
14
______________________________________________________________________________________________
Curso Técnico em Informática 224 Programação Java
Paralelismo x Concorrência:
Threads podem executar suas funções de forma paralela ou concorrente, onde quando as
threads são paralelas elas desempenham o seus papeis independente uma das outras. Já na exe-
cução concorrente, as threads atuam sobre objetos compartilhados de forma simbiótica necessi-
tando de sincronismo no acesso a esses objetos, assim deve ser garantido o direito de atomicidade
e exclusão mútua nas operações das threads sobre objetos compartilhados.
14.1 Thread em Java
Todo programador está familiarizado com a programação sequencial, pois sem dúvida até o
presente momento esta é a forma de programação mais comum. Programas do tipo “Hello World”,
ou que ordenam uma lista de nome, ou que gera e imprime uma lista de números primos, etc são
programas tipicamente sequenciais, onde cada um possui: seu início, sequência de execução e fim
e em qualquer momento da sua execução estes programas possuem apenas um ponto de ex-
ecução.
Uma thread é similar ao programas sequenciais, pois possui um início, sequência de execu-
ção e um fim e em qualquer momento uma thread possui um único ponto de execução. Contudo,
uma thread não é um programa, ela não pode ser executada sozinha e sim inserida no contexto de
uma aplicação, onde essa aplicação sim, possuirá vários pontos de execuções distintos, cada um
representado por uma thread. A figura abaixo descreve esse mecanismo de funcionamento da
thread dentro de um programa em execução.
Definição: Uma thread representa um fluxo de controle de execução dentro de um programa.
Não há nada de novo nesse conceito de processo com uma única thread, pois o mesmo é
idêntico ao conceito tradicional de processo. O grande benefício no uso de thread é quando temos
várias thread num mesmo processo sendo executadas simultaneamente e podendo realizar tarefas
diferentes. A figura abaixo representa um processo com múltiplas threads (Programação Multi-
Thread.)
Programa em Execução - Processo
Espaço de Endereçamento
Lógico
Segmento de
Texto
Segmento de
Dados
Segmento de
Pilha
Thread
Texto
Pilha de
Execução
Registradores
Process Control Block (PCB)
Informações
para Gerência
do Processo
Informações
para Gerência
de Memória
Informações
para Gerência
de Arquivos
Processo com apenas uma Thread
______________________________________________________________________________________________
Curso Técnico em Informática 225 Programação Java
Definição : Com múltiplas theads um programa possui múltiplos pontos de execução
Dessa forma podemos perceber facilmente que aplicações multithreads podem realizar
tarefas distintas ao “mesmo tempo”, dando idéia de paralelismo. Veja um exemplo do navegador
web HotJava, o qual consegue carregar e executar applets, executar uma animação, tocar um som,
exibir diversas figuras, permitir rolagem da tela, carregar uma nova página, etc e para o usuário
todas essas atividades são simultâneas, mesmo possuindo um único processador. Isso é possível,
por que dentro da aplicação do navegador HotJava várias threads foram executadas, provavel-
mente, uma para cada tarefa a ser realizada.
Alguns autores tratam threads como processos leves. Uma thread é similar a um processo no
sentido que ambos representam um único fluxo de controle de execução, sendo considerada um
processo leve por ser executada dentro do contexto de um processo e usufruir dos recursos aloca-
dos pelo processo. Cada thread necessita possuir apenas as informações (contador de programa
e pilha de execução) necessárias a sua execução, compartilhando todo o contexto de execução do
processo com todas a demais threads do mesmo processo.
A linguagem Java possui apenas alguns mecanismos e classes desenhadas com a finalidade
de permitir a programação Multi-Thread, o que torna extremamente fácil implementar aplicações
Multi-Threads, sendo esses:
A classe java.lang.Thread utilizada para criar, iniciar e controlar Threads;
As palavras reservadas synchronized e volatile usadas para controlar a execução de código
em objetos compartilhados por múltiplas threads, permitindo exclusão mútua entre estas;
Os métodos wait, notify and notifyAll definidos em java.lang.Object usados para coordenar
as atividades das threads, permitindo comunicação entre estas.
14.2 Criando Threads em Java
A criação de threads em java é uma atividade extremamente simples e existem duas formas
distintas de fazê-lo: uma através da herança da classe Thread, outra através da implementação da
interface Runnable, e em ambos os casos a funcionalidade (programação) das threads é feita na
implementação do método run.
Programa em Execução - Processo
Espaço de Endereçamento
Lógico
Segmento de
Texto
Segmento de
Dados
Segmento de
Pilha
Thread
Texto
Pilha de
Execução
Registradores
Process
Control Block
(PCB)
Informações
para Gerência
do Processo
Informações
para Gerência
de Memória
Informações
para Gerência
de Arquivos
Processo com múltiplas Threads
Thread
Texto
Pilha de
Execução
Registradores
...
______________________________________________________________________________________________
Curso Técnico em Informática 226 Programação Java
14.2.1 Implementando o Comportamento de uma Thread O método run contém o que a thread faz, ele representa o comportamento (implementação)
da thread, é como um método qualquer podendo fazer qualquer coisa que a linguagem Java per-
mita. A classe Thread implementa uma thread genérica que por padrão não faz nada, contendo um
método run vazio, definindo assim uma API que permite a um objeto runnable prover uma imple-
mentação para o método run de uma thread.
14.2.2 Criando uma subclasse de Thread A maneira mais simples de criar uma thread em Java é criando uma subclasse de Thread e
implementando o que a thread vai fazer sobrecarregando o método run.
Exemplo de criação de threads estendendo a classe Thread
/** Criação de NovaThread através da herança da classe Thread */
public class NovaThread extends Thread {
/** Construtor de NovaThread*/
public NovaThread (String threadName) {
/* construtor de Thread passando o nome da Thread como parâmetro */
super(threadName);
}
/** método run o qual representa o comportamento de NovaThread */
public void run () {
/* Implementação do comportamento da thread */
}
}
14.2.3 Implementando a Interface Runnable
A outra forma de criar threads em Java é implementando a interface Runnable e implemen-
tando o método run definido nessa interface. Sendo que a classe que implementa a thread deve
declarar um objeto do tipo Thread e para instanciá-lo deve chamar o construtor da classe Thread
passando como parâmetro a instância da própria classe que implementa Runnable e o nome da
thread. Como o objeto do tipo Thread é local a classe que vai implementar thread, e normalmente
privado, há a necessidade de criação de um método start para permitir a execução do objeto thread
local. O mesmo deve ser feito para qualquer outro método da classe Thread que dever ser visto ou
usado fora da classe que implementa Runnable.
Exemplo de thread implementando a interface Runnable
/** Criação de NovaThread através da implementação da Interface Runnable */ public class NovaThread implements Runnable { /* Objeto local do tipo Thread*/ private Thread thread = null; /* Construtor da classe */ public NovaThread (String threadName) {
______________________________________________________________________________________________
Curso Técnico em Informática 227 Programação Java
/* Caso o objeto thread local não tiver sido criado ainda */ if (thread == null) { /* A mesma deve ser instanciada com o nome recebido no construtor * Detalhe importante é que uma instância da própria classe (this) * também é passada ao construtor da classe Thread permitindo assim * a associação do método run com a thread */ thread = new Thread(this, threadName); } } /* Método para iniciar o objeto thread local */ public void start() { thread.start(); } public void run () { /* Comportamento da thead */ } }
14.2.4 Escolhendo entre os dois métodos de criação de threads
O principal fator a ser levado em consideração na escolha entre um dos dois métodos de
criação de thread é que a linguagem Java não permite herança múltipla, assim quando uma classe
que já for sub-classe de outra precisar implementar thread é obrigatório que isso seja feito através
da implementação da interface Runnable, caso contrário pode-se utilizar sub-classes da classe
Thread. Um exemplo claro desse fator de escolha é na implementação de Applet as quais obriga-
toriamente devem ser sub-classes da classe Applet, assim applets só podem implementar threads
através da implementação da interface Runnable.
Um exemplo mais interessante de threads em Java Simulação de uma Corridas de Sapos, onde cada sapo na corrida é representado por uma
thread.
/* Aplicação que simula uma corrida de sapos usando threads */ public class CorridaDeSapos { final static int NUM_SAPOS = 5; // QTE. de sapos na corrida final static int DISTANCIA = 500; // Distância da corrida em cm public static void main (String[] args) { /* colocando sapos na corrida */ for (int i = 1; i <= NUM_SAPOS; i++) { new SapoCorrendoThread("SAPO_" + i, DISTANCIA).start(); } } } /* Classe usando Thread que simula a corrida de um sapo */ class SapoCorrendoThread extends Thread { String nome; // nome do sapo int distanciaCorrida = 0; // distância já corrida pelo sapo int distanciaTotalCorrida; // distância a ser corrida pelo sapo int pulo = 0; // pulo do sapo em cm
______________________________________________________________________________________________
Curso Técnico em Informática 228 Programação Java
int pulos = 0; // quantidades de pulos dados na corrida static int colocacao = 0; // colocação do sapo ao final da corrida final static int PULO_MAXIMO = 50; // pulo máximo em cm que um sapo pode dar /** Construtor da classe. Parâmtros : Nome do Sapo e Distância da Corrida */ public SapoCorrendoThread (String nome, int distanciaTotalCorrida) { /* chamando o construtor de Thread passando o nome do sapo como parâmetro */ super(nome); this.distanciaTotalCorrida = distanciaTotalCorrida; this.nome = nome; } /** Imprime o último pulo do sapo e a distância percorrida */ public void sapoImprimindoSituacao () { System.out.println("O " + nome + " pulou " + pulo + "cm \t e já percorreu " + distanciaCorrida + "cm"); } /** Faz o sapo pular */ public void sapoPulando() { pulos++; pulo = (int) (Math.random() * PULO_MAXIMO); distanciaCorrida += pulo; if (distanciaCorrida > distanciaTotalCorrida) { distanciaCorrida = distanciaTotalCorrida; } } /** Representando o descanso do sapo */ public void sapoDescansando () { /* Método que passa vez a outras threads */ yield(); } /** Imprime a colocação do sapo ao final da corrida */ public void colocacaoSapo () { colocacao++; System.out.println(nome + " foi o " + colocacao + "º colocado com " + pulos + " pulos"); } /** Método run da thread Corrida de Sapos */ public void run () { while (distanciaCorrida < distanciaTotalCorrida) { sapoPulando(); sapoImprimindoSituacao(); sapoDescansando(); } colocacaoSapo(); } }
Resultado da Execução – Corrida de Sapos
O SAPO_01 pulou 21cm e já percorreu 21cm
O SAPO_02 pulou 21cm e já percorreu 21cm
O SAPO_03 pulou 47cm e já percorreu 47cm
______________________________________________________________________________________________
Curso Técnico em Informática 229 Programação Java
O SAPO_04 pulou 4cm e já percorreu 4cm
O SAPO_05 pulou 46cm e já percorreu 46cm
O SAPO_01 pulou 34cm e já percorreu 55cm
O SAPO_02 pulou 30cm e já percorreu 51cm
O SAPO_03 pulou 42cm e já percorreu 89cm
O SAPO_04 pulou 33cm e já percorreu 37cm
O SAPO_05 pulou 14cm e já percorreu 60cm
O SAPO_01 pulou 33cm e já percorreu 88cm
O SAPO_02 pulou 25cm e já percorreu 76cm
O SAPO_03 pulou 33cm e já percorreu 122cm
O SAPO_04 pulou 29cm e já percorreu 66cm
O SAPO_02 pulou 13cm e já percorreu 89cm
O SAPO_03 pulou 8cm e já percorreu 130cm
O SAPO_04 pulou 37cm e já percorreu 103cm
O SAPO_05 pulou 5cm e já percorreu 65cm
O SAPO_01 pulou 17cm e já percorreu 105cm
O SAPO_02 pulou 25cm e já percorreu 114cm
O SAPO_03 pulou 10cm e já percorreu 140cm
O SAPO_04 pulou 11cm e já percorreu 114cm
O SAPO_05 pulou 48cm e já percorreu 113cm
O SAPO_01 pulou 3cm e já percorreu 108cm
O SAPO_02 pulou 44cm e já percorreu 158cm
O SAPO_03 pulou 38cm e já percorreu 178cm
O SAPO_04 pulou 37cm e já percorreu 151cm
O SAPO_05 pulou 20cm e já percorreu 133cm
O SAPO_01 pulou 40cm e já percorreu 148cm
O SAPO_02 pulou 13cm e já percorreu 171cm
O SAPO_03 pulou 45cm e já percorreu 200cm
O SAPO_04 pulou 10cm e já percorreu 161cm
O SAPO_05 pulou 18cm e já percorreu 151cm
O SAPO_01 pulou 19cm e já percorreu 167cm
O SAPO_02 pulou 18cm e já percorreu 189cm
SAPO_03 foi o 1º colocado com 7 pulos
O SAPO_05 pulou 49cm e já percorreu 200cm
O SAPO_01 pulou 44cm e já percorreu 200cm
O SAPO_02 pulou 49cm e já percorreu 200cm
O SAPO_04 pulou 14cm e já percorreu 175cm
SAPO_05 foi o 2º colocado com 7 pulos
SAPO_02 foi o 3º colocado com 9 pulos
SAPO_01 foi o 4º colocado com 8 pulos
O SAPO_04 pulou 31cm e já percorreu 200cm
SAPO_04 foi o 5º colocado com 9 pulos
______________________________________________________________________________________________
Curso Técnico em Informática 230 Programação Java
14.2.5 O ciclo de vida de uma Thread
A melhor forma de analisar o ciclo de vida de uma thread é através das operações que podem
ser feitas sobre as mesmas, tais como : criar, iniciar, esperar, parar e encerrar. O diagrama abaixo
ilustra os estados os quais uma thread pode assumir durante o seu ciclo de vida e quais métodos
ou situações levam a estes estados.
Ciclo de vida de uma thread
(Nova/Executando/Pronta/Esperando/Morta)
14.2.6 Criando Threads
A criação de uma thread é feita através da chamado ao seu construtor colocando a thread no
estado Nova, o qual representa uma thread vazia, ou seja, nenhum recurso do sistema foi alocado
para ela ainda. Quando uma thread está nesse estado a única operação que pode ser realizada é
a inicialização dessa thread através do método start(), se qualquer outro método for chamado com
a thread no estado Nova irá acontecer uma exceção (IllegalThreadStateException), assim como,
quando qualquer método for chamado e sua ação não for condizente com o estado atual da thread.
14.2.7 Iniciando Threads A inicialização de uma thread é feita através do método start() e nesse momento os recursos
necessários para execução da mesma são alocados, tais como recursos para execução, escalo-
namento e chamada do método run da thread. Após a chamada ao método start a thread está
pronta para ser executada e será assim que for possível, até lá ficará no estado Pronta. Essa
mudança de estado (Pronta/Executando) será feito pelo escalonador do Sistema de Execução
Java. O importante é saber que a thread está pronta para executar e a mesma será executada,
Estados de Threads
Esperando
Pronta
Nova
Executando
Morta
start()
ne
w T
hre
ad
()
Esca
lona
do
r
Esca
lona
do
r
yie
ld()
Método run acabar
sleep(tempo)
wait()
Solicitação de I/O
Solicitação de I/O atendida
Tempo do sleep decorrido
Outra thread chamar notify() / notifyAll()
______________________________________________________________________________________________
Curso Técnico em Informática 231 Programação Java
mais cedo ou mais tarde de acordo com os critérios, algoritmo, de escalonamento do Sistema de
Execução Java.
14.2.8 Fazendo Thread Esperar Uma thread irá para o estado Esperando quando:
O método sleep (faz a thread esperar por um determinada tempo) for chamado;
O método wait (faz a thread esperar por uma determinada condição) for chamado;
Quando realizar solicitação de I/O.
Quando um thread for para estado Esperando ela retornará ao estado Pronta quando a con-
dição que a levou ao estado Esperando for atendida, ou seja:
Se a thread solicitou dormir por determinado intervalo de tempo (sleep), assim que
este intervalo de tempo for decorrido;
Se a thread solicitou esperar por determinado evento (wait), assim que esse evento
ocorrer (outra thread chamar notify ou notifyAll);
Se a thread realizou solicitação de I/O, assim que essa solicitação for atendida.
14.2.9 Finalizando Threads Uma Thread é finalizada quando acabar a execução do seu método run, e então ela vai para
o estado Morta, onde o Sistema de Execução Java poderá liberar seus recursos e eliminá-la.
14.2.9.1 Verificando se Threads estão Executando/Pronta/Esperando ou Novas/Mortas A classe Thread possui o método isAlive, o qual permite verificar se uma thread está nos
estado Executando/Pronta/Esperando ou nos estados Nova/Morta. Quando o retorno do método
for true a thread esta participando do processo de escalonamento e o retorno for false a thread
está fora do processo de escalonamento. Não é possível diferenciar entre Executando, Pronta ou
Esperando, assim também como não é possível diferenciar entre Nova ou Morta.
14.10 Threads Daemon
São threads que rodam em background e realizam tarefas de limpeza ou manutenção, as
quais devem rodar enquanto a aplicação estiver em execução, as threads daemons somente mor-
rerem quando a aplicação for encerrada. Sendo que o Sistema de Execução Java identifica que
uma aplicação acabou quando todas as suas threads estão morta, assim para que seja possível
que uma aplicação seja encerrada ainda possuindo threads, tais threads devem ser daemon. Em
outras palavras, o Sistema de Execução Java irá terminar uma aplicação quando todas as suas
threads não daemon morrerem. Threads daemons são denominadas de Threads de Serviço e as
não daemon são denominadas de Threads de Usuário.
Os métodos para manipulação de threads daemon são:
public final void setDaemon(boolean) Torna ou não uma thread daemon
public final boolean isDaemon() Verifica se uma thread é daemon
______________________________________________________________________________________________
Curso Técnico em Informática 232 Programação Java
14.11 Escalonamento de Threads
O escalonamento é fundamental quando é possível a execução paralela de threads, pois,
certamente existirão mais threads a serem executadas que processadores, assim a execução pa-
ralela de threads é simulada através de mecanismos do escalonamento dessas threads, onde os
processadores disponíveis são alternados pelas diversas threads em execução. O mecanismo de
escalonamento utilizado pelo Sistema de Execução Java é bastante simples e determinístico, e
utiliza um algoritmo conhecido como Escalonamento com Prioridades Fixas, o qual escalona
threads baseado na sua prioridade. As threads escalonáveis são aquelas que estão nos estados
Executando ou Pronta, para isso toda thread possui uma prioridade, a qual pode ser um valor
inteiro no intervalo [MIN_PRIORITY ... MAX_PRIORITY], (estas são constantes definidas na classe
Thread), e quanto maior o valor do inteiro maior a prioridade da thread. Cada thread Nova recebe
a mesma prioridade da thread que a criou e a prioridade de uma thread pode ser alterada através
do método setPriority(int priority).
O algoritmo de escalonamento com Prioridades Fixas utilizado pela Sistema de Execução
Java funcionada da seguinte forma:
1. Quando várias threads estiverem Prontas, aquela que tiver a maior prioridade será
executada.
2. Quando existir várias threads com prioridades iguais, as mesmas serão escalonadas
segundo o algoritmo Round-Robin de escalonamento.
3. Uma thread será executada até que: uma outra thread de maior prioridade fique Pronta;
acontecer um dos eventos que a faça ir para o estado Esperando; o método run acabar;
ou em sistema que possuam fatias de tempo a sua fatia de tempo se esgotar.
4. Threads com prioridades mais baixas terão direito garantido de serem executadas para
que situações de starvation não ocorram.
Exemplo de aplicação usando threads com diferentes prioridades Observe que essa corrida não é justa pois os sapos 4 e 5 possuem prioridades máximas e
com certeza ganharão a corrida.
/* Aplicação que simula uma corrida de sapos usando threads */ public class CorridaDeSapos { final static int NUM_SAPOS = 5; // QTE. de sapos na corrida final static int DISTANCIA = 500; // Distância da corrida em cm public static void main (String[] args) { /* Criando as threads para representar os sapos correndo */ SapoCorrendoThread sapo_1 = new SapoCorrendoThread("SAPO_01", DISTANCIA); SapoCorrendoThread sapo_2 = new SapoCorrendoThread("SAPO_02", DISTANCIA); SapoCorrendoThread sapo_3 = new SapoCorrendoThread("SAPO_03", DISTANCIA); SapoCorrendoThread sapo_4 = new SapoCorrendoThread("SAPO_04", DISTANCIA); SapoCorrendoThread sapo_5 = new SapoCorrendoThread("SAPO_05", DISTANCIA); /* Estabelecendo prioridades para as threads */ sapo_1.setPriority(Thread.MIN_PRIORITY);
______________________________________________________________________________________________
Curso Técnico em Informática 233 Programação Java
sapo_2.setPriority(Thread.MIN_PRIORITY); sapo_3.setPriority(Thread.NORM_PRIORITY); sapo_4.setPriority(Thread.MAX_PRIORITY); sapo_5.setPriority(Thread.MAX_PRIORITY); /* Iniciando as threads */ sapo_1.start(); sapo_2.start(); sapo_3.start(); sapo_4.start(); sapo_5.start(); } }
14.12 Sincronizando Threads (Concorrência)
Até o momento temos abordado threads como unidades de processamento independentes,
onde cada uma realiza a sua tarefa sem se preocupar com o que as outras threads estão fazendo
(paralelimos), ou seja, abordamos threads trabalhando de forma assíncrona e embora a utilização
de threads dessa maneira já seja de grande utilidade, muitas vezes precisamos que um grupo de
threads trabalhem em conjunto e agindo sobre objetos compartilhados, onde várias threads desse
conjunto podem acessar e realizar operações distintas sobre esses objetos, sendo que, muitas
vezes a tarefa de uma thread vai depender da tarefa de outra thread, dessa forma as threads terão
que trabalhar de forma coordenada e simbiótica, ou seja, deverá haver uma sincronização entre as
threads para que problemas potenciais advindos do acesso simultâneo a esses objetos com-
partilhado não ocorram.
Esses problemas são conhecidos como condições de corrida (Race Conditions) e os trechos
de códigos, das threads, que podem gerar condições de corrida são chamados de regiões críticas
(critical sections), assim as condições de corridas podem ser evitadas através da exclusão mútua
das regiões críticas das threads e sincronização entre as threads envolvidas.
O mecanismo para prover exclusão mútua entre threads em Java é bastante simples, neces-
sitando apenas da declaração dos métodos que contém regiões críticas como synchronized. Isso
garante que quando uma das threads estiver executando uma região crítica em um objeto compar-
tilhado nenhuma outra poderá fazê-lo. Ou seja, quando uma classe possuir métodos sincronizados,
apenas um deles poderá estar sendo executado por uma thread.
14.13 Implementando Exclusão Mútua de Regiões Críticas
A sincronização entre threads, que acessam concorrentemente um mesmo objeto com-
partilhado, é feita da seguinte forma: a classe do objeto compartilhado deve possuir métodos que
realizem as operações de interesse das threads que o acessam e esses métodos devem ser
declarados como synchronized, garantido que somente uma thread por vez poderá executar um
desses métodos. Assim é fácil perceber que o mecanismo descrito acima fornece, de forma sim-
ples, a exclusão mútua de regiões críticas a qual é garantida pelo Sistema de Execução Java.
Fazendo uma relação com a teoria de Sistemas Operacionais a linguagem de programação Java
fornece um MONITOR, onde o Compilador e o Sistema de Execução garantem a exclusão mútua
e sincronia, provendo assim um mecanismo de alto nível para facilitar a criação de aplicações Multi-
Threads.
______________________________________________________________________________________________
Curso Técnico em Informática 234 Programação Java
14.14 Comunicação Entre Threads Um outro aspecto muito importante na implementação de threads que trabalham concorren-
temente sobre um objeto compartilhado é que muitas vezes a atividade de uma thread depende da
atividade de outra thread, assim é necessário que as threads troquem mensagem afim de avisarem
umas as outras quando suas tarefas forem concluídas ou quando precisam esperar por tarefas de
outras. Em Java isso é feito através dos métodos wait, notify, notifyAll, onde:
wait Faz a thread esperar (coloca no estado Esperando) em um objeto
compartilhado, até que outra thread a notifique ou determinado intervalo de
tempo seja decorrido.
notify Notifica (retira do estado Esperando) uma thread que esta esperando em um
objeto compartilhado.
notifyAll Notifica todas as threads que estão esperando em um objeto compartilhado,
onde uma delas será escalonada para usar o objeto e as outras voltarão ao
estado Esperando.
Observação: Esses métodos devem ser usados na implementação das operações dos objetos
sincronizados, ou seja, nos métodos synchronized dos objetos sincronizados. Pois só faz sentido
uma thread notificar ou esperar por outra em objetos sincronizados e o Sistema de Execução Java
tem mecanismos para saber qual thread irá esperar ou receber a notificação, pois somente uma
thread por vez pode estar executando um método sincronizado de um objeto compartilhado.
14.15 Evitando Starvation e Deadlock
Com a programação concorrente de diversas threads que trabalham em conjunto e acessam
objetos compartilhados surge o risco potencial de Starvation e Deadlock, onde Starvation acontece
quando uma thread fica esperando por um objeto que nunca lhe será concedido e o Deadlock é
quando duas ou mais threads esperam, de forma circular, por objetos compartilhados e nenhuma
delas será atendida pelo fato de esperar umas pelas outras.
Na programação Java Starvation e Deadlock devem ser evitados pelo controle lógico de
acesso aos objetos compartilhados, fazendo com que o programador deva identificar situação que
possam gerar Starvation e Deadlock e evitá-las de alguma forma e com certeza essa é a tarefa
mais desafiadora e trabalhosa na programação concorrente.
Agrupando Threads
Toda thread Java é membro de um grupo. Grupo de threads é um mecanismo para agrupar
várias threads em um único objeto e permitir realizar operações sobre todas elas mais facilmente.
O Sistema de Execução Java coloca threads em grupos no momento da sua criação. Quando uma
thread é criada a mesma é colocada num grupo padrão pelo Sistema de Execução Java ou o grupo
pode ser especificado pelo programador. Uma vez criada, a thread é membro permanente do seu
grupo e a mesma não pode ser movida para outro grupo.
O Grupo Padrão de Threads Quando uma thread é criada sem a especificação de um grupo no seu construtor, o Sistema
de Execução Java a coloca no mesmo grupo da thread que a criou. Quando uma thread for criada
______________________________________________________________________________________________
Curso Técnico em Informática 235 Programação Java
em uma aplicação sem a especificação de um grupo a mesma será colocada no grupo padrão
“main” o qual é criado na inicialização da aplicação pelo Sistema de Execução Java.
É muito comum que o programa não se preocupe com grupos no uso de threads em Java
deixando que o Sistema de Execução Java faça a tarefa de agrupar as threads. Mas, quando uma
aplicação for trabalhar com diversas threads é mais conveniente agrupá-las, pois algumas
operações deverão ser feitas sobre todas as threads e a criação de grupos de threads irá facilitar
tais operações.
Criando Grupos de Threads e Inserindo Threads A criação de um grupo de threads é feita através do construtor da classe ThreadGroup, onde
basta informar o nome do grupo:
GroupThread grupoDeThreads = new GroupThread(“Nome Grupo de Threads”)
A colocação de threads em grupos é realizada no momento da sua criação para isso, existem
três construtores onde é possível informar o grupo ao qual a thread deve ser inserida.
public Thread(ThreadGroup group, Runnable runnable)
public Thread(ThreadGroup group, String name)
public Thread(ThreadGroup group, Runnable runnable, String name)
Operações sobre Grupos de Threads As principais operações que podem ser realizadas sobre grupos de threads são:
Método Descrição
getName() Retorna o nome do grupo
toString() Retorna uma representação do grupo em string
list() Imprime informações sobre o grupo no dispositivo padrão de saída
O Exemplo Produtor/Consumidor ou Buffer Limitado
class ProdutorConsumidor {
public static void main (String[] args) {
/* Criando o Buffer Limitado */
BufferLimitado buffer = new BufferLimitado();
/* Quantidade de itens a serem produzidos/consumidos pelas threads */
final int QUANT_ITENS = 10;
/* Quantidade de threads */
final int QUANT_THREADS = 5;
/* Criando os grupos de threads Produtoras/Consumidoras */
ThreadGroup threadsProdutoras = new ThreadGroup("Produtores");
ThreadGroup threadsConsumidoras = new ThreadGroup("Consumidores");
/* Criando e iniciando e inserindo nos grupos as threads Produtoras */
for (int i = 1; i <= QUANT_THREADS; i++){
new ProdutorThread(threadsProdutoras,"Produtor_" + i,
buffer,QUANT_ITENS).start();
______________________________________________________________________________________________
Curso Técnico em Informática 236 Programação Java
}
/* Criando, iniciando e inserindo nos grupos as threads Consumidoras */
for (int i = 1; i <= QUANT_THREADS; i++){
new ConsumidorThread(threadsConsumidoras,"Consumidor_" + i,
buffer,QUANT_ITENS).start();
}
}
}
______________________________________________________________________________________________
Curso Técnico em Informática 237 Programação Java
class ProdutorThread extends Thread { /* objeto para referenciar o buffer */ BufferLimitado buffer; /* quantidade de itens a serem produzidos */ int quantItens; /** * Construtor * @param threadGroup Grupo da thread * @param nomeThread Nome da thread * @param buffer buffer a ser utilizado * @param quantItens quantidade de itens a serem produzidos */ public ProdutorThread (ThreadGroup threadGroup,String nomeThread, BufferLimitado buffer, int quantItens) { super(threadGroup, nomeThread); this.buffer = buffer; this.quantItens = quantItens; } /* * Método run da thread, o qual contém o ser comportamento */ public void run () { for (int i = 1; i <= quantItens; i++) { /* Gera um novo item aleatoriamente */ int novoItem = (int) (Math.random() * 10); /* Insere o novo item no buffer */ buffer.insere(novoItem); /* dorme pelo intervalo de tempo aleatório [0 ... 100]mseg */ int tempo = (int) (Math.random() * 1000); dorme(tempo); } } private void dorme(int tempo) { try { sleep(tempo); } catch (InterruptedException e) { System.out.println(e.getMessage()); } } }
______________________________________________________________________________________________
Curso Técnico em Informática 238 Programação Java
class ConsumidorThread extends Thread { /* objeto para referenciar o buffer */ BufferLimitado buffer; /* quantidade de itens a serem consumidos */ int quantItens; /** * Construtor * @param threadGroup Grupo da thread * @param nomeThread Nome da thread * @param buffer buffer a ser utilizado * @param quantItens quantidade de itens a serem consumidos */ public ConsumidorThread (ThreadGroup threadGroup, String nomeThread, BufferLimitado buffer, int quantItens) { super(threadGroup, nomeThread); this.buffer = buffer; this.quantItens = quantItens; } /* * Método run da thread, o qual contém o ser comportamento */ public void run () { for (int i = 1; i <= quantItens; i++) { /* Retita um elemtno do buffer */ buffer.retira(); /* dorme pelo intervalo de tempo aleatório [0 ... 100]mseg */ int tempo = (int) (Math.random() * 1000); dorme(tempo); } } private void dorme(int tempo) { try { sleep(tempo); } catch (InterruptedException e) { System.out.println(e.getMessage()); } } }
______________________________________________________________________________________________
Curso Técnico em Informática 239 Programação Java
class BufferLimitado { /* tamano do buffer */ private final static int TAMANHO = 5; /* buffer */ private int[] buffer = new int[TAMANHO]; /* posição para insercão de novo item (in) */ private int posicaoInsere = 0; /* posição para remoção do item (out) */ private int posicaoRetira = 0; /* quantidades de itens no buffer */ private int quantItens = 0; /* Construtor */ public BufferLimitado () { } /** * Insere um novo item no buffer * @param novoItem item a ser inserido no buffer */ synchronized public void insere (int novoItem) { /* enquanto o buffer estiver cheio a thread deve esperar */ while (quantItens == TAMANHO) { try { wait(); } catch (InterruptedException e){ System.out.println("Erro de Estado da Thread " + e.getMessage()); } } /* colocando novo item no buffer */ buffer[posicaoInsere] = novoItem; /* exibindo informções sobre a inserção do novo item */ System.out.print("Inserindo " + novoItem + "\tna posição " + posicaoInsere + "\t"); /* atualizando a posição de inserção */ posicaoInsere = proximaPosicao(posicaoInsere); /* incrementando a quantidade de itens no buffer */ quantItens++; /* imprimindo o buffer */ imprime(); /* caso o buffer estivesse vazio, acordar as threads consumidoras */ if (quantItens == 1) { notifyAll(); } }
______________________________________________________________________________________________
Curso Técnico em Informática 240 Programação Java
/** * Retira um item do buffer * @return Item retirado do buffer */ synchronized public int retira () { int itemRetirado; // item retirado /* enquanto o buffer estiver vazio a thread deve esperar */ while (quantItens == 0) { try { wait(); } catch (InterruptedException e){ System.out.println("Erro de Estado da Thread " + e.getMessage()); } } /* armazendo o item a ser retirado */ itemRetirado = buffer[posicaoRetira]; /* atualizando a quantidade de itens */ quantItens--; /* exibindo informações sobre a retirado do item do buffer */ System.out.print("Retirando " + itemRetirado + "\tda posição " + posicaoRetira + "\t"); /* atualizando a posição de retirado */ posicaoRetira = proximaPosicao(posicaoRetira); /* imprimindo o buffer */ imprime(); /* caso o buffer estivesse cheio, acordar as threads produtoras */ if (quantItens == TAMANHO - 1) { notifyAll(); } /* retorna o item retirado */ return itemRetirado; } /** * Obtem a próxima posição no buffer * @param posicaoAtual a atual posicao no buffer * @return a prómixa posição no buffer */ private int proximaPosicao (int posicaoAtual) { /* obtem a nova posição */ int novaPosicao = ++posicaoAtual; /* caso ultrapasse o tamanho do buffer,irá para o 1ª posição (0) */ if (novaPosicao > TAMANHO - 1) { novaPosicao = 0; } return novaPosicao; } /** * Obtem a posição anterior no buffer
______________________________________________________________________________________________
Curso Técnico em Informática 241 Programação Java
* @param posicaoAtual a atual posicao no buffer * @return a posição anterior no buffer */ private int posicaoAnterior (int posicaoAtual) { /* obtem a nova posição */ int novaPosicao = --posicaoAtual; /* caso seja menor que a posição inicial, irá para a última posição */ if (novaPosicao < 0) { novaPosicao = TAMANHO-1; } return novaPosicao; } /* * Imprime o buffer */ synchronized private void imprime () { /* posição inicial da impressão */ int inicio = posicaoRetira; /* posição final da impressão */ int fim = posicaoAnterior(posicaoInsere); /* posição impressa */ int i = inicio; /* quantidade de itens impressos */ int quantItensImpressos = 0; System.out.print("\tBuffer[" + quantItens + "] \t= "); while (quantItensImpressos < quantItens) { System.out.print(buffer[i] + " "); i = proximaPosicao(i); quantItensImpressos++; } System.out.println(); } }
Resultado da Execução – Produtor/Consumidor:
Inserindo 5 na posição 0 Buffer[1] = 5 Inserindo 0 na posição 1 Buffer[2] = 5 0 Inserindo 1 na posição 2 Buffer[3] = 5 0 1 Inserindo 5 na posição 3 Buffer[4] = 5 0 1 5 Inserindo 9 na posição 4 Buffer[5] = 5 0 1 5 9 Retirando 5 da posição 0 Buffer[4] = 0 1 5 9 Retirando 0 da posição 1 Buffer[3] = 1 5 9 Retirando 1 da posição 2 Buffer[2] = 5 9 Retirando 5 da posição 3 Buffer[1] = 9 Retirando 9 da posição 4 Buffer[0] = Inserindo 8 na posição 0 Buffer[1] = 8 Inserindo 6 na posição 1 Buffer[2] = 8 6
______________________________________________________________________________________________
Curso Técnico em Informática 242 Programação Java
Inserindo 5 na posição 2 Buffer[3] = 8 6 5 Retirando 8 da posição 0 Buffer[2] = 6 5 Inserindo 3 na posição 3 Buffer[3] = 6 5 3 Inserindo 2 na posição 4 Buffer[4] = 6 5 3 2 Inserindo 6 na posição 0 Buffer[5] = 6 5 3 2 6 Retirando 6 da posição 1 Buffer[4] = 5 3 2 6 Inserindo 3 na posição 1 Buffer[5] = 5 3 2 6 3 Retirando 5 da posição 2 Buffer[4] = 3 2 6 3 Inserindo 2 na posição 2 Buffer[5] = 3 2 6 3 2 Retirando 3 da posição 3 Buffer[4] = 2 6 3 2 Retirando 2 da posição 4 Buffer[3] = 6 3 2 Inserindo 1 na posição 3 Buffer[4] = 6 3 2 1 Retirando 6 da posição 0 Buffer[3] = 3 2 1 Retirando 3 da posição 1 Buffer[2] = 2 1 Inserindo 5 na posição 4 Buffer[3] = 2 1 5 Inserindo 8 na posição 0 Buffer[4] = 2 1 5 8 Inserindo 6 na posição 1 Buffer[5] = 2 1 5 8 6 Retirando 2 da posição 2 Buffer[4] = 1 5 8 6 Inserindo 1 na posição 2 Buffer[5] = 1 5 8 6 1 Retirando 1 da posição 3 Buffer[4] = 5 8 6 1 Inserindo 5 na posição 3 Buffer[5] = 5 8 6 1 5 Retirando 5 da posição 4 Buffer[4] = 8 6 1 5 Inserindo 9 na posição 4 Buffer[5] = 8 6 1 5 9 Retirando 8 da posição 0 Buffer[4] = 6 1 5 9 Inserindo 7 na posição 0 Buffer[5] = 6 1 5 9 7 Retirando 6 da posição 1 Buffer[4] = 1 5 9 7 Inserindo 9 na posição 1 Buffer[5] = 1 5 9 7 9 Retirando 1 da posição 2 Buffer[4] = 5 9 7 9 Inserindo 7 na posição 2 Buffer[5] = 5 9 7 9 7 Retirando 5 da posição 3 Buffer[4] = 9 7 9 7 Retirando 9 da posição 4 Buffer[3] = 7 9 7 Retirando 7 da posição 0 Buffer[2] = 9 7 Inserindo 3 na posição 3 Buffer[3] = 9 7 3 Retirando 9 da posição 1 Buffer[2] = 7 3 Inserindo 6 na posição 4 Buffer[3] = 7 3 6 Inserindo 9 na posição 0 Buffer[4] = 7 3 6 9 Retirando 7 da posição 2 Buffer[3] = 3 6 9 Inserindo 8 na posição 1 Buffer[4] = 3 6 9 8 Retirando 3 da posição 3 Buffer[3] = 6 9 8 Inserindo 2 na posição 2 Buffer[4] = 6 9 8 2 Inserindo 2 na posição 3 Buffer[5] = 6 9 8 2 2 Retirando 6 da posição 4 Buffer[4] = 9 8 2 2 . . .
______________________________________________________________________________________________
Curso Técnico em Informática 243 Programação Java
O Exemplo do Jantar dos Filósofos Glutões
Exemplo para demonstrar o controle e esforço necessário para prevenção de Starva-
tion/Deadlocks
class JantarDosFilosofos { public static void main (String[] args) { /* Mesa de jantar para os filósofos */ MesaDeJantar mesa = new MesaDeJantar (); /* Criação das threads representando os cinco filósofos */ for (int filosofo = 0; filosofo < 5; filosofo++) { new Filosofo("Filosofo_" + filosofo, mesa, filosofo).start(); } } }
______________________________________________________________________________________________
Curso Técnico em Informática 244 Programação Java
class Filosofo extends Thread { /* Tempo máximo (em milesegundos) que o filósofo vai comer ou pensar */ final static int TEMPO_MAXIMO = 100; /* Referência à mesa de jantar */ MesaDeJantar mesa; /* Filósofo na mesa [0,1,2,3,4] */ int filosofo; public Filosofo (String nomeThread, MesaDeJantar mesa, int filosofo) { /* construtor da classe pai */ super(nomeThread); this.mesa = mesa; this.filosofo = filosofo; } public void run () { int tempo = 0; /* Laço representando a vida de um filósofo : pensar e comer */ while (true) { /* sorteando o tempo pelo qual o filósofo vai pensar */ tempo = (int) (Math.random() * TEMPO_MAXIMO); /* filósofo pensando */ pensar(tempo); /* filósofo pegando garfos */ pegarGarfos(); /* sorteando o tempo pelo qual o filósofo vai comer */ tempo = (int) (Math.random() * TEMPO_MAXIMO); /* filósofo comendo */ comer(tempo); /* filósofo devolvendo garfos */ devolverGarfos(); } } /* simula o filósofo pensando */ private void pensar (int tempo) { try { /* filósofo dorme de tempo milisegundos */ sleep(tempo); } catch (InterruptedException e){ System.out.println("Filófoso pensou demais, morreu"); } } /* simula o filósofo comendo */ private void comer (int tempo) { try { sleep(tempo); } catch (InterruptedException e){ System.out.println("Filófoso comeu demais, morreu"); } }
______________________________________________________________________________________________
Curso Técnico em Informática 245 Programação Java
/* pega os garfos */ private void pegarGarfos() { mesa.pegandoGarfos(filosofo); } /* devolve os garfos */ private void devolverGarfos() { mesa.devolvendoGarfos(filosofo); } }
______________________________________________________________________________________________
Curso Técnico em Informática 246 Programação Java
class MesaDeJantar { /* filósofo pensando */ final static int PENSANDO = 1; /* filósofo comendo */ final static int COMENDO = 2; /* filósofo com fome */ final static int COM_FOME = 3; /* Quantidade de filósofos */ final static int QUANT_FILOSOFOS = 5; /* Número do primeiro filósofo */ final static int PRIMEIRO_FILOSOFO = 0; /* Número do último filósofo */ final static int ULTIMO_FILOSOFO = QUANT_FILOSOFOS - 1; /* array[0...QUANT_FILOSOFOS - 1] representando os garfos na mesa : * true = garfo na mesa; false = garfo com filósofo */ boolean[] garfos = new boolean[QUANT_FILOSOFOS]; /* array [0...QUANT_FILOSOFOS - 1] representando o estado de cada um dos filósofos */ int[] filosofos = new int[QUANT_FILOSOFOS]; /* Quantas vezes cada filósofo tentou comer e não conseguiu, * serve para identificar situações de Starvation */ int[] tentativasParaComer = new int[QUANT_FILOSOFOS]; /* Construtor */ public MesaDeJantar() { /* Preenchendo os vetores de Garfos e filósofos à mesa */ for (int i = 0; i < 5; i++) { /* Todos os garfos estão na mesa */ garfos[i] = true; /* Todos os filósofos sentam à mesa pensando */ filosofos[i] = PENSANDO; /* Nenhum filósofo tentou comer ainda */ tentativasParaComer[i] = 0; } } /* filosofo pegando os garfos */ synchronized void pegandoGarfos (int filosofo) { /* filósofo com fome */ filosofos[filosofo] = COM_FOME; /* Deve esperar enquanto algum filósofo vizinho estive comendo */ while (filosofos[aEsquerda(filosofo)] == COMENDO || filosofos[aDireita(filosofo)] == COMENDO) { try { /* Filósofo tentou comer e não conseguiu */ tentativasParaComer[filosofo]++; /* colocando o filosofo para esperar */ wait(); } catch (InterruptedException e) { System.out.println("Filósofo morreu de fome");
______________________________________________________________________________________________
Curso Técnico em Informática 247 Programação Java
} } /* Filósofo conseguiu comer */ tentativasParaComer[filosofo] = 0; /* retirando os garfos esquerdo e direito da mesa */ garfos[garfoEsquerdo(filosofo)] = false; garfos[garfoDireito(filosofo)] = false; /* Filósofo comendo */ filosofos[filosofo] = COMENDO; imprimeEstadosFilosofos(); imprimeGarfos(); imprimeTentativasParaComer(); } /* Filosofo devolvendo os garfos */ synchronized void devolvendoGarfos (int filosofo) { /* Devolvendo os garfos esquerdo e direito da mesa */ garfos[garfoEsquerdo(filosofo)] = true; garfos[garfoDireito(filosofo)] = true; /* Verificando se há algum filósofo vizinho com fome */ if (filosofos[aEsquerda(filosofo)] == COM_FOME || filosofos[aDireita(filosofo)] == COM_FOME) { /* Notifica (acorda) os vizinhos com fome */ notifyAll(); } /* Filósofo pensando */ filosofos[filosofo] = PENSANDO; imprimeEstadosFilosofos(); imprimeGarfos(); imprimeTentativasParaComer(); } /* Retorna o número do filósofo a direita */ private int aDireita (int filosofo) { int direito; /* Caso seja o filósofo nº5, a sua direita está o filósofo nº1 */ if (filosofo == ULTIMO_FILOSOFO) { direito = PRIMEIRO_FILOSOFO; } else { /* Caso contrário */ direito = filosofo + 1; } return direito; } /* Retorna o número do filósofo a esquerda */ private int aEsquerda (int filosofo) { int esquerdo; /* Caso seja o primeiro filósofo a sua esquerda está o último */ if (filosofo == PRIMEIRO_FILOSOFO) { esquerdo = ULTIMO_FILOSOFO; } else {
______________________________________________________________________________________________
Curso Técnico em Informática 248 Programação Java
esquerdo = filosofo - 1; } return esquerdo; } /** Retorna o número do garfo a esquerda do filósofo */ private int garfoEsquerdo (int filosofo) { /* O filósofo 1 possui o garfo 1 a sua esquerda e assim por diante */ int garfoEsquerdo = filosofo; return garfoEsquerdo; } /** Retorna o número do garfo a direita do filósofo */ private int garfoDireito (int filosofo) { int garfoDireito; /* O último filósofo possui o garfo 0 a sua direita*/ if (filosofo == ULTIMO_FILOSOFO) { garfoDireito = 0; } else { garfoDireito = filosofo + 1; } return garfoDireito; } /* Imprimindo os estados dos filósofos */ private void imprimeEstadosFilosofos () { String texto = "*"; System.out.print("Filósofos = [ "); for (int i = 0; i < QUANT_FILOSOFOS; i++) { switch (filosofos[i]) { case PENSANDO : texto = "PENSANDO"; break; case COM_FOME : texto = "COM_FOME"; break; case COMENDO : texto = "COMENDO"; break; } System.out.print(texto + " "); } System.out.println("]"); } /* Imprimindo os que estão na mesa */ private void imprimeGarfos () { String garfo = "*"; System.out.print("Garfos = [ "); for (int i = 0; i < QUANT_FILOSOFOS; i++) {
______________________________________________________________________________________________
Curso Técnico em Informática 249 Programação Java
if (garfos[i]) { garfo = "LIVRE"; } else { garfo = "OCUPADO"; } System.out.print(garfo + " "); } System.out.println("]"); } /* Imprimindo as tentativas de comer dos dos filósofos */ private void imprimeTentativasParaComer () { System.out.print("Tentou comer = [ "); for (int i = 0; i < QUANT_FILOSOFOS; i++) { System.out.print(filosofos[i] + " "); } System.out.println("]"); } }
Resultado da Execução – Jantar do Filósofos Glutões:
Filósofos = [ PENSANDO COMENDO PENSANDO PENSANDO PENSANDO ] Garfos = [ LIVRE OCUPADO OCUPADO LIVRE LIVRE ] Tentou comer = [ 1 2 1 1 1 ] Filósofos = [ PENSANDO COMENDO COM_FOME COMENDO PENSANDO ] Garfos = [ LIVRE OCUPADO OCUPADO OCUPADO OCUPADO ] Tentou comer = [ 1 2 3 2 1 ] Filósofos = [ COM_FOME PENSANDO COM_FOME COMENDO COM_FOME ] Garfos = [ LIVRE LIVRE LIVRE OCUPADO OCUPADO ] Tentou comer = [ 3 1 3 2 3 ] Filósofos = [ COMENDO PENSANDO COM_FOME COMENDO COM_FOME ] Garfos = [ OCUPADO OCUPADO LIVRE OCUPADO OCUPADO ] Tentou comer = [ 2 1 3 2 3 ] Filósofos = [ COMENDO PENSANDO COM_FOME PENSANDO COM_FOME ] Garfos = [ OCUPADO OCUPADO LIVRE LIVRE LIVRE ] Tentou comer = [ 2 1 3 1 3 ] Filósofos = [ COMENDO PENSANDO COMENDO PENSANDO COM_FOME ] Garfos = [ OCUPADO OCUPADO OCUPADO OCUPADO LIVRE ] Tentou comer = [ 2 1 2 1 3 ] Filósofos = [ PENSANDO PENSANDO COMENDO COM_FOME COM_FOME ] Garfos = [ LIVRE LIVRE OCUPADO OCUPADO LIVRE ] Tentou comer = [ 1 1 2 3 3 ] Filósofos = [ PENSANDO PENSANDO COMENDO COM_FOME COMENDO ] Garfos = [ OCUPADO LIVRE OCUPADO OCUPADO OCUPADO ] Tentou comer = [ 1 1 2 3 2 ] Filósofos = [ PENSANDO COM_FOME PENSANDO COM_FOME COMENDO ] Garfos = [ OCUPADO LIVRE LIVRE LIVRE OCUPADO ] Tentou comer = [ 1 3 1 3 2 ] Filósofos = [ PENSANDO COMENDO PENSANDO COM_FOME COMENDO ] Garfos = [ OCUPADO OCUPADO OCUPADO LIVRE OCUPADO ] Tentou comer = [ 1 2 1 3 2 ] Filósofos = [ PENSANDO COMENDO PENSANDO COM_FOME PENSANDO ]
______________________________________________________________________________________________
Curso Técnico em Informática 250 Programação Java
Garfos = [ LIVRE OCUPADO OCUPADO LIVRE LIVRE ] Tentou comer = [ 1 2 1 3 1 ] Filósofos = [ PENSANDO COMENDO PENSANDO COMENDO PENSANDO ] Garfos = [ LIVRE OCUPADO OCUPADO OCUPADO OCUPADO ] Tentou comer = [ 1 2 1 2 1 ] Filósofos = [ PENSANDO PENSANDO PENSANDO COMENDO PENSANDO ] Garfos = [ LIVRE LIVRE LIVRE OCUPADO OCUPADO ] Tentou comer = [ 1 1 1 2 1 ] Filósofos = [ PENSANDO PENSANDO PENSANDO PENSANDO PENSANDO ] Garfos = [ LIVRE LIVRE LIVRE LIVRE LIVRE ] Tentou comer = [ 1 1 1 1 1 ] Filósofos = [ COMENDO PENSANDO PENSANDO PENSANDO PENSANDO ] Garfos = [ OCUPADO OCUPADO LIVRE LIVRE LIVRE ] Tentou comer = [ 2 1 1 1 1 ] Filósofos = [ COMENDO PENSANDO COMENDO PENSANDO COM_FOME ] Garfos = [ OCUPADO OCUPADO OCUPADO OCUPADO LIVRE ] Tentou comer = [ 2 1 2 1 3 ] Filósofos = [ PENSANDO COM_FOME COMENDO COM_FOME COM_FOME ] Garfos = [ LIVRE LIVRE OCUPADO OCUPADO LIVRE ] Tentou comer = [ 1 3 2 3 3 ] Filósofos = [ PENSANDO COM_FOME COMENDO COM_FOME COMENDO ] Garfos = [ OCUPADO LIVRE OCUPADO OCUPADO OCUPADO ] Tentou comer = [ 1 3 2 3 2 ] Filósofos = [ PENSANDO COM_FOME PENSANDO COM_FOME COMENDO ] Garfos = [ OCUPADO LIVRE LIVRE LIVRE OCUPADO ] Tentou comer = [ 1 3 1 3 2 ] Filósofos = [ PENSANDO COMENDO PENSANDO COM_FOME COMENDO ] Garfos = [ OCUPADO OCUPADO OCUPADO LIVRE OCUPADO ] Tentou comer = [ 1 2 1 3 2 ] Filósofos = [ PENSANDO PENSANDO PENSANDO COM_FOME COMENDO ] Garfos = [ OCUPADO LIVRE LIVRE LIVRE OCUPADO ] . . .
Exercícios:
1) Crie uma class que extends a Thread e, no trabalho a ser executado, faça a soma dos números
de 1 a 10. Esse processo deve ser executado em uma nova pilha.
2) Crie uma class que implements runnable e o trabalho a ser feito é que ela conte de 1 à 15 e,
quando um número impar for encontrado, a thread entra em suspensão e depois, quando concluir
a contagem, informe quantas vezes a thread entrou em suspensão.
3) Desenvolva uma class que tenha quatro threads, cada uma com o nome diferente, e o trabalho
a ser feito em uma nova pilha seja imprimir o nome das threads.
4) Faça um programa que imprima os números primos existentes entre 0 e 99999. UTILIZE THREADS. Dica: para cada faixa de mil valores crie um thread e dispare o processo para