250
ESCOLA TÉCNICA ESTADUAL MONTEIRO LOBATO Programação Java Curso Técnico em Informática

Apostila Programação Java

Embed Size (px)

Citation preview

Page 1: Apostila Programação Java

ESCOLA TÉCNICA ESTADUAL MONTEIRO LOBATO

Programação Java

Curso Técnico em Informática

Page 2: Apostila Programação Java

______________________________________________________________________________________________

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

Page 3: Apostila Programação Java

______________________________________________________________________________________________

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

Page 4: Apostila Programação Java

______________________________________________________________________________________________

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

Page 5: Apostila Programação Java

______________________________________________________________________________________________

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

Page 6: Apostila Programação Java

______________________________________________________________________________________________

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

Page 7: Apostila Programação Java

______________________________________________________________________________________________

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

Page 8: Apostila Programação Java

______________________________________________________________________________________________

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

Page 9: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 10: Apostila Programação Java

______________________________________________________________________________________________

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

Page 11: Apostila Programação Java

______________________________________________________________________________________________

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

Page 12: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 13: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 14: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 15: Apostila Programação 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).

Page 16: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 17: Apostila Programação Java

______________________________________________________________________________________________

Curso Técnico em Informática 17 Programação Java

Opções de instalação:

Status de instalação e pasta de destino:

Page 18: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 19: Apostila Programação Java

______________________________________________________________________________________________

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

Page 20: Apostila Programação Java

______________________________________________________________________________________________

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

Page 21: Apostila Programação Java

______________________________________________________________________________________________

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

}

}

Page 22: Apostila Programação 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

Page 23: Apostila Programação Java

______________________________________________________________________________________________

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

Page 24: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 25: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 26: Apostila Programação Java

______________________________________________________________________________________________

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

Page 27: Apostila Programação Java

______________________________________________________________________________________________

Curso Técnico em Informática 27 Programação Java

Criando classe:

Page 28: Apostila Programação Java

______________________________________________________________________________________________

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

Page 29: Apostila Programação Java

______________________________________________________________________________________________

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

Page 30: Apostila Programação Java

______________________________________________________________________________________________

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

Page 31: Apostila Programação Java

______________________________________________________________________________________________

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

Page 32: Apostila Programação Java

______________________________________________________________________________________________

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

Page 33: Apostila Programação Java

______________________________________________________________________________________________

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

Page 34: Apostila Programação Java

______________________________________________________________________________________________

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

Page 35: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 36: Apostila Programação Java

______________________________________________________________________________________________

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

Page 37: Apostila Programação Java

______________________________________________________________________________________________

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

Page 38: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 39: Apostila Programação Java

______________________________________________________________________________________________

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

Page 40: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 41: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 42: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 43: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 44: Apostila Programação Java

______________________________________________________________________________________________

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]

}

Page 45: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 46: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 47: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 48: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 49: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 50: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 51: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 52: Apostila Programação Java

______________________________________________________________________________________________

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

Page 53: Apostila Programação Java

______________________________________________________________________________________________

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

Page 54: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 55: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 56: Apostila Programação Java

______________________________________________________________________________________________

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

Page 57: Apostila Programação Java

______________________________________________________________________________________________

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

Page 58: Apostila Programação Java

______________________________________________________________________________________________

Curso Técnico em Informática 58 Programação Java

Aplicação Java exemplificando a utilização do tipo de dados vetor:

Page 59: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 60: Apostila Programação Java

______________________________________________________________________________________________

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á:

Page 61: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 62: Apostila Programação Java

______________________________________________________________________________________________

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

Page 63: Apostila Programação Java

______________________________________________________________________________________________

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

Page 64: Apostila Programação Java

______________________________________________________________________________________________

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

Page 65: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 66: Apostila Programação Java

______________________________________________________________________________________________

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

Page 67: Apostila Programação Java

______________________________________________________________________________________________

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

Page 68: Apostila Programação Java

______________________________________________________________________________________________

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

Page 69: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 70: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 71: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 72: Apostila Programação Java

______________________________________________________________________________________________

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

}

}

}

Page 73: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 74: Apostila Programação Java

______________________________________________________________________________________________

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

Page 75: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 76: Apostila Programação Java

______________________________________________________________________________________________

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

Page 77: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 78: Apostila Programação Java

______________________________________________________________________________________________

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

Page 79: Apostila Programação Java

______________________________________________________________________________________________

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-

Page 80: Apostila Programação Java

______________________________________________________________________________________________

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;

}

Page 81: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 82: Apostila Programação Java

______________________________________________________________________________________________

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

}

Page 83: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 84: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 85: Apostila Programação Java

______________________________________________________________________________________________

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

Page 86: Apostila Programação Java

______________________________________________________________________________________________

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

Page 87: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 88: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 89: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 90: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 91: Apostila Programação Java

______________________________________________________________________________________________

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

Page 92: Apostila Programação Java

______________________________________________________________________________________________

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,

Page 93: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 94: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 95: Apostila Programação Java

______________________________________________________________________________________________

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

Page 96: Apostila Programação Java

______________________________________________________________________________________________

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

}

}

Page 97: Apostila Programação Java

______________________________________________________________________________________________

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

Page 98: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 99: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 100: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 101: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 102: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 103: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 104: Apostila Programação Java

______________________________________________________________________________________________

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

Page 105: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 106: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 107: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 108: Apostila Programação Java

______________________________________________________________________________________________

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)

Page 109: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 110: Apostila Programação Java

______________________________________________________________________________________________

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

Page 111: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 112: Apostila Programação Java

______________________________________________________________________________________________

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

Page 113: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 114: Apostila Programação Java

______________________________________________________________________________________________

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

Page 115: Apostila Programação Java

______________________________________________________________________________________________

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

Page 116: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 117: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 118: Apostila Programação Java

______________________________________________________________________________________________

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

Page 119: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 120: Apostila Programação Java

______________________________________________________________________________________________

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

Page 121: Apostila Programação Java

______________________________________________________________________________________________

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

Page 122: Apostila Programação Java

______________________________________________________________________________________________

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

}

Page 123: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 124: Apostila Programação Java

______________________________________________________________________________________________

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

Page 125: Apostila Programação Java

______________________________________________________________________________________________

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

Page 126: Apostila Programação Java

______________________________________________________________________________________________

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)

{

Page 127: Apostila Programação Java

______________________________________________________________________________________________

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

Page 128: Apostila Programação Java

______________________________________________________________________________________________

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

Page 129: Apostila Programação Java

______________________________________________________________________________________________

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

Page 130: Apostila Programação Java

______________________________________________________________________________________________

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

Page 131: Apostila Programação Java

______________________________________________________________________________________________

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

Page 132: Apostila Programação Java

______________________________________________________________________________________________

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

Page 133: Apostila Programação Java

______________________________________________________________________________________________

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 {

Page 134: Apostila Programação Java

______________________________________________________________________________________________

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

Page 135: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 136: Apostila Programação Java

______________________________________________________________________________________________

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

Page 137: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 138: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 139: Apostila Programação Java

______________________________________________________________________________________________

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; /**

Page 140: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 141: Apostila Programação Java

______________________________________________________________________________________________

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

Page 142: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 143: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 144: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 145: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 146: Apostila Programação Java

______________________________________________________________________________________________

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

Page 147: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 148: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 149: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 150: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 151: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 152: Apostila Programação Java

______________________________________________________________________________________________

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"/>

Page 153: Apostila Programação Java

______________________________________________________________________________________________

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; } /**

Page 154: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 155: Apostila Programação Java

______________________________________________________________________________________________

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

Page 156: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 157: Apostila Programação Java

______________________________________________________________________________________________

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

Page 158: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 159: Apostila Programação Java

______________________________________________________________________________________________

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 {

Page 160: Apostila Programação Java

______________________________________________________________________________________________

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)

Page 161: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 162: Apostila Programação Java

______________________________________________________________________________________________

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,

Page 163: Apostila Programação Java

______________________________________________________________________________________________

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

Page 164: Apostila Programação Java

______________________________________________________________________________________________

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 {

Page 165: Apostila Programação Java

______________________________________________________________________________________________

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

Page 166: Apostila Programação Java

______________________________________________________________________________________________

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"

Page 167: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 168: Apostila Programação Java

______________________________________________________________________________________________

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

Page 169: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 170: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 171: Apostila Programação Java

______________________________________________________________________________________________

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 (

Page 172: Apostila Programação Java

______________________________________________________________________________________________

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

Page 173: Apostila Programação Java

______________________________________________________________________________________________

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

Page 174: Apostila Programação Java

______________________________________________________________________________________________

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

Page 175: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 176: Apostila Programação Java

______________________________________________________________________________________________

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

Page 177: Apostila Programação Java

______________________________________________________________________________________________

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

Page 178: Apostila Programação Java

______________________________________________________________________________________________

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 (

Page 179: Apostila Programação Java

______________________________________________________________________________________________

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

Page 180: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 181: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 182: Apostila Programação Java

______________________________________________________________________________________________

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 {

Page 183: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 184: Apostila Programação Java

______________________________________________________________________________________________

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

Page 185: Apostila Programação Java

______________________________________________________________________________________________

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 (?, ?)

Page 186: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 187: Apostila Programação Java

______________________________________________________________________________________________

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

Page 188: Apostila Programação Java

______________________________________________________________________________________________

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

Page 189: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 190: Apostila Programação Java

______________________________________________________________________________________________

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 (

Page 191: Apostila Programação Java

______________________________________________________________________________________________

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

Page 192: Apostila Programação Java

______________________________________________________________________________________________

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

Page 193: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 194: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 195: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 196: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 197: Apostila Programação Java

______________________________________________________________________________________________

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

Page 198: Apostila Programação Java

______________________________________________________________________________________________

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[]) {

Page 199: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 200: Apostila Programação Java

______________________________________________________________________________________________

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

Page 201: Apostila Programação Java

______________________________________________________________________________________________

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; /**

Page 202: Apostila Programação Java

______________________________________________________________________________________________

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

Page 203: Apostila Programação Java

______________________________________________________________________________________________

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

Page 204: Apostila Programação Java

______________________________________________________________________________________________

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

Page 205: Apostila Programação Java

______________________________________________________________________________________________

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

Page 206: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 207: Apostila Programação Java

______________________________________________________________________________________________

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

Page 208: Apostila Programação Java

______________________________________________________________________________________________

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

Page 209: Apostila Programação Java

______________________________________________________________________________________________

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

Page 210: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 211: Apostila Programação Java

______________________________________________________________________________________________

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

Page 212: Apostila Programação Java

______________________________________________________________________________________________

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;

Page 213: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 214: Apostila Programação Java

______________________________________________________________________________________________

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:

Page 215: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 216: Apostila Programação Java

______________________________________________________________________________________________

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}”

Page 217: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 218: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 219: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 220: Apostila Programação Java

______________________________________________________________________________________________

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

Page 221: Apostila Programação Java

______________________________________________________________________________________________

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

Page 222: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 223: Apostila Programação Java

______________________________________________________________________________________________

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

Page 224: Apostila Programação Java

______________________________________________________________________________________________

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

Page 225: Apostila Programação Java

______________________________________________________________________________________________

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

...

Page 226: Apostila Programação Java

______________________________________________________________________________________________

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

Page 227: Apostila Programação Java

______________________________________________________________________________________________

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

Page 228: Apostila Programação Java

______________________________________________________________________________________________

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

Page 229: Apostila Programação Java

______________________________________________________________________________________________

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

Page 230: Apostila Programação Java

______________________________________________________________________________________________

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

Page 231: Apostila Programação Java

______________________________________________________________________________________________

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

Page 232: Apostila Programação Java

______________________________________________________________________________________________

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

Page 233: Apostila Programação Java

______________________________________________________________________________________________

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.

Page 234: Apostila Programação Java

______________________________________________________________________________________________

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

Page 235: Apostila Programação Java

______________________________________________________________________________________________

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

Page 236: Apostila Programação Java

______________________________________________________________________________________________

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

}

}

}

Page 237: Apostila Programação Java

______________________________________________________________________________________________

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

Page 238: Apostila Programação Java

______________________________________________________________________________________________

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

Page 239: Apostila Programação Java

______________________________________________________________________________________________

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

Page 240: Apostila Programação Java

______________________________________________________________________________________________

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

Page 241: Apostila Programação Java

______________________________________________________________________________________________

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

Page 242: Apostila Programação Java

______________________________________________________________________________________________

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

Page 243: Apostila Programação Java

______________________________________________________________________________________________

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

Page 244: Apostila Programação Java

______________________________________________________________________________________________

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

Page 245: Apostila Programação Java

______________________________________________________________________________________________

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

Page 246: Apostila Programação Java

______________________________________________________________________________________________

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

Page 247: Apostila Programação Java

______________________________________________________________________________________________

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 {

Page 248: Apostila Programação Java

______________________________________________________________________________________________

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++) {

Page 249: Apostila Programação Java

______________________________________________________________________________________________

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 ]

Page 250: Apostila Programação Java

______________________________________________________________________________________________

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