Manual de Iniciação ao JAVA

217
Manual de Iniciação ao JAVA Prof. Herberto Graça http://nl.linkedin.com/in/hgraca/ [email protected] Esta obra está licenciada com uma Licença Creative Commons Atribuição-Partilha nos termos da mesma licença 4.0 Internacional 26 de janeiro de 2014

Transcript of Manual de Iniciação ao JAVA

Page 1: Manual de Iniciação ao JAVA

Manual de Iniciação aoJAVA

Prof. Herberto Graça http://nl.linkedin.com/in/hgraca/ [email protected]

Esta obra está licenciada com uma Licença Creative CommonsAtribuição-Partilha nos termos da mesma licença 4.0 Internacional

26 de janeiro de 2014

Page 2: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Índice

1 Sobre este manual...................................................................................7

2 Introdução................................................................................................8

3 Ferramentas de Trabalho........................................................................10 3.1 JAVA - J2SE SDK................................................................................10

3.1.1 Download..................................................................................10 3.1.2 Instalação.................................................................................10

3.2 Ferramentas fornecidas com o J2SE SDK.........................................11 3.3 A documentação das classes..........................................................11 3.4 O manual oficial..............................................................................11 3.5 O IDE - Integrated Development Environment................................12

3.5.1 Download..................................................................................12 3.5.2 Instalação.................................................................................12 3.5.3 Configuração básica.................................................................12

4 A utilização do JAVA................................................................................13

5 Conceitos de Prog. Orientada por Objectos............................................15 5.1 Objectos..........................................................................................16 5.2 Mensagens......................................................................................17 5.3 Classes............................................................................................17 5.4 Estrutura em árvore e heranças......................................................18

5.4.1 Extends.....................................................................................19 5.5 Classes abstractas...........................................................................19

5.5.1 Métodos abstractos..................................................................20 5.5.2 Interfaces..................................................................................20

5.6 Polimorfismo....................................................................................21 5.6.1 O polimorfismo ad hoc..............................................................22 5.6.2 O polimorfismo paramétrico.....................................................22 5.6.3 O polimorfismo de herança......................................................23

5.7 Encapsulamento e Ocultação..........................................................23 5.8 Outros conceitos..............................................................................24 5.9 Classes internas (Nested Classes)...................................................24

6 Bases da programação em JAVA.............................................................25 6.1.1 Organização dos ficheiros.........................................................25 6.1.2 Estrutura de um ficheiro de código..........................................25

6.2 Convenção de nomes......................................................................26 6.3 Palavras Reservadas........................................................................26 6.4 Comentários....................................................................................26 6.5 Javadoc............................................................................................27 6.6 Tipos de dados................................................................................29 6.7 Variáveis..........................................................................................29 6.8 Expressões......................................................................................30 6.9 Operadores......................................................................................30 6.10 Entrada e Saída de dados (Teclado/Monitor).................................32

6.10.1 Saída de dados.......................................................................32

Prof. Herberto Graça Página 2 de 217

Page 3: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6.10.2 Entrada de dados...................................................................32 6.11 Estruturas de controlo...................................................................32

6.11.1 while.......................................................................................32 6.11.2 do - while................................................................................33 6.11.3 for...........................................................................................33 6.11.4 if - else....................................................................................34 6.11.5 switch - case...........................................................................34 6.11.6 break......................................................................................34 6.11.7 continue..................................................................................35 6.11.8 label:.......................................................................................35 6.11.9 return......................................................................................35 6.11.10 try - catch - finally................................................................35 6.11.11 throws - throw.......................................................................36 6.11.12 Exercícios..............................................................................36

6.12 Arrays............................................................................................39 6.12.1 Declaração de arrays..............................................................40 6.12.2 Criação de arrays....................................................................40 6.12.3 Aceder ao conteúdo de arrays................................................40 6.12.4 Exercícios................................................................................40

6.13 Vectores.........................................................................................42 6.14 Linked List.....................................................................................43 6.15 HashMap.......................................................................................43

7 Programando com classes.....................................................................45 7.1 Criar uma classe..............................................................................45

7.1.1 Declaração da classe................................................................45 7.1.2 O construtor..............................................................................45 7.1.3 Declaração de membros...........................................................46 7.1.4 O main......................................................................................47 7.1.5 O primeiro programa................................................................47 7.1.6 Convenções de programação...................................................47 7.1.7 Exercícios..................................................................................48

7.2 Utilizar objectos...............................................................................48 7.2.1 Criar um objecto.......................................................................48 7.2.2 Utilizar um objecto....................................................................49 7.2.3 Exercícios..................................................................................50

8 As classes essenciais.............................................................................53 8.1 Tratamento de erros........................................................................53

8.1.1 Tratamento com “try-catch-finally”..........................................54 8.1.2 Tratamento com “throw”..........................................................56 8.1.3 Criar a tua própria Exception....................................................56 8.1.4 Exercícios..................................................................................57

8.2 Threads...........................................................................................58 8.2.1 Criar uma subclasse de Thread................................................58 8.2.2 Implementar a interface Runnable...........................................59 8.2.3 Comunicação entre threads......................................................59 8.2.4 Exercícios..................................................................................61

8.3 Input/Output....................................................................................61 8.3.1 Streams....................................................................................61 8.3.2 Serialização..............................................................................65 8.3.3 Exercícios..................................................................................65

Prof. Herberto Graça Página 3 de 217

Page 4: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

9 Applets...................................................................................................67 9.1 O que é uma applet.........................................................................67 9.2 Como funciona uma applet.............................................................67 9.3 Desenhar e gerir eventos, numa applet (Métodos).........................68 9.4 Inserir uma applet numa página HTML............................................70

9.4.1 Passagem de parâmetros para uma applet..............................71 9.5 Exercícios........................................................................................72

10 Criar um GUI com o JFC/Swing.............................................................73 10.1 Importar os pacotes necessários...................................................73 10.2 Escolher o aspecto do GUI.............................................................73 10.3 JFrame, a base de um GUI.............................................................74 10.4 Colocar botões e etiquetas............................................................75 10.5 Colocar componentes noutros “contentores”................................75

10.5.1 Layout managers....................................................................76 10.6 Criar margens nos componentes...................................................78 10.7 Estabelecer acções para os eventos.............................................78

10.7.1 O que são os eventos.............................................................78 10.7.2 Como implementar um event listener....................................79

10.8 Exercícios......................................................................................80

11 Acesso a Bases de Dados.....................................................................85 11.1 Arquitectura do JDBC.....................................................................85

11.1.1 Modelo de dois nós.................................................................85 11.1.2 Modelo de três nós.................................................................86

11.2 Preparando o acesso ao SGBD......................................................86 11.2.1 Com o SGBD MySQL...............................................................87 11.2.2 Com o SGBD Derby.................................................................87

11.3 Plugins para Eclipse.......................................................................88 11.3.1 Apache Derby Plugins.............................................................88 11.3.2 DTP - Data Tools Platform.......................................................89 11.3.3 AmaterasERD.........................................................................89

11.4 Ligação à Base de Dados..............................................................90 11.5 Envio de comandos a uma Base de Dados....................................91

11.5.1 Enviar comandos que não devolvem dados...........................92 11.5.2 Enviar comandos que devolvem dados..................................92

11.6 Receber dados de uma Base de Dados.........................................93 11.6.1 Aceder às linhas de uma tabela de resultados (ResultSet).....93 11.6.2 Aceder às colunas de uma tabela de resultados (ResultSet). .94

11.7 Actualização de dados na base de dados......................................95 11.8 Tratamento de erros......................................................................96 11.9 Prepared Statements.....................................................................97 11.10 Transactions................................................................................98

11.10.1 Realização uma transaction..................................................98 11.10.2 Criação de um ponto de restauro.........................................99

11.11 Stored Procedures.......................................................................99 11.11.1 Criação de stored procedures...............................................99 11.11.2 Execução de stored procedures..........................................100 11.11.3 Parâmetros nos stored procedures.....................................101 11.11.4 Outras fontes de informação..............................................103

11.12 Exercícios..................................................................................103

Prof. Herberto Graça Página 4 de 217

Page 5: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

12 Relatórios...........................................................................................109 12.1 Ferramentas a utilizar.................................................................109 12.2 Desenhar um relatório.................................................................110

12.2.1 Ligar a uma fonte de dados..................................................110 12.2.2 Obter os dados.....................................................................111 12.2.3 Zonas do relatório................................................................114 12.2.4 Formatação de dados...........................................................115 12.2.5 Agrupamentos, sumarização e ordenação de dados............116 12.2.6 Imagens................................................................................119 12.2.7 Gráficos e Mapas..................................................................120

12.3 Relatórios dinâmicos...................................................................128 12.3.1 Fórmulas e variáveis.............................................................128 12.3.2 Parâmetros...........................................................................131

12.4 Subrelatórios...............................................................................132 12.5 Relatórios de tabelas cruzadas....................................................132 12.6 Exportar um relatório..................................................................132 12.7 Usar um relatório numa aplicação JAVA.......................................133

12.7.1 Bibliotecas a importar..........................................................133 12.7.2 Criar um visualizador interno numa aplicação.....................133

12.8 Exercícios....................................................................................137

13 Optimizações.....................................................................................145 13.1 Optimizações de baixo nível........................................................146

13.1.1 Benchmark de algoritmos.....................................................147 13.1.2 Técnicas de optimização gerais............................................148 13.1.3 Técnicas de optimização específicas....................................149 13.1.4 Exercícios..............................................................................154

13.2 Optimizações de alto nível..........................................................154 13.2.1 Processo de optimização......................................................155 13.2.2 Técnicas algorítmicas............................................................158

13.3 Optimizações para redução de tamanho.....................................160 13.4 Optimizações para a manutenção de código..............................160

14 Empacotamento.................................................................................162 14.1 Pacote executável.......................................................................162

14.1.1 Compilar e executar os nossos programas...........................162 14.1.2 Os ficheiros “.jar”.................................................................162 14.1.3 Criar um “.jar”......................................................................163 14.1.4 Problemas dos “.jar”.............................................................165 14.1.5 Exercícios..............................................................................166

14.2 Pacote instalador.........................................................................167 14.2.1 Instalador multi-plataforma..................................................167 14.2.2 Pacotes MSI (MS Windows)...................................................167 14.2.3 Pacotes DEB (Linux / Debian)...............................................167 14.2.4 Pacotes RPM (Linux / Red Hat)..............................................168 14.2.5 Exercícios..............................................................................168

15 Javadocs.............................................................................................169 15.1 Comentários javadoc...................................................................169 15.2 Etiquetas javadoc........................................................................169 15.3 Gerar a documentação................................................................170

15.3.1 Pela linha de comandos........................................................170

Prof. Herberto Graça Página 5 de 217

Page 6: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

15.3.2 Através do IDE Eclipse..........................................................171 15.4 Exercícios....................................................................................172

16 Java Server Pages e Servlets..............................................................173 16.1 Introdução...................................................................................173

16.1.1 O que são as Servlets...........................................................173 16.1.2 Vantagens das Servlets........................................................173 16.1.3 O que são as JSP...................................................................174 16.1.4 Vantagens das JSP................................................................174

16.2 O servidor....................................................................................175 16.2.1 Download..............................................................................175 16.2.2 Instalação.............................................................................175 16.2.3 Configuração do contexto de desenvolvimento...................176

16.3 JSP...............................................................................................179 16.3.1 Download..............................................................................179

Bibliografia...............................................................................................180

Índice de Ilustrações................................................................................181

Índice de Tabelas......................................................................................183

Índice de Código......................................................................................184

Anexos.....................................................................................................185Anexo 1: Alguns componentes do pacote swing..................................186Anexo 2: Classes utilizadas..................................................................189

Capítulo 4.........................................................................................189Capítulo 10.......................................................................................191

Anexo 3: Resolução dos exercícios.......................................................195Exercícios do Cap. 4.11.....................................................................195Exercícios do Cap. 4.12.....................................................................205Exercícios do Cap. 5.2.......................................................................211Exercícios do Cap. 6.2.......................................................................217Exercícios do Cap. 6.3.......................................................................220Exercícios do Cap. 7..........................................................................221Exercícios do Cap. 8..........................................................................222

Prof. Herberto Graça Página 6 de 217

Page 7: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

1 Sobre este manual

Inicialmente este manual de JAVA foi criado com a intenção de não meesquecer do pouco que tinha aprendido no estágio que realizei em 2002/03, naTurkcell, Turquia. Posteriormente fui acrescentando os conteúdos que fuiaprendendo, com a intenção de o utilizar nas minhas aulas de programação.

Em 2005 (Faro) e 2010 (Évora) apresentei propostas para formações deJava, para professores, que infelizmente nunca foram aceites e uma vez queapenas leccionei Java até ao ano lectivo de 2011/2012 é desde essa altura queeste manual não recebe uma actualização significativa.

Ao longo do manual tento ser muito sucinto na explicação de comofuncionam os vários temas, não é minha intenção fazer um manual científiconem muito detalhado, pretendo fazer explicações simples das bases do JAVAque permitam, a quem lê o manual, ter um pontapé de arranque para aprendermais sozinho.

Este é um manual em constante desenvolvimento e aperfeiçoamento,principalmente porque, como se sabe, a informática evolui a um ritmoalucinante. Assim sendo, uma vez que os conteúdos deste manual poderãoficar rapidamente desactualizados, todas as sugestões e correcções são bemvindas, em especial a adição de exercícios com as respectivas resoluções. Omeu contacto está na capa do manual, e são livres de me contactar com novasversões deste documento.

Prof. Herberto Graça Página 7 de 217

Page 8: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

2 Introdução

A linguagem JAVA, foi inicialmente chamada de OAK devido à árvore quecrescia perto do escritório do seu principal criador, James Gosling. Eledescobriu, todavia, que já existia uma linguagem de programação denominadaOAK e sendo assim, a equipa teve de procurar um novo nome. Eles compravamo café que consumiam numa loja próxima e o tipo de café compradochamava-se Java. Uma vez que o café estava sempre presente enquantotrabalhavam, esse foi o nome escolhido.

Esta linguagem foi desenvolvida pela “Sun MicroSystems”, entretantoincorporada na Oracle, num projecto ambicioso para criar uma nova linguagemde programação. O primeiro objectivo deste projecto era poder criar programaspequenos e portáveis, que pudessem correr em vários tipos de plataformas dehardware diferentes. O segundo objectivo era a construção de programasrobustos, que tivessem o menor número de bugs possível. O terceiro objectivoao construir esta nova linguagem, era que ela fosse fácil de aprender e de usar.Já desde há muito tempo que o mundo da programação contava com muitosprogramadores de C e C++, por isso escolheu-se o seu modelo de sintaxe eadoptaram-se também algumas características de Smalltalk.

A eficácia do JAVA como uma linguagem de programação, pode serilustrada pelo modo como reduz o número de bugs:

• A maior fonte de bugs nas linguagens de programação tradicionaisestá relacionada com um deficiente manejo da reserva dinâmica dememória. Estas falhas podem ser, por exemplo, programas quereservam memória e depois perdem a sua localização ousimplesmente não a libertam. O JAVA trata de toda a gestão dememória sozinho, libertando o programador dessa responsabilidade.A memória é reservada quando um objecto é criado e é libertadaquando um objecto deixa de existir, através de um processochamado “garbage collection”.

• Outra fonte de problemas está relacionada com a indexação dearrays, fora do alcance destes. O C e o C++ não fazem a verificaçãodestes erros mas o JAVA faz.

• O JAVA evita problemas sintácticos relacionados com a herançamúltipla, que é uma característica da programação orientada porobjectos, em C++. O JAVA utiliza interfaces de modo a aproveitar osbenefícios da herança múltipla, evitando os seus problemas.

Prof. Herberto Graça Página 8 de 217

Page 9: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

3 Ferramentas de Trabalho

3.1 JAVA - J2SE SDK

3.1.1 DownloadA primeira ferramenta de trabalho que devemos ter operacional na nossa

máquina, de modo a podermos programar em JAVA, é o próprio JAVA!

O download do ficheiro de instalação do JAVA, pode ser feito através dosseguintes links:

http://java.sun.com/javase/downloads/index.jsp

Na página referida acima, deve ser feito do download do ficheiro “JDK 5.0Update 9” (SDK). Esta designação significa “JAVA Development Kit versão 5,update 9”.

3.1.2 InstalaçãoPara instalar, basta correr o ficheiro de instalação e seguir as instruções.

Depois de instalado, convêm actualizar as variáveis de sistema, da formacomo passo a descrever:

Variável “PATH”:

Escolher “Start” > “Settings” > “Control Panel” > “System” > “Advanced”> “Environment Variables”. Aqui deves editar a variável “PATH” e acrescentarno final um “;” seguido do caminho para o directório “bin” que se situa dentroda directoria de instalação do JAVA. Será algo do tipo “;C:\ProgramFiles\Java\j2re…\bin” .

Esta variável serve para dizer ao sistema onde deve procurar umcomando, quando este é executado na linha de comandos do DOS.

Variável “CLASSPATH”:

Escolher “Start” > “Settings” > “Control Panel” > “System” > “Advanced”> “Environment Variables”. Aqui deves criar a variável “CLASSPATH” e colocaro seguinte no valor da variável:

“.\;C:\Program Files\Java\j2re…\lib\;C:\Program Files\Java\j2re…\lib\ext”1

Esta variável serve para dizer ao sistema onde este deve procurar classesextra. Aqui pode-se introduzir um caminho para uma directoria, um ficheiro“.class”, ou um ficheiro “.jar”.

As descrições anteriores são válidas para o SO Windows XP, para saberinstruções sobre outros SO ou para mais detalhes sobre a instalação, podesconsultar o link: http://java.sun.com/j2se/1.5.0/install.html

1 Este caminho deve ser adaptado ao caminho de instalação do JAVA no teu PC

Prof. Herberto Graça Página 9 de 217

Page 10: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

3.2 Ferramentas fornecidas com o J2SE SDK

O directório “D:\j2sdk1.4.2_01\bin” contem as ferramentas necessáriaspara trabalhar com programas em JAVA. Das muitas ferramentas que sãodisponibilizadas, as mais importantes são as que se seguem:

javac - O compilador da linguagem JAVA

java - O ficheiro de arranque da JVM (Java Virtual Machine).

jar - Agrupa várias classes num único ficheiro

javadoc - Constrói documentos, a partir dos comentários do código

jdb - O debugger do JAVA.

Podes encontrar mais informação sobre as ferramentas disponibilizadaspelo JAVA, em:

http://java.sun.com/j2se/1.5.0/docs/tooldocs/index.html

3.3 A documentação das classes

Esta documentação possui informação detalhada sobre todas as classesdo JAVA, as suas constantes, os seus métodos, a sua utilidade, o modo comofuncionam, o modo como devem ser utilizadas, etc.

O JAVA possui centenas de classes, como é óbvio torna-se impossívelconhecer todas as classes disponibilizadas pelo JAVA, muito menos todos osmétodos de todas as classes! Deste modo, se queremos utilizar todas aspotencialidades disponibilizadas pelo JAVA, a documentação das classestorna-se uma ferramenta indispensável no desenvolvimento de aplicações emJAVA.

Esta documentação pode ser acedida nos links seguintes:

http://www.allimant.org/javadoc/index.php (formato “HTML help”)

http://java.sun.com/j2se/1.5.0/docs/api/index.html (online)

3.4 O manual oficial

O JAVA possui muitas áreas onde programar, e cada uma delas possui assuas particularidades. Apenas um programador com muita experiência deprogramação em JAVA pode dizer que sabe programar em qualquer das áreasde JAVA, e ainda assim, uma vez que ninguém é perfeito, surgem sempredúvidas, ou uma nova alteração de fundo do JAVA. Deste modo, um bommanual é a melhor companhia de um programador, na hora de trabalhar, equal o melhor manual se não um manual em formato digital ainda por cimafornecido gratuitamente pelos criadores desta magnifica linguagem?!

O manual oficial disponibilizado pela “Sun MicroSystems” pode serencontrado em:

Prof. Herberto Graça Página 10 de 217

Page 11: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

http://www.allimant.org/javadoc/index.php (formato “HTMLhelp”)

http://java.sun.com/docs/books/tutorial/index.html (online)

Toda a documentação pode ser encontrada em:

http://java.sun.com/j2se/1.5.0/docs/index.html

3.5 O IDE - Integrated Development Environment

Existem vários editores que podem ser utilizados, uns são mais leves erápidos, outros são mais completos em termos de informação para oprogramador, outros são feitos em JAVA e podem ser utilizados em diferentesSO.

Nesta formação, vamos privilegiar a utilização do IDE “Eclipse” que é feitoem JAVA, e portanto um pouco lento, mas que oferece bastantes facilidades nodesenvolvimento de código, o que se torna especialmente importante paraquem está a iniciar a sua aprendizagem desta linguagem.

3.5.1 DownloadO editor escolhido tem uma licença que permite a sua utilização

livremente. O seu download pode ser feito a partir do seguinte link:

http://www.eclipse.org/downloads/

3.5.2 InstalaçãoA instalação do Eclipse é bastante simples, basta copiar o ficheiro de

instalação para a directoria onde se pretende que o programa fique instalado ecorrer esse mesmo programa.

Depois disso basta criar um atalho do ficheiro “eclipse.exe” e colocá-lo nodesktop (ou onde quiseres).

Prof. Herberto Graça Página 11 de 217

Page 12: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

4 A utilização do JAVA

Apesar de o JAVA ser ideal para programação em redes, uma vez que permite quequalquer máquina na rede possa correr o seu código e possui facilidades paraprogramar a qualquer nível de protocolos de redes, como disse anteriormente, um dosobjectivos do JAVA era criar programas pequenos e portáveis, de modo a quepudessem correr em vários tipos de plataformas. Uma vez que essas característicastornam o JAVA uma ferramenta ideal para programar em redes, tornam-no tambémuma ferramenta ideal para programar para a Internet, sendo mais conhecido por ser alinguagem para programar applets, que não são mais do que pequenos programasque correm dentro do contexto de outros programas, como por exemplo um browserde Internet.

No entanto, é importante realçar que não está limitado a esse tipo deprogramação. O API do JAVA possui classes para criar GUIs, trabalhar comficheiros, aceder a Bases de Dados, trabalhar com XML e muito mais.

Deste modo, o JAVA é, provavelmente, a linguagem de programação quetem uma utilização mais geral e abrangente no tipo de aplicações que podedesenvolver, e prova disso são os ranquings que se podem encontrar naInternet e que colocam o JAVA como uma das linguagens mais utilizadas.

Ilustração 1: Ranking da utilização das Linguagens deProgramação

Prof. Herberto Graça Página 12 de 217

Page 13: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Para além das vantagens já enunciadas, estas são as principais “virtudes”do Java:

• Object-Oriented;

• Multi-Plataforma (“write once, run anywhere” – apesar de às vezesnão ser bem assim);

• Garbage Collector;

• Sintaxe muito user-friendly e, quanto a mim, muito intuitiva mesmopara novatos;

• Programas muito bem estruturados devido à organização porpackages e classes e, devido à capacidade de hierarquizar estasúltimas;

• Bom mecanismo para apanhar e tratar excepções;

• Extensa comunidade de programadores o que facilita a resolução deproblemas;

• Extensa API com packages para tudo e mais alguma coisa (Redes,Criptografia, Web-Services, Applets, Manuseamento de ficheiros).

Prof. Herberto Graça Página 13 de 217

Page 14: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

5 Conceitos de Prog. Orientada por Objectos

Desde sempre, as linguagens de programação têm vindo a evoluir demodo a se tornarem cada vez mais modulares, isto é, o modo como seestrutura o código de um programa, deixa de ser um bloco de código único ecompacto e tende a evoluir para uma situação em que se têm vários pequenosblocos de código que executam uma única tarefa e a executam bem. Por estarazão se utilizam os procedimentos e as funções em Pascal e C. As vantagensda utilização de funções e procedimentos, já todos conhecemos e portanto nãovamos debruçar-nos aqui sobre estes aspectos, no entanto, são as mesmasque nos levam a utilizar objectos sendo que a modularidade dos nossosprogramas será ainda maior trazendo-nos ainda mais facilidades quandotratamos de modificar, adaptar ou reutilizar código. Bons sistemas OOpermitem modificações extensas sem efeitos colaterais ou “bolas de neve”.

Suponhamos, o Objecto Computador. O Objecto Computador, poderia-sedizer, é constituído por outros tantos objectos – Rato, Monitor, Teclado,Colunas, etc. Cada um desses objectos, funciona independentemente docontexto em que estão inseridos, ou seja, seja qual for o Computador (Objectono global com todos os seus componentes) a que “pertençam” cumprem a suafunção. O fabricante, aquando da construção do Rato, não pensa que é parafuncionar “naquele” Computador mas, em qualquer Computador. Istoexemplifica como o programador deverá programar numa LP OO.

Ilustração 2: Exemplo de Objecto Computador

O código por nós produzido, quando se utiliza uma linguagem OO, deveráser modular pensando sempre na sua reutilização. Quer isto dizer que, quandonos propomos a construir o objecto “ComputadorTipoA” (ou seja, desenvolver aclasse “ComputadorTipoA”), devemos construir os objectos (definir as classes)Rato, Monitor, Teclado, etc como módulos separados e independentes. Destaforma quando estamos a construir o “Rato”, não temos de nos preocupar com

Prof. Herberto Graça Página 14 de 217

Page 15: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

as funções, por exemplo, do teclado. Só temos de definir que o nosso Rato temo comportamento que se esperaria de um objecto com esse nome efuncionalidade se, receber X como entrada, tendo nesse caso Y comosaída/resultado.

Se procedermos desta forma para todos os objectos em causa, na classeComputadorTipoA, dizemos que sempre que fôr construido umComputadorTipoA, deve ser adicionado um Rato, um Monitor, etc, não havendonecessidade de estar a definir novamente esses objectos. As vantagens, comojá devem ter percebido tem a ver com o facto de que, quando quisermosconstruir um objecto ComputadorTipoB, TipoC, etc, apenas haverá necessidadede definir os pormenores relativos ao Computador do tipo em causa, oscomponentes do mesmo já estão definidos, podendo ser reutilizados. A istochama-se programação modular e, tem como mais valias:

• Abstracção e divisão de um problema maior, dividindo-o em pequenosproblemas que, conjuntamente, resolverão a nossa questão inicial;

• Reutilização de código em projectos futuros, poupando desse modotempo de desenvolvimento, o que leva a uma maior produtividade/lucro.

5.1 Objectos

Os objectos são a chave para se compreender os conceitos da POO.

Os objectos de software são criados de modo a que possam ser “vistos”como objectos normais da vida real. Deste modo, tal como um objecto real temcaracterísticas e comportamentos, por exemplo, um cão é grande e castanho(características) e pode estar a abanar a cauda ou a ladrar (comportamento),um objecto de software também tem as suas características, que são mantidasem variáveis desse objecto, e os seus comportamentos, que são definidospelos métodos desse objecto. Um método, não é mais do que uma funçãoassociada a um objecto.

Ilustração 3: Exemplo do Objecto ”Cao”

Existem várias condicionantes e restrições que se podem impor aos váriosmembros de um objecto. Por exemplo, se tivermos um objecto do tipocamaleão, ele vai ter um método “acasalar”, no entanto este só vai poder seraccionado por outro objecto do mesmo tipo, e vai ter uma “cor”, que vai poderser alterada, mas apenas por ele próprio, devendo haver um métodoimplementado para o efeito. Os vários tipos de restrições disponíveis em JAVA,serão vistos mais adiante.

Prof. Herberto Graça Página 15 de 217

Se tivermos um objecto do tipo “Cao”, chamado “joca” com as características:

joca.cor=castanho;joca.tamanho=grande;

podemos dizer para ele ladrar:joca.ladrar();

para abanar a cauda:joca.abanarCauda();

ou ainda para correr:joca.correr();

Objectodo tipo

Cao

cortamanho

abanarCauda

ladrarcorrer

Page 16: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Cada objecto tem sua própria memória que consiste em outros objectos.Todo objecto é uma instância de uma classe.

5.2 Mensagens

Um objecto não nos serve de muito se estiver sozinho, por exemplo, umvolante de um carro não nos serve de muito se nós não tivermos o resto docarro. Então podemos dizer que, geralmente, um objecto é uma parte de outroobjecto.

Acontece exactamente a mesma situação com os objectos de software.Um objecto é, geralmente, um componente de um programa composto pormuitos outros objectos sendo, até esse mesmo programa um objecto. Entãoum programa vai funcionar através da interacção entre todos os objectos que ocompõem. Essa interacção vai acontecer através de “mensagens” que unsobjectos enviam para outros. Por exemplo, uma bicicleta não faz nada seestiver encostada à parede, no entanto se nos montarmos na bicicleta epedalarmos, ela começa a andar.

Algumas vezes torna-se necessário mandar informação numa mensagem,por exemplo, ao mudar de “mudança” da bicicleta, temos de dizer para qualmudança queremos mudar.

Ilustração 4: Comunicação entre Objectos

Assim, a computação ocorre com objectos comunicando-se entre sisolicitando que outros objectos executem acções. Objectos comunicam-seenviando e recebendo mensagens. A mensagem é uma requisição para acçãojunto com argumentos necessários para levar adiante a tarefa solicitada.

5.3 Classes

No mundo real tens muitos objectos do mesmo tipo, existem muitascadeiras, muitas bicicletas, muitos carros. Usando a terminologia de POO,dizemos que a tua bicicleta é uma instância da classe bicicleta.

Quando uma fábrica constrói bicicletas, usa sempre o mesmo desenhopois seria uma perdida de tempo estar a fazer um novo desenho para cadabicicleta. Em POO, também temos vários objectos que tem as mesmascaracterísticas por isso, também se utiliza o mesmo desenho para váriosobjectos do mesmo tipo. Por exemplo um objecto segmento de recta, cada

Prof. Herberto Graça Página 16 de 217

eu

umaBicicleta

umaBicicleta.mudarMudança(“segunda”);

Page 17: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

segmento pode ter uma inclinação e um tamanho diferentes, mas todos ossegmentos tem um tamanho e uma inclinação.

Def. 1: Uma Classe

Depois de se ter criado a classe bicicleta, podemos criar tantos objectosdo tipo bicicleta como quisermos, a partir da sua classe. Quando criamos umobjecto, o sistema reserva memória para o objecto e todas as variáveis donovo objecto, chamadas de “variáveis de instância”. Cada nova instância ficacom uma cópia das variáveis de instância definidas na classe.

Para além das variáveis de instância, temos também as variáveis declasse. Uma variável de classe contém informação que é partilhada por todosos objectos da sua classe. Por exemplo, se todas as bicicletas tiverem 18mudanças, então não é necessário estar a reservar memória, em cada objectoda classe bicicleta, para guardar aquele valor. Basta declarar essa variávelcomo sendo uma variável de classe. Uma vez que as variáveis de classe sãopartilhadas por todas as instâncias dessa classe, então se um objecto alterar ovalor dessa variável, esse valor vai ser alterado para todas as instâncias.

Também nos métodos existem métodos de instância e métodos de classe.Um método de classe pode ser chamado a partir da própria classe, enquantoum método de instância tem de ser chamado a partir de uma instância.

Uma classe representa um agrupamento de objectos semelhantes comointeiros e listas. A classe é um repositório do comportamento associado aosobjectos, ou seja, todos os objectos que são instâncias de uma mesma classepodem realizar as mesmas acções.

5.4 Estrutura em árvore e heranças

Em geral, os objectos são definidos em termos de classes. Podemos nãosaber o que é uma “BMX”, mas se nos disserem que é uma bicicleta, entãosabemos que tem duas rodas, pedais, travões etc.

Uma bicicleta de montanha também é uma bicicleta e por isso partilhamuitas características de uma “BMX”, no entanto tem muitas outrascaracterísticas diferentes. Por isso, se quisermos criar um objecto bicicleta decada tipo, necessitamos de classes diferentes, ainda que estes pertençam àmesma classe! Consegui confundir-te?

Prof. Herberto Graça Página 17 de 217

Uma classe é um protótipo que define asvariáveis e os métodos comuns a todos osobjectos de um determinado tipo.

Page 18: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

O tipo de relação descrito antes, é traduzido para POO, através deheranças entre classes, tal como mostra o seguinte esquema:

Ilustração 5: Comunicação entre Objectos

Os métodos das classes também são passados como herança para as suassubclasses, no entanto, caso seja necessário, uma subclasse pode reescrever ométodo que herdou. Por exemplo, a classe Bicicleta fornece um método parafazer a mudança de mudança, contudo, se a bicicleta de montanha tiver maismudanças possíveis, será necessário reescrever esse método para estasubclasse.

As classes são organizadas numa única estrutura de árvore chamada dehierarquia de herança. Os atributos e os comportamentos associados ainstâncias de uma classe são automaticamente disponíveis a qualquer classeassociada a um descendente nesta estrutura de árvore.

5.4.1 ExtendsQuando uma classe “C” faz extends de uma outra classe “B”, está a

herdar todos os métodos e variáveis definidos nessa classe “B”.

No entanto, se essa última classe definir uma variável/método que jáexista na classe herdada, será feito um override, ou seja, ignora a criaçãoprévia na “classe pai” (o termo é superclasse). Repare no exemplo seguinte

Prof. Herberto Graça Página 18 de 217

Bicicleta

BMX BicicletaMontanha

Page 19: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

5.5 Classes abstractas

Muitas vezes temos conceitos que se aplicam a todo um conjunto declasses, determinando comportamentos que gostaríamos de herdar de umasuperclasse, mas não faria sentido instanciar objectos desta superclasse.

Definimos então esta superclasse como sendo abstracta, de modo quepossa fornecer propriedades e funções a classes derivadas, ou utiliza-la comotipo de dados para referências, mas não seja permitido criar instâncias.

Ou seja, os programadores podem definir classes abstractas com a únicafunção de definir comportamentos e características genéricos para as suassubclasses.

5.5.1 Métodos abstractosO uso do polimorfismo exige a compatibilidade de tipo entre os objectos

envolvidos, o que em geral se obtém com o uso de superclasses.

Mas há situações em que não é possível fornecer uma implementaçãopadrão para ser herdada; criar uma classe abstracta com métodos vazios não éelegante...

Nestes casos a implementação da superclasse abstracta é “incompleta”:as classes concretas derivadas devem completar as funções herdadas.

Um método abstracto fornece apenas uma assinatura, mas nenhumaimplementação.

Métodos abstractos só podem ser definidos em classes abstractas.

Uma subclasse deve implementar todos os métodos abstractos herdados,ou deve ser ela mesma declarada como sendo abstracta.

5.5.2 InterfacesUm comando de televisão pode ser visto como uma interface da televisão,

que permite a interacção entre uma pessoa e uma televisão. É portanto algoque permite a interacção entre dois objectos que não se relacionam em nada.

Em POO, uma interface tem a mesma utilidade. Por exemplo, suponhamosque temos, numa loja, um programa que faz o inventário da loja. Para fazer oinventário, precisa de recolher determinada informação de cada objecto,numero, tipo e preço. Deste modo, para esse programa poder recolher essainformação, precisa ter uma interface com esse objecto. Assim, seriaimplementado em cada objecto da loja, uma mesma interface que permitisseao programa interagir com os objectos de modo a recolher a informaçãonecessária.

Em linguagens OO podemos definir classes abstratas puras (onde todos osmétodos são abstratos) para utilizar polimorfismo sem herdar comportamentosque não serão utilizados. O Java extende este conceito para a definição deinterfaces.

Interfaces são classes que não definem a implementação dos métodos,mas apenas as suas assinaturas (nomes e argumentos). Interfaces não podem

Prof. Herberto Graça Página 19 de 217

Page 20: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

ter atributos e todos os seus métodos são implicitamente abstratos e públicos.

Uma classe pode extender apenas uma única superclasse (para evitarconflitos entre os comportamentos herdados), mas pode implementar váriasinterfaces (mesmo que elas definam métodos com a mesma assinatura).

Podemos declarar variáveis tipadas por interfaces da mesma forma quevariáveis tipadas por classes. O primeiro caso indica uma referência paraqualquer objecto que implemente a interface, o segundo caso indica umareferência para qualquer objecto da classe ou de suas subclasses.

As interfaces permitem definir funcionalidades baseadas em conceitos quese aplicam a várias classes distintas (em hierarquias de especializaçãodiferentes):

• Uma classe estende uma outra classe

• Uma classe implementa uma ou várias interfaces

• Uma interface estende uma ou várias interfaces

• Uma classe pode, ao mesmo tempo, estender outra classe eimplementar uma ou várias interfaces

Assim, o JAVA não suporta herança múltipla, ou seja, apenas pode“estender” uma classe. No entanto, pode implementar (implements) váriasInterfaces. Uma interface serve para “obrigar” uma classe a ter umadeterminada estrutura, um determinado conjunto de métodos e/ou variáveis.Nesta apenas estão definidas as assinaturas dos métodos.

5.6 Polimorfismo

A palavra polimorfismo vem do grego e significa que pode tomar váriasformas. Esta característica é um dos conceitos essenciais da programação

Prof. Herberto Graça Página 20 de 217

Page 21: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

orientada para o objecto. Enquanto a herança se refere às classes (e à suahierarquia), o polimorfismo diz respeito aos métodos dos objectos.

Distinguem-se geralmente três tipos de polimorfismo:

• Polimorfismo ad hoc (igualmente sobrecarga ou em inglêsoverloading)

• Polimorfismo paramétrico (em inglês template)

• Polimorfismo de herança (igualmente redefinição, especialização ouem inglês overriding)

Ilustração 6: Polimorfismo

Vamos agora tentar definir mais precisamente tudo isto, mas é importantenotar que existe muita confusão quando se trata de diferenciar todos os tiposde polimorfismo.

5.6.1 O polimorfismo ad hocO polimorfismo ad hoc permite ter funções do mesmo nome, com

funcionalidades similares, em classes sem nenhuma relação entre elas (a nãoser, claro, serem filhas da classe objecto). Por exemplo, a classe complexa, aclasse imagem e a classe relação podem ter, cada uma, uma função “afixar”.Isto permitirá não ter de se preocupar com o tipo do objecto que temos sedesejarmos mostrá-lo no ecrã.

O polimorfismo ad hoc permite assim definir operadores cuja utilizaçãoserá diferente de acordo com o tipo dos parâmetros que lhes são passados. Épor isso possível, por exemplo, sobrecarregar o operador + e fazê-lo realizaracções diferentes conforme se trate de uma operação entre duas totalidades(adição) ou entre duas cadeias de caracteres (concatenação).

5.6.2 O polimorfismo paramétricoO polimorfismo paramétrico representa a possibilidade de definir várias

funções do mesmo nome mas possuindo parâmetros diferentes (em númeroe/ou tipo). O polimorfismo paramétrico torna assim possível a escolhaautomática do bom método a adoptar em função do tipo de dado passado emparâmetro.

Assim, pode-se por exemplo definir vários métodos homónimos adição ()efectuando uma soma de valores.

• método int addition (int, int) poderá dar a soma de duas totalidades

Prof. Herberto Graça Página 21 de 217

Page 22: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• método float addition (float, float) poderá dar a soma de doisflutuantes

• método char addition (char, char) poderá definir à vontade do autora soma de dois caracteres, etc.

Chama-se assinatura ao número e tipo (estático) dos argumentos de umafunção. É por conseguinte a assinatura de um método que determina qual seráchamado.

5.6.3 O polimorfismo de herançaA possibilidade de redefinir um método em classes que são herdeiras de

uma classe básica chama-se a especialização. É então possível chamar ométodo de um objecto sem estar a preocupar-se com o seu tipo intrínseco:trata-se do polimorfismo de herança. Isto permite fazer abstracção dosdetalhes das classes especializadas de uma família de objecto, mascarando-ocom um interface comum (que é a classe básica).

Imagine um jogo de xadrez que comporta os objectos rei, rainha, bispo,cavaleiro, torre e peão, descendentes do objecto peça.

O método movimento () poderá, graças ao polimorfismo de herança,efectuar o movimento adequado em função da classe do objecto remetido nomomento da chamada. Isto permitirá nomeadamente ao programa dizerpeça.movimento sem ter de se preocupar com a classe da peça.

5.7 Encapsulamento e Ocultação

O encapsulamento é um mecanismo que consiste em reunir os dados e osmétodos numa estrutura escondendo a implementação do objecto, ou seja,impedindo o acesso aos dados por um meio diferente dos serviços (métodos,funções) propostos. O encapsulamento permite por conseguinte garantir aintegridade dos dados contidos no objecto.

O utilizador de uma classe não tem necessariamente de saber como estãoestruturados os dados no objecto, isto significa que um utilizador não tem deconhecer a aplicação. Assim, proibindo o utilizador de alterar directamente osatributos, e obrigando-o a utilizar as funções definidas para alterá-los,podemos garantir a integridade dos dados (poderá por exemplo garantir que otipo dos dados fornecido está conforme ao desejado, ou ainda que os dados seencontram no intervalo esperado).

O encapsulamento permite definir níveis de visibilidade dos elementos daclasse. Estes níveis de visibilidade definem os direitos de acesso aos dadosconforme se aceda por um método da própria classe, de uma classe herdeira,ou de uma classe qualquer. Existem três níveis de visibilidade:

• pública: as funções de todas as classes podem aceder aos dados ouaos métodos de uma classe definida com o nível de visibilidadepública. Trata-se de mais baixo nível de protecção de dados;

• protegida: o acesso aos dados está reservado às funções dasclasses que se encontram no mesmo pacote, sejam subclasses ou

Prof. Herberto Graça Página 22 de 217

Page 23: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

não;

• privada: o acesso aos dados é limitado aos métodos da própriaclasse. Trata-se do nível de protecção dos dados mais elevado

5.8 Outros conceitos

• static: a declaração de um método ou de uma variável static servepara:

▪ Numa variável: Utiliza-se para que todas as instâncias deobjectos dessa classe possam aceder a uma variável comosendo comum entre todas elas. Ou seja, quando alteram avariável numa das instâncias criadas, o seu valor será alteradoem todas as instâncias daquele mesmo objecto;

▪ Num método: Utilizado para que um método seja utilizadoapenas na sua classe e não nas instâncias da mesma.

• abstract: quando se aplica a métodos, serve para indicar que ométodo em causa deverá ser definido nas suas subclasses (classesque herdem a classe onde o método foi definido). No caso dasclasses, indica que a classe não está completamente definida ecomo tal não pode ser instanciada (utilizado, por exemplo, emInterfaces).

• final: utiliza-se para declarar constantes, ou seja, valores que nãosão alterados durante a execução de um programa.

5.9 Classes internas (Nested Classes)

São classes definidas dentro de classes e que serão utilizadas no contextodestas últimas.

Prof. Herberto Graça Página 23 de 217

Page 24: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6 Bases da programação em JAVA

A sintaxe do JAVA baseia-se na do C e do C++. Como resultado, o modo básico de declarações, avaliação de expressões, controlo de fluxo e comentários, são praticamente idênticos.

Neste capítulo vamos apenas fazer uma revisão desta sintaxe, e o modo como se utiliza em JAVA.

6.1.1 Organização dos ficheirosOs ficheiros de código fonte têm uma

organização específica convencionada. Assim,dentro da directoria principal do projecto, devemoster duas directorias, uma chamada “src” e outrachamada “bin”. A pasta bin é onde serão colocadosos ficheiros “executáveis” resultantes da compilaçãodos nossos ficheiros de código. Na pasta src, iremoster todos os ficheiros de código fonte, organizadosem sub-pastas a que chamamos de pacotes(package). Estes pacotes servem para separar ocódigo de vários programadores, separar o códigode várias secções do projecto e ajudar ao controlode permissões de acesso, como veremos mais àfrente.

6.1.2 Estrutura de um ficheiro de códigoA estrutura de um programa em JAVA assemelha-se muito à estrutura de

um programa em C. As secções de código existentes em C existem tambémem JAVA e a ordem em que se colocam é também a mesma. A única diferençarelevante é que em JAVA existem mais duas secções, a localização, queespecifica qual o pacote a que a classe pertence, e a definição da classe.

Programa em C Programa em JAVA

Directivas

Vars. globais

Funções

Programa

#include <stdio.h>

int y;

int umaFunção(int x){ …}

void main (){ …

}

Localização

Directivas

Def. Classe

Vars. globais

Funções

Programa

package pacote;

import java.io.IOException;

public class Baralho {

int uma_variavel;

public int umaFunção(int x){…

}

public static void main(String[] args){…

}}

Ilustração 8: Estrutura de um ficheiro de código, em C e em JAVA.

Prof. Herberto Graça Página 24 de 217

Ilustração 7: Organização deum projecto java

Page 25: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6.2 Convenção de nomes

É importante no nosso código, utilizar os standards de nomes para a LP naqual estamos a programar. Isso facilita a compreensão do nosso código. ParaJava, utilizam-se as seguintes convenções:

• Nome de Ficheiros – estes deverão começar por maiúsculas e terum nome o mais descritivo possível. Caso se deseje atribui um nomecom várias palavras, a primeira letra de cada uma delas deverá sermaíuscula. Exs.: Automovel.java, AutomovelPesado.java,Circulo.java, FiguraGeometrica.java, etc;

• Nome de Classes – deverão ser idênticos ao nome dos ficheirosretirando, o “.java”. Exs.: Automovel, AutomovelPesado, Circulo,FiguraGeometrica, etc;

• Nome de Métodos – segue as regras dos ficheiros/classes comligeiras modificações: a primeira letra é uma minúscula, caso sejaum método de atribuição de um valor a uma variável deverácomeçar por “set”, caso seja um método para obter o valor atribuídoa uma variável deverá começar por “get”. Exs.: getPesoAutomovel(),setCorAutomovel(), getRaioCirculo(), setTipoFiguraGeometrica();

• Nome de Variáveis – situação idêntica à dos métodos (no caso devariáveis não existirá gets nem sets). Exs.: contador, limiteMaximo,nomeGestorConta;

• Nome de Constantes – em maíusculas. Se contiver váriaspalavras, estas deverão ser separadas por underscore (‘_’). Exs.:CONSTANTE_GRAVITACIONAL, MAX_PESO_PERMITIDO;

6.3 Palavras Reservadas

Ao definir os nomes das variáveis e métodos nos nossos programas, à queter em atenção as palavras reservadas existentes na LP. Tal como em outras,existem palavras que estão “proibidas” de ser utilizadas uma vez que estas sãonomes de métodos/tipos pré-definidos. Em Java são as seguintes:

private, protected, public, abstract, class, extends, final,implements, interface, new, static, strictfp, synchronized, transient,volatile, break, case, continue, default, do, else, for, if, instanceof,return, switch, while, assert, catch, finally, throw, throws, try, import,package, boolean, byte, char, double, float, int, long, short, super,this, void, const, goto, null, true, false

6.4 Comentários

O JAVA reconhece os mesmos tipos de comentários do C e do C++.

Utiliza “/*…*/” para comentários de várias linhas e “//” para comentáriosde apenas uma linha. Estes último método é mais aconselhado, uma vez quepode ser inserido dentro de um bloco de comentários assinalado com “/*…*/”.

Prof. Herberto Graça Página 25 de 217

Page 26: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Existe também um outro tipo de sinalização para comentários “/**…*/”que é lido como um comentário normal, mas é também utilizado para gerardocumentação externa acerca desse código, os chamados “javadocs”. Assim,quando um programador introduz comentários no seu código, desta maneira,está ao mesmo tempo a criar a sua documentação.

6.5 Javadoc

Uma ferramenta muito útil e que deve ser utilizada para fazer adocumentação dos nossos projectos (a documentação técnica) é o Javadoc.Esta ferramenta já vem com o SDK que necessitamos de instalar paraprogramar em Java, como demonstrado no anterior tutorial. Esta ferramenta,de uma forma simples, permite criar documentação no formato da API do Java,sendo por isso uma mais valia para todos os developers.

Para conseguir tal feito, os comentários nos nossos programas, ao invésde no formato normal, terão de estar num formato especial – muito simplista –que será reconhecido e compilado pelo próprio compilador do Java, tendo comooutput a API do nosso projecto em formato HTML.

Assim, existem dois tipos de comentários no formato Javadoc: Class-levelComments e Member-level Comments, qualquer um deles começa por ‘/**’ eacaba em ‘*/’.

• Class-level comments são utilizados para descrever a classe e sãocolocados logo acima da linha de código que inicializa a classe:

Ilustração 9: Comentário de classe

• Member-level comments servem para fazer a descrição dosconstrutores da classe, dos métodos da mesma, etc:

Prof. Herberto Graça Página 26 de 217

Page 27: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Ilustração 10: Comentários de membros

Generalizando, ou comentários são construídos no seguinte formato:

Ilustração 11: Generalização dos comentários ao código

As tags mais utilizadas em Javadoc – apesar de existirem outras mais – sãoas seguintes:

@author: Autor da classe;

@param: parâmetro do método ou do construtor;

@return: o que o método retorna;

@throws: descreve uma excepção que poderá ser lançada pelométodo;

@exception: descreve uma excepção;

@version: versão de uma classe ou de um método

Prof. Herberto Graça Página 27 de 217

Page 28: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Depois de termos os nossos comentários num formato Javadoc, paraconstruir a nossa API, temos de executar o seguinte comando (existem maisflags que podem ser adicionadas, estes são os parâmetros base):

javadoc –d directoria_destino_api –sourcepath path_src_projecto

Existe muito mais informações sobre Javadoc – tags, flags de compilação,etc –, o que aqui foi apresentado foi o básico para utilizar a ferramenta. Para osmais curiosos, podem obter mais informações nos seguintes links:

http://pt.wikipedia.org/wiki/Javadoc

http://java.sun.com/j2se/1.3/docs/tooldocs/win32/javadoc.html

http://java.sun.com/j2se/javadoc/writingdoccomments/index.html

6.6 Tipos de dados

O JAVA tem suporte para os tipos de dados nativos presentes na tabelaseguinte. Os tipos de dados nativos são os tipos de dados disponibilizados pelocompilador. Todos os outros tipos de dados disponibilizados pelo JAVA, comopor exemplo o tipo String, são tipos definidos como classes pelosprogramadores.

Tipo Contém Valor pordefeito

Tamanho (bits) Valores Min e Max

boleano Verd. ou falso falso 1 -

char caracter \u0000 16 \u0000 até \uFFFF

byteInteiro com

sinal 0 8 -128 até 127

short Inteiro comsinal

0 16 -32768 até 32767

intInteiro com

sinal 0 32-2147483648 até

2147483647

long Inteiro comsinal

- 64-9223372036854775808

até9223372036854775807

float IEEE754 flt. pt. 0.0 32+/-3.40282347E+38

até+/-1.40239846E-45

Tabela 1: Tipos de dados nativos

6.7 Variáveis

Mais uma vez, a declaração de variáveis em JAVA é bastante semelhante àdeclaração de variáveis em C e C++.

Para os tipos de dados nativos, a sintaxe utilizada pode ser sumariadapelas premissas seguintes:

• O nome do tipo tem apenas uma palavra

Prof. Herberto Graça Página 28 de 217

Page 29: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• Uma lista de variáveis separadas por virgulas

• Uma inicialização opcional seguindo cada variável

• Um ponto e virgula para terminar

Por exemplo:

Declaração de um inteiro de nome “i”:

int i;

Declaração de dois inteiros de nomes “i” e “j”:

int i, j;

Declaração de dois inteiros de nomes “i” e “j” e sua inicialização:

int i = 3, j = 4;

6.8 Expressões

Mais uma vez tal como em C e C++, as expressões funcionam do mesmomodo em JAVA!

Vejamos alguns exemplos:

int a = 1; // Declaração e inicialização

int b = 45; // Declaração e inicialização

int c; // Declaração

c = b; // Atribuição

c = c + a; // Calculo e atribuição

c += a; // Incremento e atribuição estilo C

6.9 Operadores

Também aqui as semelhanças entre o JAVA e o C, C++, são evidentes,restando-me chamar a atenção para alguns dos operadores mais pertinentes,na tabela seguinte.

Prof. Herberto Graça Página 29 de 217

Page 30: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Operador Utilização Exemplo

(tipo) Fazer a conversão entre tiposint a=10;float b;b= (float) a; //converte a para float

instanceof Verifica se um objecto é de umadeterminada classe

umObjecto.instanceof(umaClasse);

^XOR, retorna 1 se alguma das 2

condições for verdadeira, mas 0 seforem as 2 verdadeiras

A B XOR0 0 00 1 11 0 11 1 0

&&, ||AND e OR, mas só avalia a 2ª

expressão caso ainda possa fazerdiferença no resultado final

((Expr1)&&(Expr2));//só avalia Expr2 se Expr1=1((Expr1)||(Expr2));//só avalia Expr2 se Expr1=0

?: O mesmo que “if-else” (Expr1)? A=1:A=0;//if(Expr1) A=1; else A=0;

Tabela 2: Descrição de alguns operadores

Na tabela seguinte, exponho a precedência de operadores em JAVA.

Precedência Operador Tipo deoperandos

Associatividade Operação

1

++ aritméticos D pré ou pós incremento

-- aritméticos D pré ou pós incremento

+, - aritméticos D Positivo, negativo

~ inteiro D negação binária

! boleano D Negação lógica

(tipo) qualquer D “cast”

2 *, /, % aritméticos E Multiplicação, divisão, resto

3+, - aritméticos E adição, subtracção

+ String E concatenação de Strings

4

<< inteiros E shiftagem para a Esq.

>> inteiros E shiftagem para a Dir. com sinal

>>> inteiros Eshiftagem para a Dir. com

preenchimento a zeros

5<, <=, >, >= aritméticos E Menor, menor ou igual, maior, maior

ou igual

instanceof objectos, tipos E Comparação de tipos

6==, != nativos E Valores iguais ou diferentes

==, != objectos E Refere-se ao mesmo objecto ou não

7 & Inteiro, boleano E AND binário e boleano

8 ^ Inteiro, boleano E XOR binário e boleano

9 | Inteiro, boleano E OR binário e boleano

10 && boleano E AND boleano condicional

11 || boleano E OR boleano condicional

12 ?:Boleano, qualquer,

qualquer D Operador condicional

13

= Variável, qualquer D atribuição

*=, /=, %=,+=, -=, <<=,>>=, >>>=,&=, ^=, |=

Variável, qualquer D Atribuição após operação

Tabela 3: Precedência de operadores

Prof. Herberto Graça Página 30 de 217

Page 31: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6.10 Entrada e Saída de dados (Teclado/Monitor)

6.10.1 Saída de dadosEscrever qualquer coisa na consola (linha de comandos), usando o JAVA, é

bastante simples. Basta chamar a função “print” ou “println”, da stream “out”,da classe “System”, e passar-lhe as variáveis que queremos excrever naconsola. Quando temos várias variáveis para escrever, usamos o símbolo “+”para as concatenar (juntar).

package xpto;

public class Exemplo_saida_de_dados {public static void main(String[] args){

String outroTexto="Bla bla bla !"; int val = 0 ;

System.out.println("Um texto qualquer");System.out.println("Outro texto qualquer: "+outroTexto); System.out.println("Um numero inteiro: "+val); System.out.println("Um numero inteiro: "+val+" "+outroTexto);

}}

6.10.2 Entrada de dadosPara ler algo da linha de comandos (consola), é um pouco mais

complicado do que para escrever. Primeiro é necessário criar um buffer paraguardar os dados de uma stream de entrada. No entanto, este buffer guarda osdados em modo texto e portanto se quisermos ler, por exemplo, um númerointeiro vamos ter de converter o texto lido para o tipo de dados “int”. Estaconversão é realizada utilizando a função “parse…” que existe nas váriasclasses representativas dos tipos de dados. Para cada tipo de dados quequeiramos ler, teremos de utilizar a classe representativa e a função parsecorrespondente.

Para facilitar este processo podemos utilizar uma classe que nos permitaler qualquer tipo de dados, como por exemplo a classe KeyboardInput (verAnexo 2).

6.11 Estruturas de controlo

Novamente, as estruturas de controlo têm uma sintaxe semelhante ao C eC++, existinto apenas um novo tipo de estruturas de controlo em JAVA. Sendoassim, os tipos de estruturas de controlo existentes são as seguintes:

Tipo de estrutura Palavras-chave“looping” while, do-while , for

Tomada de decisões if-else, switch-case

“Branching” break, continue, label:, return

Tratamento de excepções (erros) try-catch-finally, throw

Tabela 4: Tipos de estruturas de controlo existentes em JAVA

6.11.1 whileEsta instrução executa um bloco de instruções enquanto uma determinada

Prof. Herberto Graça Página 31 de 217

Page 32: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

condição for verdadeira. A condição é verificada antes do bloco de instruçõesser executado.

while ( <expressão boleana> ){ <instruções> }

while (getMember (i)) i++;

6.11.2 do - whileEsta instrução executa um bloco de instruções enquanto uma determinada

condição for verdadeira. A condição é verificada depois do bloco de instruçõesser executado, o que significa que o bloco de instruções será executado pelomenos uma vez.

do{ <instruções> }while (<expressão boleana>)

do{a += a;

}while (a <= limit / 2);

6.11.3 forEsta instrução executa um bloco de instruções enquanto uma determinada

condição for verdadeira. A condição é verificada antes do bloco de instruçõesser executado.

A diferença para a instrução while é que o for fornece um local especificopara colocar as condições de inicialização e iteração de variáveis.

for ( <inicialização>; <expressão boleana>; <condição de iteração>){<instruções>

}

for (i=0; i<22; i++){ a=a+i;}

Prof. Herberto Graça Página 32 de 217

Page 33: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6.11.4 if - elseA instrução if permite fazer a escolha entre dois blocos de instruções, de

acordo com o resultado de uma expressão boleana.

if (< expressão boleana > ){ <instruções> }else{ <instruções> }

if (i > 0)x = y * z;

else // o else é opcionalx = 0;

6.11.5 switch - caseA instrução switch permite fazer a escolha entre vários blocos de

instruções, de acordo com o resultado de uma expressão que retorna um valorinteiro.

switch ( <expressão inteira> ){ case <inteiro>: <instruções>; break;case <inteiro>: <instruções>; break;case <inteiro>: <instruções>; break;default: <instruções>; break; //opcional

}

int numero = 1;switch (numero) {

case 1: System.out.println("um"); break;case 2: System.out.println("dois"); break;default: System.out.println("outro num."); break;

}

6.11.6 breakEsta instrução é utilizada dentro de um loop, e provoca a saída imediata

do loop onde se encontra.

while ( 1==1 ) { // sempre verdade!<instruções>

if ( a==b ) break; // sai do loop!<instruções>}

for ( i=1 ; i<=10 ; i++ ){for ( j=1 ; j<=10 ; j++ ){

if ( j==5 ) break; // sai do loop j, não do loop i <instruções>

}}

Prof. Herberto Graça Página 33 de 217

Page 34: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6.11.7 continueTambém se utiliza esta instrução dentro de um loop, e provoca o início

imediato de uma nova iteração, caso a expressão de avaliação seja verificada.

int i;for( i=1 ; i<=10 ; i++ ){

if (i == 5) continue; //passa imediatamente para a iteração <instruções> //seguinte sem executar estas instruções

}

6.11.8 label:Em C e C++, esta instrução é utilizada com a instrução goto. No entanto

em JAVA, a instrução label é usada em conjunto com as instruções break econtinue, nos casos em que temos ciclos aninhados. Deste modo, se usada emconjunto com a instrução break, podemos especificar qual o ciclo de quepretendemos sair e se usada em conjunto com a instrução continue, podemosespecificar qual o ciclo que pretendemos continuar.

Point_A: a = x + y;<instruções>

loop1:while (a != b){<instruções>while (i != j){

<instruções>if (zztop > y+1) break loop1; //sai dos 2 loops

<instruções>}

}

6.11.9 returnA instrução return serve para sair de um método (função), podendo ser

utilizada de dois modos, um em que se retorna um valor e outro em que não seretorna nada. Quando se utiliza esta instrução, é necessário ter em atençãoque, o valor a retornar por esta expressão deve ser do mesmo tipo declaradocomo tipo de retorno do método. Se o tipo de retorno do método for void entãoesta instrução deverá ser utilizada sem argumentos.

return ++count; //retorna o resultado de uma expressão

return; //não retorna nada (void)

6.11.10 try - catch - finallyO JAVA possui um mecanismo conhecido como exceptions que ajuda a

fazer o tratamento de erros. Quando ocorre um erro, o JAVA lança uma

Prof. Herberto Graça Página 34 de 217

Page 35: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

exception, que quer dizer que o programa pára e o JAVA tenta encontrar osprocedimentos para tratar esse erro. A esses procedimentos chama-seexception handler.

Um bloco try, é usado quando temos um bloco de código que poderáprovocar um erro.

Numa linguagem sem este tipo de mecanismos, quando se tenta prevenirerros, pode-se chegar a uma situação em que o código fica muito complexo, eaté podemos ter várias chamadas às mesmas funções tornando-se difícildistinguir o código do programa, do código usado para prevenir erros. Noentanto com este mecanismo podemos separar o código que nos interessa, docódigo usado para fazer o tratamento de erros. Repara que o código dentro dobloco try pode gerar o mesmo tipo de erro várias vezes, no entanto basta umexception handler para todos os erros do mesmo tipo.

No caso de haver um bloco de instruções que seja necessário corrersempre, quer ocorra um erro ou não, então esse bloco de instruções deverá serintroduzido dentro da instrução finally.

try {// código que pode gerar um erro

} catch(Type1 id1) { //exception handler// tratar um erro do tipo Type1

} catch(Type2 id2) { //exception handler// tratar um erro do tipo Type2

} catch(Type3 id3) { //exception handler// tratar um erro do tipo Type3

} finally {// código que tem de correr sempre

}

Como foi referido antes, o JAVA tem um processo chamado “garbagecollection”, que vai libertar memória, automaticamente. Numa linguagem quenão disponha de essa ferramenta, o bloco finally é utilizado para tratar essasituação. Então, qual a utilidade desta ferramenta? É útil, quando se querretornar um elemento ao seu estado original, por exemplo uma variável, umaligação à Internet, um desenho no ecrã ou até mesmo um interruptor, nomundo exterior.

6.11.11 throws - throwA instrução throw serve para dizer que um determinado método pode

lançar uma determinada exception.

float divisao(int a, int b) throws ArithmeticException {Object obj;if (b == 0) throw new ArithmeticException();return a/b;

}

6.11.12 Exercícios1) Faça um programa que escreva no ecrã “Olá mundo!”.

2) Faça um programa que leia um número e que indique qual oseguinte.

Prof. Herberto Graça Página 35 de 217

Page 36: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

3) Faça um programa que leia um número x e que calcule:

X2 + 2xX + 3

Apresente o resultado no ecrã da seguinte forma:

“O número lido foi o # e o resultado é & “

sendo que # e & são os valores lidos e o resultado daexpressão.

4) Faça um programa que leia dois números e calcule a respectivasoma, diferença (o primeiro menos o segundo), produto e quociente(o primeiro a dividir pelo segundo).

5) Faça um programa que leia dois números e calcule a respectivamédia.

6) Escreva um programa que calcule a raiz quadrada de um númerointroduzido pelo utilizador.

7) Escreva um programa que calcule o quadrado de um númerointroduzido pelo utilizador.

8) Escreva um programa que calcule a hipotenusa de um triângulorectângulo, cujos catetos são dados pelo utilizador.

9) Escreva um programa que introduzido um número pelo utilizador,calcula o seu arredondamento e apresenta o resultado no ecrã.

10) Escreva um programa que leia um número e apresente a tabela demultiplicação pelos números naturais de 1 a 10.

Ex: x = 55 x 1 = 55 x 2 = 105 x 3 = 155 x 4 = 20

11) Escreva um algoritmo que, após a leitura do nome, do ano, do anode nascimento, da turma e da nota de um aluno escreva em linhasseparadas:

a) O nome do aluno, a turma e o ano, separados por doisespaços;

b) A palavra MENOR se o aluno tiver menos de 18 anos ou MAIORem caso contrário;

c) A palavra REPROVADO se a nota for menor que 10 ouAPROVADO em caso contrário.

12) Escreva um algoritmo com a estrutura CASO... que leia um valorpara a variável OPERADOR e escreva o nome de uma das quatrooperações básicas, ou seja, se o operador for: 1 escreve ‘Adição’ ; 2escreve ‘Subtracção’ ; 3 escreve ‘Multiplicação’ ; 4 escreve ‘Divisão’.

Prof. Herberto Graça Página 36 de 217

Page 37: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

13) Escreva um programa que faça a conversão de notas quantitativaspara qualitativas usado a instrução CASO..., do seguinte modo:

0 a 4 = Muito Insuficiente

5 a 9 = Insuficiente

10 a 13 = Suficiente

14 a 17 = Bom

18 a 20 = Muito Bom

14) Escreva um programa que faça a conversão de notas quantitativaspara qualitativas usado a instrução SE..., do seguinte modo:

0 a 4 = Muito Insuficiente

5 a 9 = Insuficiente

10 a 13 = Suficiente

14 a 17 = Bom

18 a 20 = Muito Bom

15) Escreva um programa que calcule a soma dos primeiros 20números inteiros. Utilize a estrutura PARA....

16) Escreva um programa para o computador determinar se umdeterminado ano entre 1950 e 2050 é bissexto.

17) Escreva um programa para o computador calcular a média de umconjunto de números positivos. Um valor zero na entrada significaque se chegou ao fim da sequência de números positivos.

18) Escreva um programa para que seja lido um nome e, após a leitura,seja escrito 10 vezes.

19) Escreva um programa que leia 15 números reais e vá escrevendoPOSITIVO, NEGATIVO ou ZERO consoante o número lido seja positivo,negativo ou zero.

20) Escreva um programa que leia 20 números inteiros e determinequantos desses números são zero(0) .

21) Escreva um programa que leia 20 números reais e, utilizando ociclo ENQUANTO... FAZER, calcule a sua média.

22) Escreva um programa que resolva o seguinte problema:

“Sabendo que uma loja de doces está a fazer promoções deNatal em que para compras de valor superior a 100 € é oferecido 1Kg; para valores entre 70 e 100 € oferece ½ Kg de doces e paravalores inferiores nada é oferecido. O preço por quilo é de 10 €.Introduzindo a quantidade comprada terá de calcular o valorcomprado e mostrar o que ganhou nessa compra.”

23) Escreva um programa que determine se um número inteiro é parou ímpar.

Prof. Herberto Graça Página 37 de 217

Page 38: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

24) Escreva um programa que leia 25 números reais, calcule o dobro decada um deles e mostre o resultado no écran. Use a estruturaPARA....

25) Escreva um programa que leia um conjunto de 50 letras edetermine quantas dessas letras são ‘a’.

26) Faça um programa para ler e escrever 20 palavras.O algoritmo deve ser o seguinte:

ALGORITMO LeEscreveVARIÁVEIS

Nome : CADEIATotal : INTEIRO

INICIO

Total ← 0ENQUANTO Total<20 FACA

LEIA(Nome)ESCREVA (‘Nome=‘,

Nome)

Total ← Total + 1

FIM ENQUANTOFIM.

27) Crie um programa que calcule o factorial de um número.O algoritmo deve ser o seguinte:

VAR n, resultado: Inteiros;

INICIOEscrever(“Introduza um número”);Ler (N);

REPETIR

Resultado resultado * (N-1);N = n -1;

ATÉ QUE (N<=1)Escrever(“O resultado é:”, resultado);

FIM.

28) Utilizando um ciclo for, crie um programa que calcule um valor Aelevado a um expoente B. Os valores A e B deverão ser dados peloutilizador.

29) Dado dois valores A e B quaisquer, faça um algoritmo que imprimase A > B, ou A < B , ou A = B.

30) Faça um programa que dado um número inteiro retorne o mês aque este corresponde. Caso o número não corresponda a um mêsdeverá retornar “Esse mês não existe”.

6.12 Arrays

Os arrays são tabelas que se utiliza para guardar vários elementos domesmo tipo, que tem algum tipo de relação entre si.

De seguida, apresento alguns exemplos de como trabalhar com arrays, emJAVA.

Prof. Herberto Graça Página 38 de 217

Page 39: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6.12.1 Declaração de arrays

int[] anArray; // declaração de um array de inteiros

int[][] anArray; // declaração de um array de inteiros, // bidimensional

6.12.2 Criação de arrays

anArray = new int[10]; // criação de um array de 10 inteiros

int[] anArray = new int[10]; //declaração e criação de um array

anArray = new int[5][5]; // criação de um array bidimensional

Também é possível declarar um array bidimensional em que a segundadimensão é variável, no entanto será necessário criar cada array secundárioindividualmente.

anArray = new int[3][]; // criação de um array bidimensional com // a segunda dimensão indefinida

anArray[0] = new int[23]; // criação dos arrays secundários, cadaanArray[1] = new int[52]; // um com uma dimensão diferenteanArray[2] = new int[3]; //

6.12.3 Aceder ao conteúdo de arrays

for (int i = 0; i < anArray.length; i++) {anArray[i] = i; //faz uma atribuiçãoSystem.out.print(anArray[i] + " ");//devolve um conteúdo

}

for (int i = 0; i < anArray.length; i++) {// ciclo das linhasfor (int j = 0; j < anArray.length; j++) {// ciclo das colunas

anArray[i][j] = i+j; //faz uma atribuição//devolve um conteúdoSystem.out.print(anArray[i][j] + " ");

}System.out.println("");//muda de linha no final de cada linha

}

6.12.4 Exercícios1) Fazer um programa que permita ao utilizador introduzir 15 valores

e de seguida calcule o quadrado e a raiz quadrada dos valores.Apresente os resultados no écran.

Prof. Herberto Graça Página 39 de 217

Page 40: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

2) Fazer um programa que receba o gasto de cada mês num ano epermita ao utilizador consultar a despesa efectuada num dado mês.Este último processo deve ser repetido até o utilizador desejar. Nofinal do programa calcule a média das despesas desse ano.

3) Fazer um programa que permita a introdução de 5 pesos e deseguida indique qual o maior peso que foi introduzido e a posição dovector onde se encontra.

4) Uma determinada empresa vende 5 artigos, cada um com umdeterminado valor. Com a introdução do Euro, a empresa teve queactualizar os preços em escudos para euros. Apresente os preçosdos artigos em escudos e em euros. Faça um programa que resolvao problema acima especificado.

5) Elabore um programa que permita registar, para os seis primeirosmeses do ano, as receitas e as despesas da clínica Dóimaki, Lda. Nofinal, pretendemos saber os lucros ou prejuízos de cada mês (quedeverão ser registados num novo vector), e o total dos seis meses.

6) Faça um programa que:• Leia, via teclado, 20 valores do tipo inteiro e os guarde

num array. • Depois deverá emitir um relatório com:

◦ Todos os números pares que foram lidos◦ Qual o menor valor existente no array◦ Qual o maior valor existente no array◦ Os valores que são maiores que a média desses

valores.

7) Faça um programa que registe as vendas de 3 lojas em cada mêsdo 1º trimestre do ano. De seguida, o programa deve permitir aoutilizador consultar as vendas de uma determinada loja numdeterminado mês, enquanto o utilizador desejar.

8) Temos um armário com 4 prateleiras e 2 colunas de gavetas emcada prateleira. Pretende-se um programa que permita registar o nºde documentos existentes em cada gaveta. No final, deverá sercalculado o total de documentos em cada uma das colunas, o totalde documentos em cada uma das linhas e o total de documentospresentes no armário.

9) Pretendemos registar em cada um dos meses do ano, as receitas edespesas de um departamento de vendas. No final, apresente oslucros ou prejuízos de cada mês e do total do ano.

10) Num centro meteorológico, as temperaturas são medidas 2 vezespor dia. Faça um programa que permita registar as temperaturasocorridas ao longo dos 7 dias da semana, No final, apresente amédia de cada dia e a média da semana. Indique também o(s) diasque tiveram temperaturas acima da média semanal.

11) Pretende-se registar as notas de 3 alunos a 2 disciplinas. Oprograma deverá calcular a média das 2 disciplinas por aluno, assimcomo a média por disciplina.

Prof. Herberto Graça Página 40 de 217

Page 41: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

12) Desenvolve um programa que permita calcular a soma entre duasmatrizes quadradas (por exemplo, 3x3).

6.13 Vectores

A classe Vector é possivelmente uma das mais úteis da API do Java e,talvez uma das mais utilizadas. Um vector, de um modo simplista, é um arraydinâmico. Quer isto dizer que o tamanho deste não é fixo, podendo-seacrescentar ou remover posições com facilidade. No entanto, isto é umprocesso que poderá consumir muitos recursos do sistema se for utilizadoincorrectamente uma vez que, sempre que a estrutura é alterada, o que o Javafaz é criar uma nova estrutura com o tamanho desejado e copia os dados daanterior estrutura para a nova. O Vector apenas aceita como seus elementosObjectos, não podendo portanto guardar nele tipos primários de dados. Eis umexemplo de como utilizar a classe Vector:

O programa anterior teria como output o seguinte:

Prof. Herberto Graça Página 41 de 217

Page 42: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6.14 Linked List

A classe LinkedList é uma implementação da Interface List e, tal como onome indica é uma lista ligada, ou seja, é uma lista em que cada nó da mesmatem informação sobre qual é o nó seguinte e o nó anterior. Esta também é umaestrutura dinâmica. Em comparação com o Vector, tem uma performancesuperior a nível de inserção/remoção de elementos no início e fim da lista, masuma menor performance quando os elementos a remover/inserir são no meioda mesma.

Ilustração 12: Lista duplamente encadeada

6.15 HashMap

A classe HashMap implementa a interface Map e é, nada mais do que, arepresentação Java da estrutura de dados Hash Table. Esta estrutura servepara guardar pares <chave,valor>, sendo chave e valor do tipo definido peloprogramador. As chaves devem ser únicas e, dada uma chave conseguimosobter o seu valor correspondente.

Prof. Herberto Graça Página 42 de 217

Page 43: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Prof. Herberto Graça Página 43 de 217

Page 44: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

7 Programando com classes

7.1 Criar uma classe

A primeira coisa que se faz quando se começa a fazer um programa emJava, é criar uma classe, que irá usar objectos de outras classes, sejam estasdisponibilizadas pela API do JAVA, ou criadas pelo programador.

7.1.1 Declaração da classeNa declaração de uma classe, podemos definir determinadas

características da classe. Na tabela seguinte estão as palavras-chave quepodem ser usadas na declaração de uma classe, na ordem em que devem serutilizadas, bem como uma pequena descrição da sua utilidade.

Palavra-chave Descriçãopublic A classe é de acesso público

abstract Não podem ser criados objectos desta classe

final A classe não pode ter subclasses

class nomeDaClasse O nome da classe

extends A super classe da classe (a classe pai)

implements Interfaces Interfaces implementadas pela classe

Tabela 5: Palavras-chave da declaração de classes

Exemplo da declaração de uma classe:

public class HelloWorldApp {//código…

}

7.1.2 O construtorO construtor de uma classe é a 1ª “função” que vai ser executada quando

um objecto é criado. Então é aqui que se vão fazer as inicializações dasvariáveis de instância e se vão executar todos os métodos que é necessáriocorrer quando se cria um objecto.

Características de um construtor:

• Não tem retorno.

• Não é obrigatório, uma classe possuir um construtor, mas pode termais do que um.

• Tem de ter o mesmo nome da classe.

Exemplo da declaração de uma classe com um construtor:

Prof. Herberto Graça Página 44 de 217

Page 45: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

public class Stack {

public Stack(){items=new Vector(10);

}

}

7.1.3 Declaração de membrosSão chamados membros de uma classe a todas as variáveis e todos os

métodos dessa classe.

Na declaração de um membro, podemos definir determinadascaracterísticas de esse membro. Na tabela seguinte estão as palavras-chaveque podem ser usadas na declaração de uma classe, na ordem em que devemser utilizadas, bem como uma pequena descrição do seu significado.

Palavra-chave Descriçãonível de acesso Indica o nível de acesso a um membro

static Declara um membro de classe

final Indica que é constante

transient Marca as variáveis membro que não devemser serializadas

volatile Evita que o compilador faça determinadasoptimizações ás variáveis membro

“tipo” nomeDaVarivel O tipo e o nome de uma variável

Tabela 6: Palavras-chave da declaração de membros

A tabela seguinte especifica os vários níveis de acesso que é possívelatribuir a um membro de uma classe:

Nível A própia Classe Classes nomesmo Pacote

Subclasse forado pacote

Qualquerclasse,

qualquerpacote

private x<sem modificador> x x

protected x x x2

public x x x x

Tabela 7: Níveis de acesso possíveis de atribuir a um membro

Mais informação: http://www.powerbot.org/vb/showthread.php?t=573108&page=1

2 O acesso só é permitido aos membros que são herdados pela subclasse, não aos membros de objectos da classemãe. Ver exemplo em: http://www.uni-bonn.de/~manfear/javaprotection.php#subyes

Prof. Herberto Graça Página 45 de 217

Page 46: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Exemplo da declaração de uma classe, um construtor, uma variável e ummétodo:

public class Stack {

// Variável de instânciaprivate Vector items;

// Construtorpublic Stack(){

items=new Vector(10);}

// Método

public Object push(Object item){items.addElement(item);return item;

}}

- Nível de acesso.

- Tipo de retorno.

- Nome.

- Parâmetros.

7.1.4 O mainO main é onde vamos escrever o nosso programa. Quando mandarmos o

nosso programa correr, ele vai executar o código presente neste bloco.

Exemplo da declaração de uma classe com o main:

public class HelloWorld {

public static void main(String[] args) {//código do programa

}

}

7.1.5 O primeiro programaAgora que já sabemos como criar uma classe, declarar os membros e o

main, vamos então construir o nosso primeiro programa, que como não podiadeixar de ser é o inevitável “Hello World!”:

/** * A classe HelloWorldApp implementa uma aplicação que * imprime "Hello World!" para o “standard output”. */public class HelloWorld {

public static void main(String[] args) {//Imprime "Hello World!"System.out.println("Hello World!");

}}

7.1.6 Convenções de programaçãoAs convenções de programação são regras, não mandatórias, que devem

ser seguidas por todos os programadores. Estas convenções são muitoimportantes, pelas seguintes razões:

• 80% do custo de um software, ao longo da sua vida, vai para a suamanutenção;

Prof. Herberto Graça Página 46 de 217

Page 47: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• A manutenção de código raramente é realizada pelo seu criador, aolongo de toda a sua vida;

• Levam uma melhor legibilidade do código criado, permitindo que osprogramadores que não o criaram, compreendam o código melhor emais rapidamente.

As convenções de programação JAVA podem ser consultadas num dosanexos deste manual, ou no endereço:

• http://www.oracle.com/technetwork/java/codeconv-138413.html

7.1.7 Exercícios1) Considera a seguinte classe:

public class IdentifyMyParts {public static int x = 7; public int y = 3;

}

a) Identifica as variáveis de classe, da classe.

b) Identifica as variáveis de instância, da classe.

2) Cria um pequeno programa que imprima uma frase, no ecrã, adizer se o valor de uma variável é maior ou menor que 50. Deveráscriar uma função que diga se um valor é menor que cinquenta.

3) Cria um pequeno programa que imprima, no ecrã, o nome de ummês, conforme o valor de uma variável. Caso o valor da variável seja>12 ou <1, deverá imprimir uma mensagem de erro.

4) Cria um pequeno programa que:

a) Pede 10 valores inteiros, que coloca dentro de um array.

b) Calcula o maior valor do array.

c) Calcula o menor valor do array.

d) Calcula a média dos valores do array.

7.2 Utilizar objectos

Apesar de já podermos fazer programas básicos, inevitavelmente, nãopodemos fazer grande coisa sem utilizarmos objectos. Afinal, estamos a falarde Programação Orientada por Objectos!

7.2.1 Criar um objectoA criação de um objecto é muito semelhante à criação de uma variável

normal, e é composta por três partes fundamentais:

1. Declaração: A declaração de um objecto, tal como a declaração deuma variável normal, tem a função de associar um nome de umavariável a um tipo. Na declaração de uma variável, não é necessário

Prof. Herberto Graça Página 47 de 217

Page 48: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

fazer a atribuição de um valor a essa variável, no entanto, isso podeser feito.

2. Instanciação: A instanciação de um objecto é a parte em que secria o objecto, fazendo a ligação desse objecto ao nome de umavariável. Esta instanciação é feita através do operador new.

3. Inicialização: O operador new é seguido da chamada a umconstrutor de uma classe, que vai fazer a inicialização do novoobjecto.

Ex:

public class Teste_1 {Rectangle rectangulo = new Rectangle(50, 100);

}

Declaração Instanciação Inicialização

7.2.2 Utilizar um objectoComo já vimos, um objecto tem dois tipos de membros, as variáveis e os

métodos. Pode-se dizer que a utilização de um objecto se resume ao acesso eutilização dos seus membros.

Ex:

public class Teste_1 {

static Rectangle rect = new Rectangle(50, 100);static double altura=rect.getHeight();

public static void main(String[] args) {System.out.println( altura );System.out.println( rect.x );

}}

- Declaração de uma variável membro de classe.

- Acesso a um método membro, do objecto “rect”.

- Acesso a uma variável estática num contexto estático.

- Acesso a uma variável membro, do objecto “rect”.

Prof. Herberto Graça Página 48 de 217

Page 49: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

7.2.3 Exercícios1) Considera a seguinte classe:

public class IdentifyMyParts {public static int x = 7; public int y = 3;

}

a) Qual é o output do código seguinte:

IdentifyMyParts a = new IdentifyMyParts();IdentifyMyParts b = new IdentifyMyParts();a.y = 5;b.y = 6;a.x = 1;b.x = 2;System.out.println("a.y = " + a.y);System.out.println("b.y = " + b.y);System.out.println("a.x = " + a.x);System.out.println("b.x = " + b.x);

2) Constrói uma classe, cujas instâncias representem uma carta deum baralho de cartas.

3) Constrói uma classe, cujas instâncias representem um baralho decartas.

4) Escreve um programa que crie um baralho de cartas, as baralhe eas mostre no ecrã.

5) Constrói uma classe, cujas instâncias representem um baralho decartas muito genérico.

a) Constrói uma subclasse da classe que criaste, e querepresente um baralho de cartas normais (baralho latino).

b) Constrói uma subclasse da classe que criaste, e querepresente um baralho de cartas de UNO.

O baralho de UNO tem 108 cartas:

19 azuis - 0 + (1 a 9) x2

19 verdes - 0 + (1 a 9) x2

19 vermelhas - 0 + (1 a 9) x2

19 amarelas - 0 + (1 a 9) x2

8 cartas +2 - 2 em cada cor

8 cartas de inverter - 2 em cada cor

8 cartas de passe - 2 em cada cor

4 cartas de mudança de cor

4 cartas de mudança de cor e +4

Prof. Herberto Graça Página 49 de 217

Page 50: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

c) Constrói uma subclasse da classe que criaste, e querepresente um baralho de cartas de tarôt.

O baralho de tarô de 78 cartas contém:

14 cartas cada um dos quatro naipes: 10 cartasnumeradas de um (ou ás) a dez, mais as figuras, que no jogode tarô são quatro: Rei, Dama, Cavaleiro e Valete;

21 trunfos, conhecidos no tarô esotérico como arcanosmaiores, cuja função no jogo é um naipe permanente detrunfos;

1 carta sem número chamada Curinga, ou o Louco dosbaralhos esotéricos, conhecido nos jogos de tarô como aDesculpa, chamada assim porque o jogador pode usá-la como"desculpa" para não seguir o naipe regente da vaza — mas àsvezes atua como o trunfo mais forte.

Os Arcanos maiores possuem 22 símbolos arquetípicosque revelam os estados latentes das idéias e possibilidadesda vida, a saber:

1. O Mago

2. A Sacerdotisa - A Papisa

3. A Imperatriz

4. O Imperador

5. O Hierofante - O Papa

6. Os Enamorados

7. O Carro

8. A Justiça

9. O Eremita

10. A Roda da Fortuna

11. A Força

12. O Enforcado

13. A Morte (o arcano sem

nome)

14. A Temperança

15. O Diabo

16. A Torre

17. A Estrela

18. A Lua

19. O Sol

20. O Julgamento

21. O Mundo

22. O Louco (o arcano sem

número)

Os Arcanos menores que expressam os resultados e asformas das idéias, contidos no primeiro conjunto, possui 56arcanos distribuídos por quatro símbolos básicos: o Naipe deOuros, o Naipe de Espadas, o Naipe de Copas e o Naipe dePaus. Por sua vez, cada naipe, possui dez arcanos numeradose quatro arcanos com figuras da corte medieval (Valete,Cavaleiro, Rainha, Rei).

d) Baseando-nos numa aplicação exemplificativa do MS Access,

Prof. Herberto Graça Página 50 de 217

Page 51: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

vamos criar a sua correspondente em JAVA. Cria um novoprojecto chamado “Adamastor”, e dentro desse projecto, umpacote chamado “CLI”. Construa um CLI para o projectoAdamastor, com as seguintes características:

• Menu principal com 6 opções:

• Ver uma listagem das categorias de produtos,cada uma delas com:

• Nome da categoria;• Descrição;• Listagem de produtos dessa categoria;

• Ver uma listagem dos fornecedores, cada umdeles com:

Código do Fornecedor, Nome da Empresa,Nome do Contacto, Cargo, Endereço,Cidade, Região, Código Postal, País,Telefone, Fax, Home Page

• Para cada fornecedor, ter a opção para:• Ver os seus produtos;• Acrescentar um produto à sua lista;

• Ver uma listagem dos produtos, cada um delescom:

Código do Produto, Nome do Produto,Fornecedor, Categoria, Quantidade PorUnidade, Preço Unitário, Existências,Unidades Encomendadas, ExistênciaMínima, Descontinuado

• Ver uma listagem das encomendas, cada umadelas com:

Nome do cliente, morada do cliente, nomedo vendedor, nome da empresa de envio,código da encomenda, data de encomenda,data requerida, data de envio, subtotal daencomenda, frete e preço total daencomenda (subtotal + frete)

• listagem de produtos na encomenda, com:produto, preço unitário, quantidade,desconto e preço total de cada produto

• Para cada encomenda, ter a opção paraimprimir a factura;

• Imprimir relatórios de vendas, com as seguintesopções:

• Vendas dos empregados, por país;• Totais de vendas por valor;• Vendas por categoria de produto, sendo

possível escolher qual a categoria que sepretende ver;

• Sair do programa.

Prof. Herberto Graça Página 51 de 217

Page 52: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

8 As classes essenciais

8.1 Tratamento de erros

Como foi dito anteriormente, existem dois modos para fazer o tratamentode erros, utilizando uma estrutura “try-catch-finally” ou o comando “throws”.

Suponhamos que temos uma classe cujos objectos contem um vector de10 inteiros que estão guardados de forma sequencial de 0 a 9. Esta classetambém define um método chamado “writeList” que escreve o conteúdo dovector para um ficheiro chamado “OutFile.txt”.

import java.io.*;import java.util.Vector;

public class ListOfNumbers {private Vector victor;private static final int size = 10;

public ListOfNumbers () {victor = new Vector(size);for (int i = 0; i < size; i++)

victor.addElement(new Integer(i));}public void writeList() {

PrintWriter out=null;

out = new PrintWriter(new FileWriter("OutFile.txt"));for (int i = 0; i < size; i++)

out.println("Value at: " + i + " = " + victor.elementAt(i));

out.close();}

}

Como podemos ver no código acima, a primeira acção do método“writelist” é abrir o ficheiro para escrita e criar uma stream que vai enviar osdados para o ficheiro.

PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));

Parece estar tudo bem, mas, o que acontece se não for possível abrir oficheiro?! ERRO!

Teremos então de fazer o tratamento deste erro, podemos, por exemplo,fazer o programa sair imediatamente, ou criar aquele ficheiro. O compilador deJAVA, nem sequer vai aceitar o código, tal como está neste momento, e por issodiz-se que esta é uma “checked exception”, ou erro de compilação.

Para além desta fonte de possíveis erros, que é detectada ao se tentarcompilar o nosso programa, existe ainda outro problema. Enquanto se percorreo vector, pode acontecer que se exceda o número de campos do vector.

out.println("Value at: " + i + " = " + victor.elementAt(i));

Este tipo de erros não são detectados no momento da compilação, apenas

Prof. Herberto Graça Página 52 de 217

Page 53: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

no momento em que se corre o programa, por isso são chamados “runtimeexception”. Estes erros, geralmente não são tratados, confiando-se que ocódigo do programador não cometa este tipo de erros. Além disso, códigocomo o descrito antes acontece com muita frequência, portanto o seutratamento teria elevados custos de performance.

Apesar dos erros descritos acima serem de origens diferentes, podem sertratados da mesma forma. De seguida veremos os dois modos possíveis paraos tratar.

8.1.1 Tratamento com “try-catch-finally”Como foi descrito no cap. 4.2.6.10, a sintaxe deste bloco é a seguinte:

try {// código que pode gerar um erro

} catch(Type1 id1) { //exception handler// tratar um erro do tipo Type1

} catch(Type2 id2) { //exception handler// tratar um erro do tipo Type2

} catch(Type3 id3) { //exception handler// tratar um erro do tipo Type3

} finally {// código que tem de correr sempre

}

Então, para tratar os erros descritos antes, vamos colocar o código que éum potencial gerador de erros, dentro do bloco “try”:

try {out = new PrintWriter(new FileWriter("OutFile.txt"));for (int i = 0; i < size; i++)

out.println("Value at: " + i + " = " + victor.elementAt(i));}

Mas isto não é suficiente, um bloco “try” deve ser sempre seguido por umbloco “catch” ou “finally”:

try {out = new PrintWriter(new FileWriter("OutFile.txt"));for (int i = 0; i < size; i++)

out.println("Value at: " + i + " = " + victor.elementAt(i));} catch (Exception e) {

e.printStackTrace();// Imprime a pilha de execução}

No código acima, o que acontece é que, se irá tentar correr o bloco “try”.Qualquer erro que ocorra, irá interromper a normal execução do código epassará a ser executado o código do bloco “catch” respectivo. Uma vez que aclasse “Exception” é a classe superior, na hierarquia das classes queidentificam exceptions, todos os erros levarão à execução deste bloco decódigo. No entanto, nós temos dois tipos diferentes de erros no nosso código e,provavelmente, queremos resolver cada erro de um modo diferente. Então onosso código passará a ser algo do tipo:

Prof. Herberto Graça Página 53 de 217

Page 54: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

try {out = new PrintWriter(new FileWriter("OutFile.txt"));for (int i = 0; i < size; i++)

out.println("Value at: " + i + " = " + victor.elementAt(i));} catch (ArrayIndexOutOfBoundsException e) {

System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage());} catch (IOException e) {

System.err.println("Caught IOException: " + e.getMessage());}

Mas ainda não acaba aqui. Para além de detectarmos e tratarmos os erros,queremos ter a certeza que, se ocorrer um erro, ao terminar o tratamento doerro, o contexto em que nos encontramos será sempre o mesmo. Se deixarmoso código como no exemplo anterior, nunca poderemos assegurar que a streamserá fechada. Portanto teremos de utilizar a cláusula “finally”:

public void writeList() {PrintWriter out=null;

try {out = new PrintWriter(new FileWriter("OutFile.txt"));for (int i = 0; i < size; i++)

out.println("Value at: " + i + " = " + victor.elementAt(i));} catch (ArrayIndexOutOfBoundsException e) {

System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage());} catch (IOException e) {

System.err.println("Caught IOException: " + e.getMessage());}finally {

if (out != null) {System.out.println("Closing PrintWriter");out.close();

} else {System.out.println("PrintWriter not open");

}}

}

Claro que poderíamos incluir “out.close();” em todos os blocos “catch”,mas isso seria uma repetição de código desnecessária e perfeitamentehorrível, caso tivéssemos, por exemplo, 5 “catch” e 15 linhas de código pararepetir.

Prof. Herberto Graça Página 54 de 217

Page 55: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

8.1.2 Tratamento com “throw”Suponhamos que a classe desenvolvida anteriormente iria ser utilizada por

outros programadores, noutros programas. Então, nesse caso, talvez seja maisconveniente deixar o tratamento dos erros ficar ao critério de esses outrosprogramadores. Como fazer isso sem que seja necessário estar a alterar ocódigo da nossa classe?! Podemos retornar um aviso de que ocorreu um erro,ou seja, podemos lançar uma excepção.

public void writeList() throws ArrayIndexOutOfBoundsException,IOException{PrintWriter out=null;

out = new PrintWriter(new FileWriter("OutFile.txt"));for (int i = 0; i < size; i++)

out.println("Value at: " + i + " = " + victor.elementAt(i));

out.close();}

Neste caso não é necessário criar e lançar uma exeption porque ela écriada e lançada para este método pelo objecto “PrintWriter”. No caso seguinteé necessário criar e lançar a exception, uma vez que esta não nos é lançadapor nenhum outro objecto.

float divisao(int a, int b) throws ArithmeticException {Object obj;

if (b == 0) throw new ArithmeticException();

return a/b;}

8.1.3 Criar a tua própria ExceptionApesar de a API do JAVA disponibilizar bastantes tipos de exceptions, mais

tarde ou mais cedo vais encontrar situações em que não vais ter uma quesatisfaça as tuas necessidades. Nessa altura, terás de criar a tua própriaException fazendo-a uma subclasse da classe “Exception”.

Por convenção, o nome das exceptions deve ser sempre terminado por“Exception”.

Prof. Herberto Graça Página 55 de 217

Page 56: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

8.1.4 Exercícios1) Considerando as seguintes classes, detecta as possíveis fontes de

erro e altera o código de modo a que, caso ocorra um erro, sejaexibida uma mensagem de erro e o programa termine a execução:

public class Ex61411 {public static void main(String[] args) throws IOException {

if (args.length == 0) {System.out.println("A sintaxe é: Ex61411.jar <ficheiro>");return;

}FileInputStream in=null;in = new FileInputStream(args[0]);int ch;while ((ch = in.read()) != -1) {

System.out.print((char) ch);}System.out.println();in.close();

}}

public class Ex61412 {public static void main(String[] args)throws IOException {

if (args.length == 0) {System.out.println("A sintaxe é: Ex61412.jar <ficheiro>");return;

}

FileInputStream fin;fin = new FileInputStream(args[0]);DataInputStream din = new DataInputStream(fin);int i;for (;;) {

i = din.readInt();System.out.println(i);

}fin.close();

}}

2) Constrói um programa que leia o conteúdo de um ficheiro eimprima, no ecrã, as suas palavras em ordem inversa. A estrutura doprograma deve ser a seguinte:

a) Verificar os parâmetros de entrada.

b) Criar uma stream de leitura do ficheiro. (FileInputStream)

c) Ler o ficheiro para dentro de um buffer. (StringBuffer)

d) Separar o conteúdo por palavras. (StringTokenizer)

e) Inverter a ordem das palavras. (Stack)

f) Imprimir no ecrã.

3) Cria um novo tipo de exception chamado “MyException”, e umaclasse, chamada “TestException”, com um método, chamado“doException()”, que lance essa exception. Faz um programa quecrie um objecto do tipo “TestException” e chame o método“doException()”. A classe “MyException” deverá ter um construtor

Prof. Herberto Graça Página 56 de 217

Page 57: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

que aceite uma mensagem. Quando criares a classe “MyException”,declara-a como subclasse de “Exception”. Deste modo podesaproveitar uma pequena ajuda do Eclipse.

8.2 Threads

Uma thread pode ser definida como um bloco de instruções sequenciais deum programa.

Até agora os nossos programas tinham sempre apenas uma sequência deinstruções, mas com as threads podemos ter várias sequências de instruções aserem executadas “simultaneamente”, uma sequência em cada thread.

Thread A: Um bloco de instruções, porex., o código principal de um programa.

Thread B: Outro bloco de instruções, porex., um conjunto de instruções que faz oprograma ficar a espera de uma ligação deoutro, via Internet.

Ilustração 13: Exemplo de funcionamento de threads

No exemplo descrito acima, é possível colocar os dois blocos de instruçõesna mesma thread, no entanto, se o programa for feito desse modo, então oprograma irá ficar bloqueado até receber uma ligação de outro computador.Mas se a aplicação for construída utilizando duas threads distintas, então,enquanto um thread espera uma ligação, a outra (o programa principal) podecontinuar a funcionar normalmente, executando outras tarefas.

Existem dois modos para criar threads, criando uma subclasse da classeThread e implementando uma interface Runnable.

8.2.1 Criar uma subclasse de ThreadAo criarmos uma subclasse da classe Thread, existem dois métodos que

teremos de criar.

O primeiro método a ter em conta, é o construtor, que, geralmente, temcomo único parâmetro de entrada uma string e é utilizado apenas para dar umnome à thread.

O segundo método a criar é o método “run()”, que é onde vamos colocar ocódigo que queremos que seja executado. Seguidamente temos um exemplodeste modo de criar uma thread.

public class SimpleThread extends Thread {

public SimpleThread(String str) {super(str);

}

public void run() {for (int i = 0; i < 10; i++) {

System.out.println(i + " " + getName());try {

sleep((long)(Math.random() * 1000));

Prof. Herberto Graça Página 57 de 217

Page 58: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

} catch (InterruptedException e) {}

}System.out.println("DONE! " + getName());

}}

public class TwoThreadsDemo {public static void main (String[] args) {

new SimpleThread("Jamaica").start();new SimpleThread("Fiji").start();

}}

A classe “SimpleThread” apresentada acima, vai imprimir no ecrã o nomeda thread, 10 vezes, separado por um intervalo de tempo aleatório. Quandochega ao fim, imprime “Done!”.

A classe “TwoThreadsDemo” cria duas threads do mesmo tipo, mas comnomes diferentes, e dá início imediato à sua execução.

Como resultado, temos um programa a executar dois blocos de códigosimultaneamente.

8.2.2 Implementar a interface Runnable Como já vimos antes, implementar uma interface significa implementar

alguns métodos na nossa classe.

Deste modo, e tal como consta na especificação desta interface nadocumentação da API, a interface Runnable requer que nós implementemosapenas o método “run()”.

Então, implementando o exemplo descrito no sub capítulo anterior,utilizando este novo modo, iremos ter o seguinte código:

public class SimpleThread2 implements Runnable {String nome="";public SimpleThread2(String str) {

nome = str;}public void run() {

for (int i = 0; i < 10; i++) {System.out.println(i + " " + nome);try {

Thread.sleep((long)(Math.random() * 1000));} catch (InterruptedException e) {}

}System.out.println("DONE! " + nome);

}}

public class TwoThreadsDemo2 {public static void main (String[] args) {

new Thread(new SimpleThread2("Jamaica")).start();new Thread(new SimpleThread2("Figi")).start();

}}

8.2.3 Comunicação entre threads Uma thread é utilizada para correr código que vai executar uma

Prof. Herberto Graça Página 58 de 217

Page 59: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

determinada tarefa. Na vasta maioria dos casos, é necessário retornar umqualquer dado, nem que seja apenas para dizer que a operação foi concluídacom sucesso. É necessário, então, haver um modo para fazer a comunicaçãoentre duas threads.

Esta comunicação é feita através daquilo a que se chama um “tampão”,que não é mais do que uma variável comum ás duas threads. A classe destenosso tampão, deve consistir de uma variável onde se irá guardar ainformação, um método para colocar a informação nessa variável e um métodopara retirar a informação dessa variável.

Suponhamos que temos uma classe que produz números de 0 a 9ordenadamente, separados por um intervalo de tempo aleatório, e uma outraclasse que deverá receber esses números e imprimi-los no ecrã.

Ora, teremos de criar uma classe tampão para receber os números doobjecto produtor e entrega-los ao objecto consumidor.

Então poderemos usar uma classe como a seguinte:

public class CubbyHole {private int contents;

public synchronized int get() {return contents;

}

public synchronized void put(int value) {contents = value;

}

}

No entanto esta classe deixa-nos com alguns problemas:

• O consumidor não sabe quando deve ir buscar o número

• O produtor não sabe se já pode colocar outro valor, substituindo oanterior

Então, em primeiro lugar devemos criar uma variável boleana que nosdiga se o tampão contém alguma informação ou não:

public class CubbyHole {private int contents;private boolean available = false;

public synchronized int get() {if (available){

available = false;return contents;

}}

public synchronized void put(int value) {if (!available){

contents = value;available = true;

}}

}

Assim, já só é retirado um elemento quanto este existe no tampão, e só éinserido um novo elemento quando o tampão está vazio. Porém, o queacontece quando se quer inserir um novo elemento e tal não nos é permitido?!

Prof. Herberto Graça Página 59 de 217

Page 60: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

E quando se quer retirar um elemento e não existe nenhum para retirar?! Naprimeira situação, interessa-nos esperar que nos seja possível inserir umelemento, e no segundo caso interessa-nos esperar que haja um elemento pararetirar.

Vejamos agora, a classe tampão, finalmente terminada:

public class CubbyHole {private int contents;private boolean available = false;

public synchronized int get() {while (available == false) {

try {wait();

} catch (InterruptedException e) { }}available = false;notifyAll();return contents;

}

public synchronized void put(int value) {while (available == true) {

try {wait();

} catch (InterruptedException e) { }}contents = value;available = true;notifyAll();

}

}

8.2.4 Exercícios1) Considerando o exemplo descrito no capítulo 6.4.3, cria as classes

“Producer” e ”Consumer”, como subclasses da classe Thread, bemcomo o programa principal.

2) Altera as classes “Producer” e ”Consumer”, desenvolvidas noexercício anterior, de modo a serem classes normais queimplementam a interface Runnable.

3) Cria um programa que utilize uma thread para pedir uma frase aoutilizador, e outra thread para imprimir essa frase no ecrã.

8.3 Input/Output

8.3.1 Streams Para receber ou enviar informação de/para um ficheiro, memória ou um

socket, um programa cria uma stream utilizando-a para ler ou escrever dados,de forma sequencial.

De qualquer modo, independentemente de/para onde um programalê/escreve dados, o algoritmo para fazer isso é sempre o mesmo, uma vez quese trabalha com streams.

Prof. Herberto Graça Página 60 de 217

Page 61: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Ler Escreverabrir uma stream

enquanto (há dados)

lê dados

fechar a stream

abrir uma stream

enquanto (há dados)

escreve dados

fechar a stream

Ilustração 14: Pseudocódigo de utilização de streams de leitura e escrita

Existem dois tipos de streams, uma para trabalhar com caracteres e outrapara trabalhar com bytes.

8.3.1.1 Streams de caracteres

As super classes abstractas destas streams são as classes “Reader” e”Writer”. As subclasses destas classes principais, são classes especializadasque se dividem em dois tipos, as que apenas fazem o transporte de dados (emcinzento) e as que fazem algum tipo de processamento (em branco).

A maioria dos programas devem utilizar este tipo de streams paratrabalhar com caracteres, uma vez que estas podem trabalhar com quaisquercaracteres, enquanto as streams de bytes apenas podem trabalhar comcaracteres do tipo ISO-Latin-1 8-bit bytes.

Prof. Herberto Graça Página 61 de 217

Ilustração 15: Árvores de classes das streams decaracteres

Page 62: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

8.3.1.2 Streams de bytes

As super classes abstractas destas streams são as classes “InputStream” e” OutputStream”. As subclasses destas classes principais, são classesespecializadas que se dividem em dois tipos, as que apenas fazem o transportede dados (em cinzento) e as que fazem algum tipo de processamento (embranco). As streams de bytes devem ser usadas para transportar dadosbinários, como, por exemplo, imagens ou ficheiros de som.

8.3.1.3 Como utilizar streams

As streams mais utilizadas e fáceis de compreender serão, porventura, asstreams que lêem e escrevem ficheiros:

import java.io.*;public class Copy { public static void main(String[] args) throws IOException { File inputFile = new File("fich_entrada.txt"); File outputFile = new File("fich_saida.txt");

FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c;

while ((c = in.read()) != -1) out.write(c);

in.close(); out.close(); }}

O programa anterior utiliza as streams “FileReader” e “FileWriter” para lere escrever um ficheiro de texto. Ele começa por criar um objecto do tipo “File”,utilizando-o depois para criar a stream correspondente. A partir daí, enquantoexistem caracteres para ler, ele lê de uma stream e escreve na outra stream.No final, resta fechar as duas streams.

Prof. Herberto Graça Página 62 de 217

Ilustração 16: Árvores de classes das streams de bytes

Page 63: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

8.3.2 Serialização Entende-se por serialização de objectos, a escrita de um objecto de modo

a que ele possa, mais tarde, ser recuperado e reconstruído, exactamente nomesmo estado em que se encontrava quando foi serializado.

Um exemplo de um objecto serializado, pode ser uma folha de Excelgravada em disco, ou um ficheiro “.doc”. Numa aplicação, por exemplo, umaagenda em que guardamos as tarefas, agendadas, num array quandopretendermos sair da aplicação iremos com certeza desejar rever as tarefasagendadas, mais tarde. Ora o lógico será guardar esse array num ficheiro emdisco, sendo então necessário criar métodos para gravar e ler o array, numdeterminado formato. É precisamente aí que entra a serialização de objectos,tornando mais fácil o processo descrito antes.

Outra forma de utilizar a serialização de objectos é na comunicação entreprogramas, através de sockets.

A serialização de objectos é feita através de streams, nomeadamente“ObjectInputStream” e “ObjectOutputStream”, no entanto, para um objecto serserializável é necessário que implemente a interface “Serializable”.

O código seguinte faz a serialização de um objecto “String”, para o ficheiro“serial.txt”. Como podes ver, é utilizada uma stream “ObjectOutputStream”, eo método “writeObject”, dessa stream. Esta stream funciona com um buffer, oque quer dizer que, não vai escrever no ficheiro, cada vez que o método“writeObject” é chamado. Por este motivo, no final é utilizado o método “flush”,que vai, finalmente, escrever todos os conteúdos do buffer no ficheiro.

public static void main(String[] args) throws IOException{FileOutputStream out = new FileOutputStream("serial.txt");ObjectOutputStream s = new ObjectOutputStream(out);s.writeObject("Blablabla!");s.flush();

}

Como foi dito antes, para um objecto poder ser serializado, é necessárioque implemente a interface “Serializable”, no entanto não existe qualquerdificuldade em fazer isso uma vez que esta interface é uma interface vazia, istoé, não requer que algum método seja implementado, sendo apenas necessáriodeclarar a nossa classe, como “Serializable”, como ilustra o exemplo seguinte:

public class UmaClasse implements Serializable {//...

}

8.3.3 Exercícios1) Cria um programa que faça a cópia de uma imagem, para a mesma

directoria.

2) Cria um programa que faça a cópia de um ficheiro de texto, para amesma directoria.

3) Faz um programa que crie um ficheiro chamado “olamundo.txt” eescreva lá dentro “Olá mundo!”.

Prof. Herberto Graça Página 63 de 217

Page 64: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

4) Faz um programa que peça o nome e a idade do utilizador eescreva esses dados num ficheiro chamado “ex_6_3_3_4.txt”.

5) Faz um programa que, dados os catetos de um triangulorectângulo, calcule a sua hipotenusa. Os dados devem ser lidos eescritos no ecrã.

6) Altera o programa anterior, de modo a que os catetos devem serlidos do ficheiro “catetos.txt”.

7) Altera o programa anterior de modo a que o utilizador possaescolher se quer introduzir os valores dos catetos ou se estes devemser lidos do ficheiro.

8) Altera o programa anterior de modo a que a hipotenusa sejaguardada no ficheiro “hipotenusa.txt” e mostrada no ecrã.

9) Faça um programa que leia um ficheiro de texto, e escreva os seusconteúdos no ecrã. De seguida o deverá guardar esses conteúdosnoutro ficheiro de texto, mas em ordem inversa, carácter a carácter.

10) Faça um programa que, dado um ficheiro de texto, procure umadeterminada palavra (dada pelo utilizador) e troque todas as suasocorrências por outra palavra (dada pelo utilizador).

11) Faça um programa que, dado um ficheiro qualquer (dado peloutilizador), altere o seu nome para outro nome (dado pelo utilizador).

12) Cria um programa que:1. imprime uma string no ecrã2. serializa a string num ficheiro3. lê o objecto serializado4. imprime o objecto lido, no ecrã

13) Altera o programa anterior, de modo a serializar uma string e umobjecto do tipo “Date”, para o mesmo ficheiro, e a ler esses doisobjectos.

Prof. Herberto Graça Página 64 de 217

Page 65: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

9 Applets

9.1 O que é uma applet

Uma applet é um pequeno programa em JAVA, que pode ser embebidonuma página HTML. As applets diferem de um programa normal de JAVA, emque não lhes é permitido o acesso a determinados recursos do computadorlocal como sejam ficheiros e periféricos, nem lhes é permitido comunicar comoutros computadores na mesma rede, exceptuando o computador de onde foienviada a applet.

As applets são implementadas como sendo uma subclasse da classe“Applet”, tal como ilustra a seguinte hierarquia de classes:

Ilustração 17: Arvore declasses da classe Applet

Então, podemos concluir que uma applet não é mais do que uma instânciada classe “Applet”, que é uma classe com apenas algumas diferenças de umaclasse normal.

9.2 Como funciona uma applet

Uma applet tem apenas quatro estados:

• Pode estar a inicializar

• Pode estar a correr

• Pode estar parado

• Pode estar a libertar recursos

A classe “Simple” é uma classe que implementa todos os métodosherdados da classe “Applet”, no entanto, não é obrigatório que tal aconteça,podendo até haver uma applet que não implemente nenhum deles,

Prof. Herberto Graça Página 65 de 217

Page 66: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

desenhando apenas um quadrado no ecrã.

public class Simple extends Applet {/*. . .*/public void init() { /*. . .*/ }public void start() { /*. . .*/ }public void stop() { /*. . .*/ }public void destroy() { /*. . .*/ }/*. . .*/

}

Os métodos herdados da classe “Applet”, são executadosautomaticamente pela ordem “init”, ”start”, ”stop”, ”destroy”, sendo que nãose deve utilizar o construtor para uma applet, uma vez que algumas dasfuncionalidades das applets não funcionam no construtor, devendo-se utilizar ométodo “init” para esse efeito.

Métodos específicos daclasse

“Applet”Função do método

init

Inicializa uma applet, cada vez que é carregada. Éútil para uma rápida inicialização de variáveis egeralmente deve ser utilizada em substituição doconstrutor.

startComeça a execução da applet, cada vez que esta é

carregada. Quando uma applet faz algo após serinicializada, ela fá-lo neste método.

stop

Pára a execução da applet, cada vez que outilizador sai da página onde esta a applet ou fechao browser. A maioria das applets que implementam ométodo “start” também necessitam implementar ométodo “stop”, de modo a parar a execução da appletquando o utilizador não a tem activa, por exemplo,quando o browser é minimizado.

destroy

Liberta os recursos ocupados pela applet. Estemétodo não costuma ser necessário, uma vez que ométodo “stop” é chamado antes do “destroy”,fazendo-se a libertação dos recursos nesse outrométodo.

Tabela 8: Os métodos da classe "Applet"

9.3 Desenhar e gerir eventos, numa applet (Métodos)

Existem outros métodos herdados de classes superiores à classe “Applet”.Esses outros métodos vão-nos permitir, por exemplo, desenhar botões eatribuir acções a esses botões.

Os métodos utilizados para desenhar uma representação de uma appletsão os métodos “paint” e “update”, descritos abaixo, que são herdados daclasse AWT (Abstract Window Toolkit).

Prof. Herberto Graça Página 66 de 217

Page 67: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Métodos para desenho deapplets

Função do método

paint O método mais comum para desenhar arepresentação de uma applet.

updateÉ utilizado em conjunto com o método “paint” de

modo a melhorar a performance deste.

Tabela 9: Métodos para desenho de applets

Os métodos utilizados para gerir eventos são muitos e são herdados daclasse “Component”. Um exemplo pode ser o método “mouseDown” que defineo comportamento da applet, quando se clicka com o rato, em cima desta.

import java.awt.Event;//. . .public boolean mouseDown(Event event, int x, int y) {

addItem("click!... ");return true;

}

A título de exemplo, vejamos a applet seguinte:

import java.applet.Applet;import java.awt.Event;import java.awt.Graphics;

public class Simple extends Applet {

StringBuffer buffer;

public void init() {buffer = new StringBuffer();addItem("initializing... ");

}

public void start() {addItem("starting... ");

}

public void stop() {addItem("stopping... ");

}

public void destroy() {addItem("preparing for unloading...");

}

void addItem(String newWord) {System.out.println(newWord);buffer.append(newWord);repaint(); //outra opção: paint(this.getGraphics());

}

public void paint(Graphics g) {//Desenha um rectângulo na área da Appletg.drawRect(0, 0, size().width - 1, size().height - 1);

//Desenha uma string dentro do rectangulog.drawString(buffer.toString(), 5, 15);

}

public boolean mouseDown(Event event, int x, int y) {addItem("click!... ");return true;

}}

Esta applet vai:

Prof. Herberto Graça Página 67 de 217

Page 68: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• Inicializar.

• Começar a execução.

• Fica à espera de um evento (um click do rato).

• Quando ocorre um evento:

• Adiciona a string “click!...” ao buffer e chama método “paint”,através do método “repaint” de modo a actualizar a applet.

• Quando a aplicação que contém a applet é minimizada outerminada, é chamado o método “stop”.

• Quando a aplicação que contem a applet é terminada, é chamado ométodo “destroy”, após o método “stop”.

9.4 Inserir uma applet numa página HTML

Vamos então agora, inserir a nossa applet “Simple” numa página HTML.

A primeira regra a ter em conta para se fazer isto é que a classe da nossaapplet não deve estar inserida em nenhum pacote, devemos então criar anossa classe, directamente na directoria “src”. Automaticamente, o Eclipse irácriar um “(default package)” e irá inserir a nossa classe nesse pacote. Oimportante é que no código, não exista nenhuma referência do tipo “packageum_pacote;”.

Para fazer o HTML carregar a applet, iremos utilizar a tag“<APPLET></APPLET>”. Partindo do principio que a nossa classe compiladaestá na mesma directoria do nosso ficheiro HTML basta-nos fazer a seguintechamada:

<APPLET CODE="Simple2.class" WIDTH="200" HEIGHT="50"> </APPLET>

Caso a nossa classe esteja noutra directoria, deveremos utilizar o atributo“codebase” para dizer em que directoria se encontra a classe.

<APPLET CODE="Simple2.class" WIDTH="200" HEIGHT="50" CODEBASE="applets/"> </APPLET>

Prof. Herberto Graça Página 68 de 217

Page 69: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

A tabela seguinte descreve os atributos específicos1 da tag “<APPLET>”:

Atributos Utilidade

codebase Especifica a localização do ficheiro de código.

code Especifica o nome do ficheiro da classe.

nameEspecifica o nome da instância, permitindo a

comunicação entre applets.

archiveEspecifica uma lista de ficheiros, separados por

“;”, que contém classes que serão carregadaspreviamente.

objectEspecifica um objecto serializado, localizado em

“codebase”. Quando deserializado, o método “init” nãoé invocado.

width Largura da applet.(é sempre necessário incluir)

height Altura da applet. (é sempre necessário incluir)

Tabela 10: Atributos específicos da tag <APPLET>

No entanto existe um problema com a tag <APPLET>, ela está fora de uso,devendo-se por isso utilizar a tag <OBJECT>, que é uma tag geral paraqualquer objecto de tipo de uma applet.

Mas como não podia deixar de ser, a tag <OBJECT> acarreta algunsproblemas para ser utilizada. Tanto é assim, que a Sun acabou por criar umaferramenta que nos traduz o código da tag <APPLET> para o código da tag<OBJECT>. Essa ferramenta encontra-se na directoria “bin” da instalação do“j2sdk”, chama-se “HtmlConverter.exe” e tem um GUI bastante simples.

9.4.1 Passagem de parâmetros para uma applet Tal com é bastante útil passar parâmetros para um método, também o é,

passar parâmetros para uma applet. Deste modo podemos, por exemplo,alterar as cores da nossa applet de modo a que esta se adapte ás cores danossa página.

Temos ainda a possibilidade de utilizar a tag <PARAM>, dentro de umbloco da tag <APPLET>. Nesta tag, vamos especificar o nome de cada um dosparâmetros de entrada, bem como do seu valor.

Então, se tivéssemos uma applet que utilizasse parâmetros, essesparâmetros seriam enviados utilizando o seguinte código:

<APPLET CODE = "UmaClasse.class" CODEBASE = "./" WIDTH = "55" HEIGHT = "10"><PARAM NAME = parametro1 VALUE=valor1><PARAM NAME = parametro1 VALUE=valor2>

</APPLET>

Na respectiva applet, esses parâmetros seriam acedidos através de ummétodo existente para esse efeito:

String parametroA=getParameter("parametro1");

Prof. Herberto Graça Página 69 de 217

Page 70: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

9.5 Exercícios

1) Modifica a classe “Simple”, de modo a que a cor de fundo e a cordas letras sejam dadas como parâmetros de entrada.3

2) Cria um ficheiro HTML, que chame a applet que criaste antes e lhepasse os parâmetros de entrada.4

3) Completa a seguinte classe, que é uma classe de uma applet quemostra um relógio. Deves construir o método “init” e o método“paint”. Esta applet deve receber a cor das letras e a cor do fundocomo parâmetro de entrada, sendo que caso esses parâmetros nãosejam fornecidos, o fundo deverá ser branco e as letras deveram serpretas. O formato da hora deverá ser do tipo: ”hh:mm:ss”.

import java.awt.Graphics;import java.awt.Color;import java.util.Date;

public class Clock_2 extends java.applet.Applet implements Runnable {private Thread clockThread = null;String cor_de_fundo;String cor_de_font;

public void init() { //... }

public void start() {if (clockThread == null) {

clockThread = new Thread(this, "Clock");clockThread.start();

}}

public void run() {Thread myThread = Thread.currentThread();while (clockThread == myThread) {

repaint();try { Thread.sleep(1000);} catch (InterruptedException e){ }

}}

public void paint(Graphics g) { //... }

public void stop() {clockThread = null;

}}

3 Podes testar o teu código, inserindo as variáveis de entrada no menu: Run > Run… > Parameters

4 Para testar o código, é necessário ele ser colocado num servidor WEB

Prof. Herberto Graça Página 70 de 217

Page 71: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

10 Criar um GUI com o JFC/Swing

10.1 Importar os pacotes necessários

Para a construção de um GUI, o primeiro pacote que é necessário importaré o pacote “javax.swing”, que contém o conjunto de componentes que seutilizam na construção da vasta maioria dos GUIs.

Para além desse pacote, existem ainda dois outros pacotes que deverãoser necessários em muitos casos. Um, é o pacote “java.awt” que contém todasas classes necessárias para a construção de GUIs e que são utilizadas peloscomponentes do pacote swing. O outro, é o pacote “java.awt.event”, quecontém as interfaces e as classes para lidar com os eventos (por ex. o clicknum botão), “disparados” pelos componentes do pacote swing ou pelas classesdo pacote awt.

Pacotes que devem serimportados

Utilidade

import javax.swing.*;Contém o conjunto de componentes que se

utilizam na construção da vasta maioria dos GUIs.

import java.awt.*;Contém todas as classes necessárias para a

construção de GUIs e que são utilizadas peloscomponentes do pacote swing.

import java.awt.event.*;

Contém as interfaces e as classes para lidarcom os eventos (por ex. o click num botão),“disparados” pelos componentes do pacote swing oupelas classes do pacote awt.

Tabela 11: Pacotes utilizados na construção de GUI

10.2 Escolher o aspecto do GUI

Existem três tipos de aspecto disponibilizados pelo JAVA:

Nome Aspecto

Java

CDE/Motif

Windows

Tabela 12: Aspectos disponibilizados pelo JAVA

Caso não seja escolhido nenhum aspecto, será sempre utilizado o aspecto

Prof. Herberto Graça Página 71 de 217

Page 72: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

do JAVA, por default. Caso se pretenda escolher um aspecto, deverá serutilizado um código semelhante ao seguinte:

public static void main(String[] args) {try {

UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

} catch (Exception e) { }// Criar e mostrar o GUI...

}

No exemplo anterior, definiu-se o aspecto do Windows com a string"com.sun.java.swing.plaf.windows.WindowsLookAndFeel" passada comoparâmetro para o método estático “setLookAndFeel” da classe “UIManager”.No entanto, poderíamos utilizar qualquer um dos seguintes argumentos:

Argumento Comentários

"javax.swing.plaf.metal.MetalLookAndFeel" Específica o aspecto JAVA.

"com.sun.java.swing.plaf.windows.WindowsLookAndFeel"

Específica o aspecto Windows.Apenas pode ser utilizado com oWindows.

"com.sun.java.swing.plaf.motif.MotifLookAndFeel" Específica o aspecto Motif.

UIManager.getCrossPlatformLookAndFeelClassName()Retorna um estilo que pode ser

sempre utilizado em qualquerplataforma.

UIManager.getSystemLookAndFeelClassName() Retorna o estilo típico daplataforma corrente.

Tabela 13: Argumentos para selecção de um aspecto visual

10.3 JFrame, a base de um GUI

Uma coisa comum a todos os programas que utilizam um GUI é o facto detodos eles abrirem uma janela onde serão colocadas as ferramentas parautilizar o programa. Assim sendo, ao construir um GUI, a primeira coisa a fazeré criar a nossa janela.

Em JAVA, a classe utilizada para criar a janela do nosso programa é aclasse “Jframe”.

Para exemplificar a utilização desta classe, vejamos mais uma vez oexemplo do costume, o programa “Hello World”:

import javax.swing.*; //Importa os pacotes necessáriospublic class HelloWorldSwing {

public static void main(String[] args) {JFrame frame = new JFrame("HelloWorldSwing");//cria a janelaframe.setSize(165,79);//estabelece o tamanho da janelaframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true); //torna a janela visível

}}

Prof. Herberto Graça Página 72 de 217

Page 73: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

No exemplo anterior é utilizada a classe “JFrame”, do pacote swing, sendode notar a linha:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Esta linha de código vai instruir a janela sobre o que fazer quando esta forfechada, sendo que neste caso, quando a janela for fechada, o programa seráterminado. Se comentares esta linha de código, vais poder observar, no painelde debug do Eclipse, que quando fechares a janela, o programa irá continuaractivo.

10.4 Colocar botões e etiquetas

O programa anterior, criou uma janela com o título “HelloWorldSwing”,mas isso talvez não fosse bem o que estávamos à espera. Seria preferível umajanela em que a frase “HelloWorld” aparecesse no seu interior.

import javax.swing.*; //Importa os pacotes necessários

public class HelloWorldSwing {public static void main(String[] args) {

JFrame frame = new JFrame("HelloWorldSwing"); //cria a janela

final JLabel label = new JLabel("Hello World"); //cria uma etiquetacom texto

frame.getContentPane().add(label); //coloca a etiqueta na janela

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.pack(); //adapta o tamanho da janela aos

seus conteúdosframe.setVisible(true); //torna a janela visível

}}

Nesta nova versão do nosso programa, para além de criar a janela, criatambém uma etiqueta com o texto “Hello World”, colocando-o depois na janela.Outra diferença, é que não definimos o tamanho da janela, utilizando o método“pack” para adaptar o tamanho da janela aos conteúdos desta.

Do mesmo modo como criamos e colocamos a etiqueta na janela,poderíamos ter colocado um botão, bastando para isso, utilizar a classe“JButton” em vez da classe “JLabel”.

O Apêndice A contém uma lista de alguns dos componentes do pacoteswing.

10.5 Colocar componentes noutros “contentores”

Uma técnica bastante útil quando se constrói um GUI em JAVA é agruparcomponentes que deverão ficar situadas na mesma zona do GUI. Esseagrupamento, é feito utilizando componentes “contentores”. O componentemais utilizado para este efeito, é o “JPanel”.

Na seguinte versão do “Hello World”, a label é colocada num painel e

Prof. Herberto Graça Página 73 de 217

Page 74: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

depois o painel é colocado na frame.

import javax.swing.*; import java.awt.*;

public class HelloWorldSwing {public static void main(String[] args) {

JFrame frame = new JFrame("HelloWorldSwing");//cria a janelaJPanel pane = new Jpanel();

//cria uma etiqueta com textofinal JLabel label = new JLabel("Hello World");label.setForeground(Color.GREEN);label.setBackground(Color.WHITE);

pane.add(label);//coloca a etiqueta no painelpane.setBackground(Color.ORANGE);frame.getContentPane().add(pane);//coloca o painel na janela

frame.getContentPane().setBackground(Color.BLUE);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.pack(); //adapta o tamanho da janela aos seus conteúdosframe.setVisible(true);//torna a janela visivel

}}

Prof. Herberto Graça Página 74 de 217

Page 75: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

10.5.1 Layout managers Os layout managers são os objectos que fazem a gestão de como os

componentes do GUI vão ser colocados num contentor. O JAVA disponibilizacinco layout managers principais:

Descrição ExemploBorderLayout

Este é o tipo de layout por defeito, para asframes, applets e caixas de diálogo. Estádividido em cinco áreas, norte, sul, este, oestee centro. Quando se coloca um componente, tem dese especificar em que área, o componente, deveráser colocado.

GridLayout

Este layout divide um contentor numa grelha departes iguais, com um número de linhas e colunasdefinidas aquando da construção deste layout. Ámedida que se colocam componentes no contentor,os componentes vão preenchendo as posições dagrelha, da esq. para a dir., de cima para baixo.

FlowLayout

É o layout por defeito, do JPanel. Neste layout,os componentes são colocados da esquerda para adireita, sendo criadas novas linhas conforme sejanecessário.

BoxLayout

Este layout coloca todos os componentes na mesmalinha ou coluna, permitindo definir os tamanhosdos componentes e alinha-los.

GridBagLayout

Este layout é o mais sofisticado e flexível detodos, uma vez que apesar de criar uma grelhacomo o GridLayout, permite que os componentesocupem várias células, para além de que as linhase as colunas podem ter alturas e largurasdiferentes.

Tabela 14: Os Layout Managers

O exemplo seguinte é uma adaptação do anterior, mas que vai colocaruma label no canto sup. esq. e outra no canto inf. dir., utilizando um“GridLayout”:

import javax.swing.*; import java.awt.*;

public class HelloWorldSwing {public static void main(String[] args) {

JFrame frame = new JFrame("HelloWorldSwing"); //cria a janelaframe.getContentPane().setBackground(Color.BLUE);

JPanel pane = new JPanel();pane.setLayout(new GridLayout(2, 2));pane.setBackground(Color.ORANGE);

final JLabel label = new JLabel("posicao 1-1"); //cria uma etiqueta com texto

Prof. Herberto Graça Página 75 de 217

Page 76: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

label.setForeground(Color.GREEN);label.setBackground(Color.WHITE);final JLabel label2 = new JLabel("posicao 2-2");//cria uma etiqueta com texto

pane.add(label);//coloca a etiqueta no painelpane.add(new JPanel());pane.add(new JPanel());pane.add(label2);

frame.getContentPane().add(pane);//coloca o painel na janelaframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.pack(); //adapta o tamanho da janela aos seus conteúdosframe.setVisible(true); //torna a janela visível

}}

10.6 Criar margens nos componentes

As margens têm a única função de criar espaço vazio em redor doscomponentes. As margens são criadas utilizando a classe “BorderFactory”, quecontém vários tipos de margens.

Por exemplo, para criar margens no nosso painel do exemplo anterior,seria suficiente acrescentar o código seguinte:

pane.setBorder(BorderFactory.createEmptyBorder(30, //margem sup30, //margem esq10, //margem inf30) //margem dir

);

10.7 Estabelecer acções para os eventos

10.7.1 O que são os eventos Num programa podem acontecer vários eventos, de vários tipos, que tem

origem em acções. Essas acções podem ser, por exemplo, carregar no enter ouclickar num botão do rato.

Para um objecto captar um evento, apenas necessita de implementar ainterface apropriada e ser registado na fonte do evento, como sendo um eventlistener.

Uma aplicação swing pode gerar vários eventos, por exemplo:

Prof. Herberto Graça Página 76 de 217

Page 77: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Acção que resulta no evento Tipo de listener

Clickar um botão ou pressionar o enter. ActionListener

Fechar uma janela. WindowListener

Pressionar no botão do rato. MouseListener

Passar com o rato por cima de umcomponente. MouseMotionListener

Tornar um componente visível. ComponentListener

Um componente “apodera-se” do teclado. FocusListener

O elemento seleccionado numa caixa, éalterado. ListSelectionListener

Tabela 15: Acções que resultam em eventos

Um evento não é mais do que um objecto com informação acerca doevento e da sua fonte e do mesmo modo que um componente pode ter váriosevent listeners, um event listener pode estar associado a vários componentes.

10.7.2 Como implementar um event listener Os componentes que levam à utilização de event listeners mais

frequentemente são os botões e as janelas. O event listener mais utilizado paraum botão é um “ActionListener” que, geralmente, implementa apenas ummétodo, o método “public void actionPerformed(ActionEvent e)”. A suautilização pode ser vista no exemplo seguinte:

//...JButton botão = new JButton("Um botão!");botão.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {//Código que o botão executa quando é

clickado}

});//...

Um event listener utilizado com uma janela, pode ser, por exemplo umque permita especificar o que uma janela deve fazer quando é fechada. Onormal é dizer que o fechar a janela, o programa deverá ser terminado, noentanto poderia ser útil dizer ao programa para colocar um ícone no systemtray e continuar activo.

O exemplo seguinte implementa um event listener numa janela, de modoa terminar o programa, quando a janela for fechada.

//...JFrame frame = new JFrame("Uma janela!");frame.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {System.exit(0);

}});//...

Prof. Herberto Graça Página 77 de 217

Page 78: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Os exemplos acima, criam um novo objecto especificamente para lidarcom o evento, no entanto também é possível fazer a nossa classe implementara interface pretendida. O exemplo seguinte ilustra a utilização desta outratécnica, criando um botão que utiliza o event listener da classe onde estáinserido:

public class Blabla implements ActionListener {//...button.addActionListener(this);//...public void actionPerformed(ActionEvent e) {

//Código do botão...}

}

O código dos event handlers deve ser composto apenas por operaçõesleves e rápidas, uma vez que todo esse código é executado numa thread a quese chama “event-dispatching thread” que é a mesma thread responsável por,por exemplo, pintar um GUI. Isto significa que, enquanto estiver a serexecutado o código de um event handler, não será possível actualizar o GUI.Por esta razão, se for pretendido executar código que seja lento, deve-se criaruma thread separada para o executar.

10.8 Exercícios

1) Crie o programa “hello world” mas com um botão em vez de umalabel.

2) Crie um novo projecto chamado “Agenda” e segue as seguintesinstruções, de modo a criar uma agenda. As classes seguintesdevem ser criadas dentro de um pacote chamado “GUI”.

a) Crie a classe “Dia”, que deverá ser identificada por um dia, ummês e um ano, e deverá ser representado por um botão com onúmero do dia. No main, cria código que mostre o botão numajanela.

b) Crie a classe “Mes” que deverá ser identificada por um mês eum ano. Deverá conter os dias desse mês e deverá serrepresentado por um painel com os dias e o nome do mês, notopo. No main, cria código que mostre o mês numa janela.

c) Crie a classe “Ano”, que deverá ser representada por um ano edeverá conter os meses desse ano. A sua representaçãodeverá ser um painel, com o número do ano no topo e osrespectivos meses. No main, cria código que mostre o anonuma janela.

d) Faça com que, quando se carregue num dia, apareça umacaixa a dizer a data desse dia.

e) Faça com que, os sábados e domingos apareçam com onúmero em verde.

f) Crie uma classe “agenda”, com uma barra de menus com osseguintes itens:

Prof. Herberto Graça Página 78 de 217

Page 79: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• Ficheiro

Opção para criar um determinado ano;Gravar o ano activo, para um ficheiro;Carregar um ano gravado num ficheiro;Sair;

• Configurações

Opção para escolher a cor dos dias defim-de-semana;

• Ajuda

Sobre.

3) Crie um novo projecto chamado “Guestbook”, onde criarás o GUI deum guestbook com as seguintes características. As classesnecessárias devem ser criadas dentro de um pacote chamado “GUI”.

a) Tem um menu com as várias acções do programa;

a) Deve ter uma opção para “instalação”, que será onde osutilizadores configurarão os dados da base de dados, e a basede dados será criada.

b) Deve ter um painel para recolher as seguintes informações dosutilizadores:

• Nome;• Localidade;• Email;• Comentário;

c) Deve ter um painel para mostrar os comentários já inseridosna tabela, com o ultimo inserido no topo;

d) Quando se inserirem dados na tabela, os dados por baixo dopainel de recolha de dados deverão ser actualizados.

e) Cria um outro painel para aceder ao mesmo guestbook, masque só mostra um comentário, e tem botões para circular parao comentário seguinte ou anterior.

4) Construa o GUI de um fórum, semelhante a um fórum do moodle. Onovo projecto deve ser chamado “Forum”. As classes necessáriasdevem ser criadas dentro de um pacote chamado “GUI”.

5) Construa um GUI para o projecto Adamastor, criado no capítuloanterior, com painéis semelhantes aos seguintes.

Prof. Herberto Graça Página 79 de 217

Page 80: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

a)

b)

c)

d) Rever os produtos:

Prof. Herberto Graça Página 80 de 217

Page 81: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

e) Adicionar produtos:

f)

g)

Prof. Herberto Graça Página 81 de 217

Page 82: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

h)

Prof. Herberto Graça Página 82 de 217

Page 83: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

11 Acesso a Bases de Dados

Em JAVA o acesso a bases de dados faz-se utilizando a API (ApplicationProgramming Interface) chamada JDBC.

O JDBC permite-nos:

• Ligar a uma base de dados;

• Enviar SQL para uma base de dados;

• Receber dados de uma base de dados;

O código seguinte é um exemplo dos três passos enunciados antes:

Connection con = DriverManager.getConnection( "jdbc:myDriver:wombat", "myLogin","myPassword");

Statement stmt = con.createStatement();ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");while (rs.next()) {

int x = rs.getInt("a");String s = rs.getString("b");float f = rs.getFloat("c");

}

De seguida será dada uma breve visão da arquitectura do JDBC eposteriormente cobriremos a prática de acesso a bases de dados, para o qualutilizaremos uma base de dados em MySQL, assumindo que já temos um SGBDMySQL instalado e a correr.

11.1 Arquitectura do JDBC

O JDBC suporta modelos de implementação de dois nós ou três nós, paraacesso a bases de dados.

11.1.1 Modelo de dois nósNeste modelo de acesso a bases de dados a aplicação, ou applet,

comunica directamente com a base de dados, necessitando de um driverespecifico do SGBD para conseguir comunicar. O SGBD a ser acedido podeestar no mesmo computador da aplicação ou num outro computador sendo,nesse caso, acedido através de uma rede informática. Este é o modelo utilizadoem aplicações simples Java SE.

Prof. Herberto Graça Página 83 de 217

Ilustração 18: Acesso a BD, no modelo de doisnós

Page 84: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

11.1.2 Modelo de três nósNo modelo de três nós, o acesso a uma base de dados é realizado através

de um intermediário, um servidor com toda a “lógica de negócio”, sendo ocliente apenas um GUI onde o utilizador visualiza e introduz informação, semqualquer tipo de processamento de dados. Este modelo é utilizado emaplicações complexas de contexto empresarial, com base em Java EE.

Este modelo tem as seguintes vantagens relativamente ao modelo de doisnós:

• O nó intermédio permite controlar o acesso aos dados e ao tipo dealterações que podem ser realizadas aos dados das empresas;

• Simplifica o distribuição e instalação da aplicação;

• Facilita as alterações na lógica de negócio, pois muitas alteraçõesapenas necessitam ser realizadas no servidor, não se reflectindo noGUI;

• Em muitos casos este modelo permite vantagens de performance.

11.2 Preparando o acesso ao SGBD

As classes do pacote java.sql (utilizadas para fazer a ligação ao SGBD)são, na sua grande maioria, apenas interfaces porque deste modo, aimplementação dessas classes fica por conta de alguém que entende dedeterminado SGBD. Por exemplo, se temos o MySQL, alguém que entenda doMySQL implementa as classes do java.sql específicas para MySQL, destaforma, nós podemos fazer conexão com o MySQL através dessas classes. Aocontrário de linguagens como php, o java não tem esses driversimplementados, eles são implementados pelo criador de cada SGBD, destamaneira, novos drivers vão aparecendo à medida que novos SGBD e novasversões deles vão aparecendo, o que seria um caos para a Oracle ter de fazer,além de provavelmente não utilizar o melhor potencial do banco de dados.

Para o JAVA aceder a um SGBD, iremos utilizar drivers específicos paraesse SGBD, que teremos de disponibilizar à JVM.

A disponibilização do driver à JVM pode ser realizada de três formas

Prof. Herberto Graça Página 84 de 217

Ilustração 19: Acesso a BD, no modelo de trêsnós

Page 85: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

diferentes:

1. Colocando o caminho para o driver na variável de sistema“CLASSPATH”;

2. Colocando o driver na pasta: $JAVA_HOME/jre/lib/ext ;

3. Disponibilizando o driver juntamente com o nosso pacote desoftware.

Iremos utilizar o método mais simples, e disponibilizaremos o driverjuntamente com o nosso pacote de software.

11.2.1 Com o SGBD MySQLVamos partir do pressuposto que o SGBD MySQL já está instalado e em

funcionamento. Caso não disponha de um SGBD MySQL funcional, consulte oseguinte site para o instalar e configurar:

http://www.apachefriends.org/en/xampp.html

Fazemos o download do driver de MySQL para JAVA, a partir da seguintelocalização: http://dev.mysql.com/downloads/connector/j/

Descomprimimos o ficheiro puxado e colocamos o ficheiromysql­connector­java­X.X.XX­bin.jar numa pasta chamada lib, directamentedentro da pasta do projecto. De seguida, clickamos com o botão direito do ratoem cima do ficheiro anterior (o driver), e seleccionamos a opção “Build Path >Add to Build Path”. Assim, o nosso projecto terá sempre acesso ao driver deMySQL, sem nos termos de preocupar com o CLASSPATH, nem copiarmosficheiros para outras localizações.

No ficheiro comprimido que puxámos anteriormente também estádocumentação relativa ao método de utilização deste driver, e como aceder abases de dados MySQL, com o JAVA.

11.2.2 Com o SGBD DerbyO SGBD Derby tem dois modos de funcionamento:

• Embebido: Utilizado quando temos uma aplicação desktop , com umúnico utilizador, que utiliza uma base de dados em exclusividade. Ouseja, a base de dados faz parte do próprio programa e édisponibilizada juntamente com o software.

• Rede: Utilizado quando temos vários utilizadores a utilizar a mesmaaplicação simultaneamente, e que, portanto, acedem à base dedados simultaneamente. Neste modo de funcionamento o SGBDDerby tem a mesma utilidade do MySQL.

Fazemos o download do SGBD Derby, a partir da seguinte localização:http://db.apache.org/derby/derby_downloads.html

Se pretendermos a versão para Windows, puxamos o ficheirodb­derby­10.6.2.1­bin.zip, caso desejarmos a versão para Unix, Linux ou Mac,puxamos o ficheiro db­derby­10.6.2.1­bin.tar.gz .

Prof. Herberto Graça Página 85 de 217

Page 86: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Depois de descomprimirmos o ficheiro anterior, teremos uma pasta, comvárias pastas dentro. Uma dessas bastas é a pasta lib, que contém váriosficheiros JAR. Aqui, o ficheiro que nos interessa é o ficheiro derby.jar, que narealidade é o SGBD Derby. Colocamos o ficheiro numa pasta chamada lib,directamente dentro da pasta do projecto. De seguida, clickamos com o botãodireito do rato em cima do ficheiro anterior, e seleccionamos a opção “BuildPath > Add to Build Path”. Assim, o nosso projecto terá sempre acesso aodriver do Derby, sem nos termos de preocupar com o CLASSPATH, nemcopiarmos ficheiros para outras localizações.

No entanto este método apenas serve para utilizarmos a base de dadosem modo embebido, para utilizarmos este SGBD em modo de rede, deveremosinstalar a aplicação por inteiro, seguindo as instruções em:

http://db.apache.org/derby/papers/DerbyTut/install_software.html

Nos exemplos seguintes de utilização do SGBD Derby, vamos remeter-nosessencialmente ao modo embebido, no entanto a única diferença práticaprende-se com o nome do driver a utilizar.

11.3 Plugins para Eclipse

Existem vários plugins para trabalhar bases de dados em Eclipse. Nósutilizaremos três plugins, open source, que se descrevem de seguida:

Plugin Descrição

Apache Derby Plugins Plugins oficiais da BD Derby.

DTP - Data Tools Platform Projecto Eclipse para Bases de Dados.

AmaterasERD Projecto independente open source

Tabela 16: Lista de plugins de Bases de Dados

11.3.1 Apache Derby PluginsSãoos plugins oficiais para a BD Derby. Permite:

• Adicionar os drivers de ligação à BD Derby (Derby Nature);

• Iniciar/Parar um servidor Derby, num determinado projecto;

• Executar ficheiros SQL directamente.

11.3.1.1 Instalação

Faz-se o download dos seguintes ficheiros:

• derby_core_plugin_XXX.zip • derby_ui_doc_plugin_XXX.zip

Descomprimem-se os ficheiros e colocam-se as pastas descomprimidas napasta de plugins dentro da pasta de instalação do Eclipse (ou em linux:~/.eclipse/plugins). As pastas a ser colocadas na pasta de plugins são as

Prof. Herberto Graça Página 86 de 217

Page 87: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

seguintes:

• org.apache.derby.core_XXX• org.apache.derby.ui_XXX• org.apache.derby.plugin.doc_XXX

11.3.1.2 Documentação

http://db.apache.org/derby/integrate/plugin_howto.html

http://db.apache.org/derby/integrate/plugin_help/start_toc.html

11.3.2 DTP - Data Tools Platform Trata-se do subprojecto Eclipse para manuseamento de bases de dados.

Permite:

• Executar scripts SQL directamente;

• Construir consultas à BD, de forma visual;

• Visualizar os resultados de consultas à BD;

• Verificar toda a estrutura da BD.

11.3.2.1 Instalação

É necessário instalar os pacotes:

• GEF - Graphical Editing Framework◦ Pelos plugins oficiais do Eclipse◦ Instalação da última versão, pelo Eclipse:

http://download.eclipse.org/tools/gef/updates/releases/ • EMF - Eclipse Modeling Framework• DTP - Data Tools Platform (enablement)

◦ Instalação da última versão, pelo Eclipse:http://download.eclipse.org/datatools/updates

11.3.2.2 Documentação

http://www.vogella.de/articles/EclipseDataToolsPlatform/article.html

http://help.eclipse.org/ganymede/index.jsp?topic=/org.eclipse.datatools.common.doc.user/projects/dtp/dtp/en/source/c_tutorial_overview.html

11.3.3 AmaterasERDAmaterasERD é um plugin de Eclipse para desenhar diagramas

Entidade-Relacionamento. Permite:

• Edição grágica de diagramas ER;• Importação do diagrama ER, de uma BD existente;• Geração de DDL a partir de um diagrama ER;• Exportação da definição das tabelas em formato HTML.

Além disso, este plugin necessita de um outro plugin dos mesmos

Prof. Herberto Graça Página 87 de 217

Page 88: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

desenvolvedores, o plugin AmaterasUML que permite:

• Desenhar diagramas de classes UML;• Desenhar diagramas de sequencia UML.

11.3.3.1 Instalação

É necessário instalar os pacotes:

• GEF - Graphical Editing Framework◦ Pelos plugins oficiais do Eclipse◦ Instalação da última versão, pelo Eclipse:

http://download.eclipse.org/tools/gef/updates/releases/ • AmaterasUML - Eclipse Modeling Framework

◦ Download da última versão de:http://sourceforge.jp/projects/amateras/releases/

◦ Descomprimir o pacote para a pasta de plugins do Eclipse• AmaterasERD - Data Tools Platform

◦ Download da última versão de:http://sourceforge.jp/projects/amateras/releases/

◦ Colocar o pacote JAR na pasta de plugins do Eclipse

11.3.3.2 Documentação

http://amateras.sourceforge.jp/cgi-bin/fswiki_en/wiki.cgi?page=AmaterasUML

http://amateras.sourceforge.jp/cgi-bin/fswiki_en/wiki.cgi?page=AmaterasERD

11.4 Ligação à Base de Dados

Temos duas metodologias para ligar a uma base de dados:

• Utilizando o JNDI e o Datasource (JAVA EE)

◦ “JNDI lookups”, é uma forma automática de conseguir umaligação à base de dados, no entanto necessitamos de um servidorde aplicações JAVA EE com suporte a “connection pooling”.“connection pooling” é uma técnica em que pedimos ao servidorpara criar várias ligações a uma base de dados, queposteriormente serão “emprestadas” aos clientes que queremaceder à base de dados. Este método também é preferencialquando utilizamos JSP com o servidor Tomcat, que disponibilizaserviços JNDI e “connection pools”. Neste caso a ligação pode serestabelecida apenas com três linhas de código, por exemplo:

InitialContext ic = new InitialContext();DataSource ds = ic.lookup("java:comp/env/jdbc/myDB");Connection con = ds.getConnection();

◦ Usamos o “Datasource” manual quando temos um servidor JAVAEE sem suporte a “connection pooling”. Nesta metodologiateremos de fornecer todos os dados de ligação, por exemplo:

DataSource ds = (DataSource) org.apache.derby.jdbc.ClientDataSource()ds.setPort(1527);ds.setHost("localhost");ds.setUser("APP")ds.setPassword("APP");

Prof. Herberto Graça Página 88 de 217

Page 89: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Connection con = ds.getConnection();

• Utilizando o DriverManager (JAVA SE)

◦ Quando não temos um servidor de aplicações JAVA EE, resta-nosa opção de utilização do DriverManager. É este o nosso caso, cujocódigo poderá ser, por exemplo no caso do MySQL:

String DB_NAME = "test";String DB_PROTOCOL = "jdbc:mysql://localhost/";String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";String USER_NAME = "";String PASS = "";Class.forName(DRIVER_CLASS_NAME).newInstance();Connection con = DriverManager.getConnection(DB_PROTOCOL+DB_NAME,USER_NAME,PASS);//...instruções...con.close();

No caso do Derby, modo embebido seria:

String DB_NAME = "test";String DB_PROTOCOL = "jdbc:derby:";String DRIVER_CLASS_NAME = "org.apache.derby.jdbc.EmbeddedDriver";String USER_NAME = "";String PASS = "";Class.forName(DRIVER_CLASS_NAME).newInstance();Connection con = DriverManager.getConnection(DB_PROTOCOL+DB_NAME,USER_NAME,PASS);//...instruções...con.close();

No caso do Derby, modo de rede seria:

String DB_NAME = "test";String DB_PROTOCOL = "jdbc:derby://localhost:1527/";String DRIVER_CLASS_NAME = "org.apache.derby.jdbc.ClientDriver";String USER_NAME = "";String PASS = "";Class.forName(DRIVER_CLASS_NAME).newInstance();Connection con = DriverManager.getConnection(DB_PROTOCOL+DB_NAME,USER_NAME,PASS);//...instruções...con.close();

Quando já não necessitarmos comunicar com a base de dados,devemos fechar a ligação utilizando o método close().

Repare que as únicas diferenças nos exemplos acima se limitamao driver e ao protocolo. Tudo o resto é exactamente igual nostrês exemplos dados, mas também em todos os outros SGBD, oque faz com que as aplicações que construirmos sejamtransparentes, relativamente à base de dados utilizada.

11.5 Envio de comandos a uma Base de Dados

Para enviarmos comandos a um SGBD, teremos de criar um objecto daclasse Statement, que é obtido através da ligação à base de dados, criada antes.Assim, continuando o exemplo anterior, utilizamos o objecto con para criar onosso objecto Statement:

Statement sttmt = con.createStatement();

Agora, com o objecto sttmt, poderemos enviar comandos à base de dados.Esse código pode retornar um conjunto de dados, no caso de uma pesquisa dedados (SQL: SELECT), ou não retornar dados, no caso de se inserir, alterar ou

Prof. Herberto Graça Página 89 de 217

Page 90: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

eliminar dados (DML), ou ainda no caso de se fazerem alterações à definiçãodas tabelas (DDL).

11.5.1 Enviar comandos que não devolvem dadosNo caso de pretendermos enviar comandos DML (Insert, Update, Delete) ou

DDL (Create, Alter, Drop), usaremos o método executeUpdate, por exemplo:

Statement sttmt = con.createStatement ();int count;//Código DDLsttmt.executeUpdate ("DROP TABLE IF EXISTS animal");sttmt.executeUpdate ( "CREATE TABLE animal (" + "id INT UNSIGNED NOT NULL AUTO_INCREMENT," + "PRIMARY KEY (id)," + "nome CHAR(40), categoria CHAR(40))");//Código DMLcount = sttmt.executeUpdate ( "INSERT INTO animal (nome, categoria)" + " VALUES" + "('cobra', 'réptil')," + "('rã', 'anfíbio')," + "('atum', 'peixe')," + "('gato', 'mamífero')");sttmt.close ();System.out.println ("Foram inseridas " + count + " linhas.");

No caso de enviarmos comandos DML, o método executeUpdate irá devolvero número de linhas afectadas (inseridas, eliminadas ou modificadas). Noexemplo acima a variável count é utilizada para guardar a quantidade de linhasinseridas, e posteriormente enviar para a consola.

Um objecto do tipo Statement pode ser utilizado para enviar váriasinstruções à base de dados. No exemplo anterior, o mesmo objecto sttmt éutilizado para enviar três conjuntos de instruções diferentes.

Após utilizarmos o objecto Statement devemos chamar o seu métodoclose(), para o destruir e libertar os recursos a si associados.

11.5.2 Enviar comandos que devolvem dadosQuando pretendemos fazer uma consulta à base de dados, utilizando

comandos SQL (Select), iremos utilizar o método executeQuery, que nosdevolverá um conjunto de dados num objecto do tipo ResultSet, por exemplo:

Statement s = con.createStatement ();ResultSet rs = s.executeQuery ("SELECT id, nome, categoria FROM animal");//...instruções...rs.close ();s.close ();

O conjunto de dados devolvido pelo objecto Statement consiste numatabela, representada por um objecto do tipo ResultSet. Para aceder aos dadosna tabela, iremos circular pelas suas linhas, mas por defeito apenas poderemoscircular sequencialmente e para a frente. Se necessitarmos de percorrer atabela para trás e para a frente, pelas linhas da tabela, teremos de criar onosso objecto da classe Statement com dois dos argumentos seguintes, sendoentão chamado de “scrollable”:

Prof. Herberto Graça Página 90 de 217

Page 91: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Parâmetro Descrição

TYPE_FORWARD_ONLY Apenas poderemos circular sequencialmente.

TYPE_SCROLL_INSENSITIVEPoderemos circular livremente pelas linhas da tabela de dados, mas não serão reflectidas alterações entretanto efectuadas nos dados.

TYPE_SCROLL_SENSITIVEPoderemos circular livremente pelas linhas da tabela de dados, sendo reflectidas as alteraçõesentretanto efectuadas nos dados.

Tabela 17: Tipos de movimentação permitidos um objecto ResultSet

Parâmetro Descrição

CONCUR_READ_ONLY Apenas poderemos realizar leitura de dados.

CONCUR_UPDATABLE Poderemos realizar alterações nos dados.

Tabela 18: Tipos de permissões de acesso a um objecto ResultSet

Assim, se quisermos criar um objecto ResultSet no qual seja possívelcircular pelas suas linhas deveremos criá-lo com dois argumentos, um quedefine a o tipo de movimentação possível na tabela de dados, e outro quedefine se pretendemos fazer actualizações nos dados ou não. Por exemplo:

Statement s = con.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);

ResultSet rs = s.executeQuery ("SELECT id, nome, categoria FROM animal");//...instruções...rs.close ();s.close ();

Mais uma vez, quando já não necessitarmos do objecto ResultSet,devemos utilizar o método close() para libertar os recursos associados a ele.

11.6 Receber dados de uma Base de Dados

Como referido antes, os dados devolvidos por uma consulta são-nosdisponibilizados dentro de um objecto da classe ResultSet, organizados emforma de tabela, na qual iremos circular pelas suas linhas de forma a acederaos dados.

11.6.1 Aceder às linhas de uma tabela de resultados (ResultSet)

Um objecto ResultSet disponibiliza-nos seguintes métodos paracircularmos nas linhas da tabela de dados:

Prof. Herberto Graça Página 91 de 217

Page 92: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Método Descrição

next()Move o cursor uma linha para a frente. Se o cursor estiver numa linha, devolve true, se estiver após a ultima linha, devolve false.

previous()Move o cursor uma linha para trás.Se o cursor estiver numa linha, devolve true, se estiver antes da primeira linha, devolve false.

first()Coloca o cursor para a primeira linha. Se o ResultSet não tiver linhas, devolve false.

last()Coloca o cursor para a última linha. Se o ResultSet não tiver linhas, devolve false.

beforeFirst()Coloca o cursor na posição inicial, antes da primeira linha. Se o ResultSet não tiver linhas,não tem qualquer efeito.

afterLast()Coloca o cursor na posição final, após a última linha. Se o ResultSet não tiver linhas,não tem qualquer efeito.

relative(int linhas)Move o cursor um numero específico de linhas, relativamente à sua posição actual.

absolute(int linha)Move o cursor para uma linha específica do ResultSet.

Tabela 19: Métodos para circular na tabela de dados de um objecto da classe ResultSet

Se tivermos um objecto ResultSet scrollable, poderemos usar todos estesmétodos para circular pela tabela de resultado, caso contrário apenaspoderemos usar alguns deles.

Inicialmente o cursor do objecto ResultSet aponta para uma posição antesda primeira linha, portanto quando chamarmos pela primeira vez o métodonext() o cursor irá ser colocado na primeira linha da tabela resultado, e assimsucessivamente até chegar ao final da tabela resultado.

Se quisermos percorrer a tabela resultado em ordem inversa, do final parao inicio, teremos de colocar o cursor após a última linha, usando o métodoafterLast(), e de seguida usar o método previous() para mover o cursor para alinha anterior.

11.6.2 Aceder às colunas de uma tabela de resultados (ResultSet)

Um objecto ResultSet disponibiliza-nos vários métodos getXxx() paraaceder às colunas da tabela de dados, por exemplo:

Método Descrição

getString(int numCol)getString(String nomeCol)

Acede a uma coluna do tipo VARCHAR, ou equivalente, e devolve os seus conteúdos em formato String.

getFloat(int numCol)getFloat(String nomeCol)

Acede a uma coluna do tipo FLOAT, ou equivalente, e devolve os seus conteúdos em formato Float.

getInt(int numCol)getInt(String nomeCol)

Acede a uma coluna do tipo INT, ou equivalente, e devolve os seus conteúdos em formato Int.

Tabela 20: Alguns métodos para aceder aos dados de uma linha da tabela de dados

Para aceder a uma coluna de uma linha, utilizamos um destes métodos

Prof. Herberto Graça Página 92 de 217

Page 93: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

getXxx() passando-lhe como argumento o número da coluna do resultado (deacordo com a consulta SQL e não com a definição da BD), ou o nome da colunaa que queremos aceder.

Assim, para aceder as dados de uma linha poderíamos usar as seguintesinstruções:

int coluna1 = rs.getInt("id"); // ou rs.getString(1); String coluna2 = rs.getString("nome"); // ou rs.getString(2); String coluna3 = rs.getString("categoria"); // ou rs.getString(3); System.out.println(coluna1+' '+coluna2+' '+coluna3);

Para aceder a toda a tabela resultado, basta colocarmos o código anteriordentro de um ciclo:

int coluna1;String coluna2;String coluna3;

while (rs.next()){coluna1 = rs.getInt("id"); // ou rs.getString(1); coluna2 = rs.getString("nome"); // ou rs.getString(2); coluna3 = rs.getString("categoria"); // ou rs.getString(3); System.out.println(coluna1+' '+coluna2+' '+coluna3);

}

Para verificarmos se um determinado valor extraído da tabela resultado énull, utilizamos o método wasNull():

String nome = rs.getString ("nome");if (rs.wasNull()){

nome = "(não existe um nome)";}

11.7 Actualização de dados na base de dados

A modificação de dados numa base de dados, pode ser realizada de duasmaneiras:

1. Utilizando DML (Update), que é enviado para o SGBD utilizando ométodo executeUpdate, como já vimos anteriormente;

2. Utilizando os métodos disponibilizados pelo JDBC, na classeResultSet.

O primeiro método de actualização de dados é relativamente simples eresume-se a conceitos explicados anteriormente.

O segundo modo de actualização de dados é composto por duas fazes:

1. Definição dos dados a ser colocados na base de dados;

2. As alterações são efectuadas em toda a linha.

Para utilizarmos este modo de actualização de dados, necessitamos de umobjecto ResultSet que seja possível actualizar, portanto quando criamos orespectivo objecto Statement passamos o argumento ResultSet.CONCUR_UPDATABLEao método createStatement da nossa ligação, como exemplificado de seguida:

Statement s = con.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

ResultSet rs = s.executeQuery ("SELECT id, nome, categoria FROM animal");

Após o código acima teremos um objecto ResultSet, que poderá serutilizado para alterar os dados na base de dados.

Assim, por exemplo, se quisermos colocar o valor “mamifero” em todas as

Prof. Herberto Graça Página 93 de 217

Page 94: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

linhas de dados da coluna “category” da tabela “animal”, do exemplo anterior,poderíamos utilizar o seguinte código:

while (rs.next()){// modifica os dados apenas no objecto ResultSetrs.updateString("categoria", "mamífero");rs.updateRow(); // modifica os dados na base de dados

}

Após a alteração na base de dados, se o objecto ResultSet for de tipoTYPE_SCROLL_SENSITIVE, quando voltarmos a aceder aos dados já estaremos aaceder aos dados actualizados, sem ser necessário voltar a fazer uma consultaà base de dados.

Neste âmbito os métodos relevantes, num objecto ResultSet, são osseguintes:

Método DescriçãoupdateString(int numCol, String x)updateString(String nomeCol, String x)

updateInt(int numCol, Int x)updateInt(String nomeCol, int x)

...

Métodos para definir os dados a serem colocados na base de dados. Após esta instrução os dados são colocados no objecto ResultSet, mas não na base de dados.

updateRow()Efectua as alterações, definidas antes,na base de dados.

cancelUpdates()

Este método pode ser chamado após usar um método updateXxx(), para voltar a colocar no ResultSet os dados originais.

Tabela 21: Métodos relevantes na actualização de dados da base de dados

11.8 Tratamento de erros

Se quisermos fazer o tratamento de erros que possam ocorrer ao aceder auma base de dados, devemos colocar o nosso código num blocotry­catch­finally para “apanhar” o erro (exception) e devolver uma mensagemde erro.

O JDBC disponibiliza os métodos getMessage() e getErrorCode() para acederà mensagem de erro e ao seu código correspondente. Vejamos o exemploseguinte, em que enviamos à base de dados uma consulta inválida:

try{Statement s = con.createStatement ();s.executeQuery ("XYZ"); // consulta invalidas.close ();

} catch (SQLException e) {System.err.println ("Error message: " + e.getMessage ());System.err.println ("Error number: " + e.getErrorCode ());// aqui o mais correcto é utilizar um método de log

}

Aqui, o erro é apanhado no bloco try e é tratado no bloco catch, enviandouma mensagem para a consola com a mensagem de erro e o respectivocódigo, que foram devolvidos pelo SGBD.

No entanto, na realidade no bloco catch deve-se utilizar um método log,para enviar a mensagem de erro. Este método log, poder ser algo muitosimples que apenas envie uma mensagem de erro para a consola, ou algo maiscomplexo como escrever a mensagem de erro num ficheiro, ou enviar um

Prof. Herberto Graça Página 94 de 217

Page 95: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

email. Aqui fica um exemplo de um método log simples, que recebe umamensagem de erro definida pelo programador e a exception, e escreve naconsola a mensagem de erro definida pelo programador, mais as váriasinformações sobre o erro, que nos são dadas pelo sistema:

private static void log(String msg, Exception e){ System.out.println(msg); if (e!=null){ System.out.println(e);

System.err.println ("Messagem de erro: " + e.getMessage ());System.err.println ("Número do erro: " + e.getErrorCode ());

e.printStackTrace(); }}

11.9 Prepared Statements

Quando é realizada uma consulta à base de dados, esse código SQL écompilado e, somente depois, executado. Portanto o SGBD perde algum tempoa compilar o código, no entanto quando é necessário fazer a mesma consulta àbase de dados várias vezes podemos criar uma consulta SQL que o SGBDcompilará e guardará para que não seja necessário voltar a compilar quando serepetir a consulta.

É ainda relevante salientar que quando repetimos uma consulta váriasvezes, geralmente o fazemos com dados diferentes, por exemplo, uma mesmaconsulta de inserção de dados, mas com dados diferentes. Também para estecaso existe uma solução, como veremos adiante.

Para aplicar esta tecnologia vamos utilizar a classe PreparedStatement e ométodo prepareStatement, do objecto do tipo Connection, que é a nossa ligaçãocom a base de dados.

PreparedStatement psttmt;psttmt = con.prepareStatement ("INSERT INTO animal (nome, categoria) VALUES(?,?)");psttmt.setString (1, "tome");psttmt.setString (2, "mamifero");int count = psttmt.executeUpdate ();psttmt.close ();System.out.println ("Foram inseridas " + count + " linhas.");

Na consulta do exemplo anterior, os caracteres “?” assinalam o local ondeo objecto psttmt (PreparedStatement) irá colocar os dados que lhe serão indicadosnas duas linhas seguintes. No referido exemplo, ambos os dados são do tipoString, portanto utiliza-se o método setString, mas existem outros métodos,como o setInt ou setFloat, que devem ser utilizados consoante o tipo de dadosa colocar no objecto PreparedStatement.

Quando executamos uma consulta várias vezes a uma base de dados, estaserá colocada dentro de um ciclo, como no seguinte exemplo:

String updateString = "update COFFEES set SALES = ? where COF_NAME like ?";PreparedStatement updateSales = con.prepareStatement(updateString);int [] salesForWeek = {175, 150, 60, 155, 90};String [] coffees = {"Colombian", "French_Roast", "Espresso", "Colombian_Decaf", "French_Roast_Decaf"};int len = coffees.length;

for(int i=0; i<len; i++) {updateSales.setInt(1, salesForWeek[i]);updateSales.setString(2, coffees[i]);updateSales.executeUpdate();

}

Repare-se que a consulta é criada fora do ciclo. Dentro do ciclo apenas se

Prof. Herberto Graça Página 95 de 217

Page 96: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

indica os dados a inserir e se dá a instrução de execução.

11.10 Transactions

Suponhamos que vamos fazer um pagamento, através de transferênciabancária. Uma transferência bancária, ao nível da base de dados, implica duasoperações:

1. Retirar dinheiro de uma conta;

2. Colocar dinheiro noutra conta.

Ora, se após a primeira operação houver uma falha técnica, por exemplouma falha de energia, então isso quer dizer que foi retirado dinheiro da nossaconta, mas não chegou a ser depositado na outra conta e portanto ficámossem o dinheiro mas o pagamento não foi realizado! A integridade dos dadosficou comprometida!

A técnica chamada de transactions vem colmatar este tipo de problemasgarantindo que, das duas uma: ou se realizam ambas as operações, ou não serealiza nenhuma.

Na realidade, sempre que realizamos uma consulta a uma base de dados,estamos a utilizar esta técnica, mas apenas com uma instrução.

Esta técnica também impede que vários utilizadores acedam aos mesmosdados simultaneamente, bloqueando-os, evitando que um utilizador modifique(ou simplesmente aceda) a dados que outro utilizador está a modificar, o quepoderia resultar em falhas na integridade dos dados.

11.10.1 Realização uma transactionO commit é a acção que concretiza uma consulta a uma base de dados.

Por defeito, o commit é realizado automaticamente, quando executamos umaconsulta, para que não tenhamos de nos preocupar com mais esta instrução.

A preparação de uma transaction começa com a desactivação doauto-commit, segue-se a definição das alterações ou consultas quepretendemos realizar na base de dados, tal como o faríamos num contextonormal, e finalmente, quando tudo tiver sido definido, realizamos o commit,chamando o método commit, do objecto com a ligação à base de dados. Apósrealizarmos o commit, devemos sempre reactivar o auto-commit, de modo queo JDBC volte ao seu funcionamento por defeito.

Vejamos o seguinte exemplo:

con.setAutoCommit(false);

PreparedStatement updateSales = con.prepareStatement( "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");updateSales.setInt(1, 50);updateSales.setString(2, "Colombian");updateSales.executeUpdate();

PreparedStatement updateTotal = con.prepareStatement( "UPDATE COFFEES SET TOTAL = TOTAL + ? WHERE COF_NAME LIKE ?");updateTotal.setInt(1, 50);updateTotal.setString(2, "Colombian");updateTotal.executeUpdate();

Prof. Herberto Graça Página 96 de 217

Page 97: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

con.commit();

con.setAutoCommit(true);

11.10.2 Criação de um ponto de restauroUm ponto de restauro é uma pequena cópia de segurança das alterações

que são realizadas numa transaction, que poderá ser chamado, repondo atransaction ao estado em que estava quando o ponto de restauro foi criado.

Statement stmt = con.createStatement();int rows = stmt.executeUpdate("INSERT INTO tab1 (col1) VALUES (?primeiro?)");// cria o ponto de restauro:Savepoint svpt1 = con.setSavepoint("SAVEPOINT_1");rows = stmt.executeUpdate("INSERT INTO tab1 (col1) VALUES (?segundo?)");//...con.rollback(svpt1);//...con.commit();

O exemplo anterior insere uma linha de dados na tabela tab1, cria umponto de restauro (SavePoint) e insere outra linha de dados na mesma tabela.Mais tarde, chama o método rollback, para devolver a tabela ao ponto derestauro criado. Assim, após o retorno ao ponto de restauro, a tabela terá osdados inseridos na primeira inserção mas não terá os dados que foraminseridos na segunda inserção.

Para destruirmos um ponto de restauro utilizamos o métodoreleaseSavepoint, da classe Connection. Todos os pontos de restauro criadosserão destruídos quando se realizar o commit de uma transaction. Quandochamamos um ponto de restauro, também iremos destruir todos pontos derestauro que tinham sido criados entretanto.

11.10.2.1 Quando fazer um rollback

Um rollback (chamar um ponto de restauro para retornar a um estadoanterior) deve ser chamado na parte catch de um bloco try­catch­finally,quando na parte do try está a a preparação de uma transaction. Assim, seocorrer algum erro na criação da transaction, poderemos voltar a um pontoanterior, no qual saberemos exactamente o que foi realizado na transaction.

11.11 Stored Procedures

Um stored procedure é um conjunto de instruções SQL, DML ou DDL, querealizam uma determinada tarefa, e que residem no SGBD, pré-compiladas eprontas a usar. No fundo, um stored procedure, funciona como uma função dopróprio SGBD que pode ser chamada e executada.

Geralmente os stored procedures são unidades de código bastantecomplexas, e que portanto beneficiam mais por estarem directamente noSGBD, mas vamos ver de seguida alguns exemplos simples, para percebercomo funcionam.

11.11.1 Criação de stored procedures 11.11.1.1 Criação de stored procedures directamente no MySQL

O código seguinte cria um stored procedure em MySQL:

Prof. Herberto Graça Página 97 de 217

Page 98: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

DELIMITER // CREATE PROCEDURE GetAllProducts() BEGIN

SELECT * FROM products; END //

DELIMITER ;

No exemplo acima, começamos por mudar o delimitador de instruções,que separa uma consulta de outra, do caracter “;” para a expressão “//”.Fazemos isto para que possamos criar várias consultas, separadas por “;”,dentro do mesmo stored procedure. Após o final do stored procedure, voltamosa definir o delimitador de instruções como sendo o caracter “;”.

11.11.1.2 Criação de stored procedures através de JDBC

Para criar o stored procedure anterior através do JDBC, iríamos usar ométodo executeUpdate de um objecto da classe Statement, sem ser necessárioalterar os delimitadores, por exemplo:

String createProcedure= "CREATE PROCEDURE GetAllProducts()" +"BEGIN" +

"SELECT * FROM products;" +"END";

Statement stmt = con.createStatement(); //criação do objecto Statementstmt.executeUpdate(createProcedure); //criação do stored procedure no SGBD

11.11.2 Execução de stored procedures 11.11.2.1 Execução de stored procedures directamente no

MySQL

O código seguinte executa um stored procedure em MySQL:

CALL GetAllProducts();

Prof. Herberto Graça Página 98 de 217

Page 99: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

11.11.2.2 Execução de stored procedures por JDBC

O código seguinte executa um stored procedure através do JDBC:

CallableStatement cs = con.prepareCall("{CALL GetAllProducts()}");//prepara a execuçãoResultSet rs = cs.executeQuery(); //executa o stored procedure

Para executar um stored procedure podemos usar três métodos diferentes,presentes na classe CallableStatement, de acordo com as características dorespectivo stored procedure:

Método Descrição

executeQueryUtilizado quando a consulta devolve apenas um ResultSet. (SQL)

executeUpdateUtilizado quando a consulta altera os dados ou as tabelas da base de dados. (DML ou DDL)

executeUtilizado quando o stored procedure tem mais que uma consulta e portanto devolve mais que um ResultSet.

Tabela 22: Métodos disponíveis, na classe CallableStatement, para executar storedprocedures

11.11.3 Parâmetros nos stored proceduresOs stored procedures podem ter parâmetros de entrada (IN), de saída

(OUT) ou de entrada e saída (INOUT). Portanto, também os objectos da classeCallableStatement, podem ter parâmetros.

Tipos de parâmetros Descrição

IN

É o tipo de parâmetro, por defeito.Indica um tipo de parâmetro que pode ser passado para o stored procedure, mas se o seu valor for alterado nostored procedure, fora do procedimento continuará a ter o mesmo valor. (Passagem de parâmetro por valor)

OUT

O seu valor de entrada é assumido sempre como sendo NULL. Serve para ser alterado dentro do stored procedure e manter esse valor fora do stored procedure.

INOUT

É a combinação dos outros dois tipos. Serve para enviar dados para um stored procedure e quando houver alterações, elas serão visíveis fora do stored procedure. (Passagem de parâmetro por referência)

Tabela 23: Tipos de parâmetros possíveis nos stored procedures

Prof. Herberto Graça Página 99 de 217

Page 100: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

11.11.3.1 Parâmetros num stored procedure, em MySQL

Um stored procedure com parâmetros, em MySQL, é definido da seguinteforma:

DELIMITER //CREATE PROCEDURE GetOfficeByCountry(IN countryName VARCHAR(255))BEGIN

SELECT city, phone FROM officesWHERE country = countryName;

END //DELIMITER ;

Este stored procedure seria posteriormente chamado da seguinte forma:

CALL GetOfficeByCountry('Portugal');

Um stored procedure com vários parâmetros seria, por exemplo:

DELIMITER $$CREATE PROCEDURE CountOrderByStatus(IN orderStatus VARCHAR(25),OUT total INT)BEGIN

SELECT count(orderNumber) INTO total /* Atribuímos o resultado à */ FROM orders /* variável total */WHERE status = orderStatus; /* A selecção é realizada dependendo */

END$$ /* da variável de entrada orderStatus*/DELIMITER ;

Este stored procedure seria posteriormente chamado da seguinte forma:

DECLARE total_count INT DEFAULT 0 /* declara a variável total_count */SET total_count = 10; /* atribui o valor 10 à variável total_count */

CALL CountOrderByStatus('Shipped',@total); /* Pesquisa as que foram enviadas */SELECT @total AS total_shipped;

CALL CountOrderByStatus('in process',@total);/* Pesquisa as que estão em processo*/SELECT @total AS total_in_process;

11.11.3.2 Parâmetros num stored procedure, em JDBC

Um stored procedure com vários parâmetros seria criado, usando JDBC,como no seguinte exemplo:

String createProcedure= "CREATE PROCEDURE CountOrderByStatus( " +"IN orderStatus VARCHAR(25),OUT total INT) " +

"BEGIN " +"SELECT count(orderNumber) INTO total " +"FROM orders " +"WHERE status = orderStatus; " +

"END";

Statement stmt = con.createStatement(); //criação do objecto Statementstmt.executeUpdate(createProcedure); //criação do stored procedure no SGBD

Prof. Herberto Graça Página 100 de 217

Page 101: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

O exemplo anterior seria executado em JAVA, com o seguinte código:

CallableStatement cstmt = con.prepareCall("{CALL CountOrderByStatus(?, ?)}");

cstmt.setString(1, “Shipped”);cstmt.registerOutParameter(2, java.sql.Types.INT);

ResultSet rs = cstmt.executeQuery(); //executa o stored procedure

int x = cstmt.getINT(2);

// ...// Se a consulta devolve um ResultSet, aqui podemos aceder a esses dados usando// os métodos rs.getXxx()// ...

cstmt.setString(1, “in process”);cstmt.registerOutParameter(2, java.sql.Types.INT);

ResultSet rs = cstmt.executeQuery(); //executa o stored procedure

int y = cstmt.getINT(2);

11.11.4 Outras fontes de informação• Tutorial MySQL Stored Procedures :

◦ http://www.mysqltutorial.org/mysql-stored-procedure-tutorial.aspx

• Tutorial JDBC/MySQL Stored Procedures :

◦ http://book.opensourceproject.org.cn/lamp/mysql/mysqlstored/index.

html?page=opensource/0596100892/mysqlspp-chp-14-sect-2.html

• Manuais de Derby (de iniciação, de referencia e dedesenvolvimento):

◦ http://db.apache.org/derby/manuals/index.html

11.12 Exercícios

1) No projecto Agenda (criado num capítulo anterior) cria um novopacote chamado “BD”. Nesse novo pacote deverás criar um classepara que a agenda utilize uma base de dados para guardar os seusdados. Após esta classe estar criada deverás fazer as devidasalterações no GUI do projecto, de modo a que a agenda utilize a BDpara guardar os seus dados. A classe a criar deverá ser capaz derealizar as seguintes acções:

a) Criar uma ligação à BD (no construtor);

b) Verificar se todas as tabelas necessárias existem;

c) Criar as tabelas da BD;

d) Inserir os dados de um dia, na BD;

e) Devolver os dados de um dia;

f) Eliminar os dados de um determinado dia existente na BD;

Prof. Herberto Graça Página 101 de 217

Page 102: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

g) Alterar os dados de um determinado dia existente na BD.

2) No projecto Guestbook (criado num capítulo anterior) cria um novopacote chamado “BD”. Nesse novo pacote deverás criar um classepara que o guestbook utilize uma base de dados para guardar osseus dados. Após esta classe estar criada deverás fazer as devidasalterações no GUI do projecto, de modo a que o guestbook utilize aBD para guardar os seus dados. A classe a criar deverá ser capaz derealizar as seguintes acções:

a) Criar uma ligação à BD (no construtor);

b) Verificar se todas as tabelas necessárias existem;

c) Criar as tabelas da BD;

d) Inserir os dados na BD;

e) Devolver os dados da BD;

f) Eliminar os dados de um determinado comentário existente naBD;

g) Alterar os dados de um determinado comentário existente naBD.

3) No projecto Forum (criado num capítulo anterior) cria um novopacote chamado “BD”. Nesse novo pacote deverás criar um classepara que o fórum utilize uma base de dados para guardar os seusdados. Após esta classe estar criada deverás fazer as devidasalterações no GUI do projecto, de modo a que o fórum utilize a BDpara guardar os seus dados. A classe a criar deverá ser capaz derealizar as seguintes acções:

a) Criar uma ligação à BD (no construtor);

b) Verificar se todas as tabelas necessárias existem;

c) Criar as tabelas da BD;

d) Inserir os dados na BD;

e) Devolver os dados da BD;

f) Eliminar os dados de um determinado comentário existente naBD;

g) Alterar os dados de um determinado comentário existente naBD.

4) Crie um programa que copie uma base de dados num SGBD MySQLpara um SGBD Derby.

a) Crie uma nova versão do programa que criou, de forma queseja possível escolher se queremos passar de MySQL paraDerby ou em direcção oposta.

5) No projecto Adamastor (criado num capítulo anterior) cria um novopacote chamado “BD”. Nesse novo pacote deverás criar uma classepara que o software utilize uma base de dados para guardar os seus

Prof. Herberto Graça Página 102 de 217

Page 103: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

dados. Após esta classe estar criada deverás fazer as devidasalterações no CLI e no GUI do projecto, de modo a que o programautilize a BD para guardar os seus dados. A classe a criar deverá teras seguintes características e testar todas as suas funcionalidades,realizando output na consola.

a) Link para a documentação de especificações da BD:https://docs.google.com/uc?id=0B5A59Hr_XNq6ODBmODRkMjgtNTI0Ni00MzNmLWJhZTYtNWUzNWNiZmVjNDl

j&export=download&authkey=CJStwNsF&hl=en

b) Criar a base de dados;

• O diagrama ER da BD chama-se"Adamastor_ERD-MySQL.pdf";

◦ O código DDL encontra-se num ficheiro de nome"Adamastor_DDL-Derby.sql" (poderá sernecessário alterar este código, consoante o tipode BD utilizada);

• No final da criação de cada tabela, deverá ser enviadauma msg para a consola;

• Deverá ser criada uma função privada para cadatabela;

• Deverá ser criada uma função privada para asalterações finais;

• Deverá ser criada uma função pública para a criação detodas as tabelas;

c) Inserir os dados nas tabelas da BD;

• Os dados que devem ser introduzidos nas tabelasencontram-se nos ficheiros "csv";

• Os dados de cada coluna estão separados por ";";

• Os ficheiros com os dados não podem ser alterados;

• Poderão criar uma função que abra o ficheiro, e leia osseus conteúdos para um array, ignorando a 1ª linha(cabeçalhos), e colocando cada coluna de dados numacoluna do array;

• No final da inserção dos dados de cada tabela, deveráser enviada uma msg para a consola;

• Deverá ser criada uma função privada para cadatabela;

• Deverá ser criada uma função pública para a criação detodas as tabelas;

d) Uma função para cada uma das seguintes pesquisas de dados(poderá ser necessário realizar alterações neste código,dependendo da BD);

Prof. Herberto Graça Página 103 de 217

Page 104: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• Consulta encomendas:

SELECT Encomendas.CódigoDaEncomenda, Encomendas.CódigoDoCliente, Encomendas.CódigoDoEmpregado, Encomendas.DataDaEncomenda, Encomendas.DataRequerida, Encomendas.DataDoEnvio, Encomendas.EnviarPor, Encomendas.Frete, Encomendas.NomeDoDestino, Encomendas.EndereçoDoDestino, Encomendas.CidadeDoDestino, Encomendas.RegiãoDoDestino, Encomendas.CódigoPostalDoDestino, Encomendas.PaísDoDestino, Clientes.NomeDaEmpresa, Clientes.Endereço, Clientes.Cidade, Clientes.Região, Clientes.CódigoPostal, Clientes.País FROM Clientes INNER JOIN Encomendas ON Clientes.CódigoDoCliente = Encomendas.CódigoDoCliente;

• Detalhes estendidos da encomenda:

SELECT [Detalhes da Encomenda].CódigoDaEncomenda, [Detalhes da Encomenda].CódigoDoProduto, Produtos.NomeDoProduto, [Detalhes da Encomenda].PreçoUnitário, [Detalhes da Encomenda].Quantidade, [Detalhes da Encomenda].Desconto, CCur([Detalhes da Encomenda].PreçoUnitário*[Quantidade]*(1-[Desconto])/100)*100 AS PreçoExtendidoFROM Produtos INNER JOIN [Detalhes da Encomenda] ON Produtos.CódigoDoProduto =[Detalhes da Encomenda].CódigoDoProdutoORDER BY [Detalhes da Encomenda].CódigoDaEncomenda;

• Encomendas trimestrais

SELECT DISTINCT Clientes.CódigoDoCliente, Clientes.NomeDaEmpresa, Clientes.Cidade, Clientes.PaísFROM Clientes INNER JOIN Encomendas ON Clientes.CódigoDoCliente = Encomendas.CódigoDoClienteWHERE (((Encomendas.DataDaEncomenda) Between #1/1/1997# And #12/31/1997#));

• Facturas

SELECT Encomendas.NomeDoDestino, Encomendas.EndereçoDoDestino, Encomendas.CidadeDoDestino, Encomendas.RegiãoDoDestino, Encomendas.CódigoPostalDoDestino,Encomendas.PaísDoDestino, Encomendas.CódigoDoCliente, Clientes.NomeDaEmpresa, Clientes.Endereço, Clientes.Cidade, Clientes.Região, Clientes.CódigoPostal, Clientes.País, [Nome] & " " & [Apelido] AS Vendedor, Encomendas.CódigoDaEncomenda, Encomendas.DataDaEncomenda, Encomendas.DataRequerida, Encomendas.DataDoEnvio, Transitários.NomeDaEmpresa, [Detalhes da Encomenda].CódigoDoProduto, Produtos.NomeDoProduto, [Detalhes da Encomenda].PreçoUnitário, [Detalhes da Encomenda].Quantidade, [Detalhes da Encomenda].Desconto, CCur([Detalhes da Encomenda].PreçoUnitário*[Quantidade]*(1-[Desconto])/100)*100 AS PreçoExtendido, Encomendas.FreteFROM Transitários INNER JOIN (Produtos INNER JOIN ((Empregados INNER JOIN (Clientes INNERJOIN Encomendas ON Clientes.CódigoDoCliente = Encomendas.CódigoDoCliente) ON Empregados.CódigoDoEmpregado = Encomendas.CódigoDoEmpregado) INNER JOIN [Detalhes da Encomenda] ON Encomendas.CódigoDaEncomenda = [Detalhes da Encomenda].CódigoDaEncomenda) ON Produtos.CódigoDoProduto = [Detalhes da Encomenda].CódigoDoProduto) ON Transitários.CódigoDoTransitário = Encomendas.EnviarPor;

• Filtro das Facturas

SELECT Facturas.*FROM FacturasWHERE (((Facturas.CódigoDaEncomenda)=[forms]![encomendas]![CódigoDaEncomenda]));

• Lista Alfabética dos Produtos

SELECT Produtos.*, Categorias.NomeDaCategoriaFROM Categorias INNER JOIN Produtos ON Categorias.CódigoDaCategoria = Produtos.CódigoDaCategoriaWHERE (((Produtos.Descontinuado)=No));

• Lista dos Produtos Actuais

SELECT Produtos.CódigoDoProduto, Produtos.NomeDoProdutoFROM ProdutosWHERE (((Produtos.Descontinuado)=No))ORDER BY Produtos.NomeDoProduto;

• Os Dez Produtos Mais Caros

SELECT TOP 10 Produtos.NomeDoProduto AS DezProdutosMaisCaros, Produtos.PreçoUnitárioFROM ProdutosORDER BY Produtos.PreçoUnitário DESC;

• Produtos Acima do Preço Médio

Prof. Herberto Graça Página 104 de 217

Page 105: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVASELECT Produtos.NomeDoProduto, Produtos.PreçoUnitárioFROM ProdutosWHERE (((Produtos.PreçoUnitário)>(SELECT AVG([PreçoUnitário]) From Produtos)))ORDER BY Produtos.PreçoUnitário DESC;

• Produtos por Categoria

SELECT Categorias.NomeDaCategoria, Produtos.NomeDoProduto, Produtos.QuantidadePorUnidade,Produtos.Existências, Produtos.DescontinuadoFROM Categorias INNER JOIN Produtos ON Categorias.CódigoDaCategoria = Produtos.CódigoDaCategoriaWHERE (((Produtos.Descontinuado)<>Yes))ORDER BY Categorias.NomeDaCategoria, Produtos.NomeDoProduto;

• Subtotais da Encomenda

SELECT [Detalhes da Encomenda].CódigoDaEncomenda, Sum(CCur([PreçoUnitário]*[Quantidade]*(1-[Desconto])/100)*100) AS SubtotalFROM [Detalhes da Encomenda]GROUP BY [Detalhes da Encomenda].CódigoDaEncomenda;

• Vendas dos Empregados por País

PARAMETERS [Data início] DateTime, [Data fim] DateTime;SELECT Empregados.País, Empregados.Apelido, Empregados.Nome, Encomendas.DataDoEnvio, Encomendas.CódigoDaEncomenda, [Subtotais da Encomenda].Subtotal AS ValorDaVendaFROM Empregados INNER JOIN (Encomendas INNER JOIN [Subtotais da Encomenda] ON Encomendas.CódigoDaEncomenda = [Subtotais da Encomenda].CódigoDaEncomenda) ON Empregados.CódigoDoEmpregado = Encomendas.CódigoDoEmpregadoWHERE (((Encomendas.DataDoEnvio) Between [Data início] And [Data fim]));

• Vendas dos Produtos em 1997

SELECT Categorias.NomeDaCategoria, Produtos.NomeDoProduto, Sum(CCur([Detalhes da Encomenda].PreçoUnitário*[Quantidade]*(1-[Desconto])/100)*100) AS VendasDoProduto, "Tri "& DatePart("q",[DataDoEnvio]) AS [Trimestre do envio]FROM (Categorias INNER JOIN Produtos ON Categorias.CódigoDaCategoria = Produtos.CódigoDaCategoria) INNER JOIN (Encomendas INNER JOIN [Detalhes da Encomenda] ON Encomendas.CódigoDaEncomenda = [Detalhes da Encomenda].CódigoDaEncomenda) ON Produtos.CódigoDoProduto = [Detalhes da Encomenda].CódigoDoProdutoWHERE (((Encomendas.DataDoEnvio) Between #1/1/1997# And #12/31/1997#))GROUP BY Categorias.NomeDaCategoria, Produtos.NomeDoProduto, "Tri " & DatePart("q",[DataDoEnvio]);

• Vendas por Ano

PARAMETERS [Forms]![Diálogo das Vendas por Ano]![DataInício] DateTime, [Forms]![Diálogo das Vendas por Ano]![DataFim] DateTime;SELECT Encomendas.DataDoEnvio, Encomendas.CódigoDaEncomenda, [Subtotais da Encomenda].Subtotal, Format([DataDoEnvio],"yyyy") AS AnoFROM Encomendas INNER JOIN [Subtotais da Encomenda] ON Encomendas.CódigoDaEncomenda=[Subtotais da Encomenda].CódigoDaEncomendaWHERE (((Encomendas.DataDoEnvio) Is Not Null And (Encomendas.DataDoEnvio) Between Forms![Diálogo das vendas por ano]!DataInício And Forms![Diálogo das vendas por ano]!DataFim));

• Vendas por Categoria

SELECT Categorias.CódigoDaCategoria, Categorias.NomeDaCategoria, Produtos.NomeDoProduto, Sum([Detalhes Extendidos da Encomenda].PreçoExtendido) AS VendasDoProdutoFROM Categorias INNER JOIN (Produtos INNER JOIN (Encomendas INNER JOIN [Detalhes Extendidos da Encomenda] ON Encomendas.CódigoDaEncomenda = [Detalhes Extendidos da Encomenda].CódigoDaEncomenda) ON Produtos.CódigoDoProduto = [Detalhes Extendidos da Encomenda].CódigoDoProduto) ON Categorias.CódigoDaCategoria = Produtos.CódigoDaCategoriaWHERE (((Encomendas.DataDaEncomenda) Between #1/1/1997# And #12/31/1997#))GROUP BY Categorias.CódigoDaCategoria, Categorias.NomeDaCategoria, Produtos.NomeDoProduto;

• Vendas por Categoria em 1997

SELECT [Vendas dos Produtos em 1997].NomeDaCategoria, Sum([Vendas dos Produtos em 1997].VendasDoProduto) AS VendasPorCategoriaFROM [Vendas dos Produtos em 1997]GROUP BY [Vendas dos Produtos em 1997].NomeDaCategoria;

• Encomendas Trimestrais por Produto

TRANSFORM Sum(CCur([Detalhes da Encomenda].PreçoUnitário*[Quantidade]*(1-[Desconto])/100)*100) AS ValorSELECT Produtos.NomeDoProduto, Encomendas.CódigoDoCliente, Year([DataDaEncomenda]) AS AnoDaEncomendaFROM Produtos INNER JOIN (Encomendas INNER JOIN [Detalhes da Encomenda] ON Encomendas.CódigoDaEncomenda = [Detalhes da Encomenda].CódigoDaEncomenda) ON Produtos.CódigoDoProduto = [Detalhes da Encomenda].CódigoDoProdutoWHERE (((Encomendas.DataDaEncomenda) Between #1/1/1997# And #12/31/1997#))GROUP BY Produtos.NomeDoProduto, Encomendas.CódigoDoCliente, Year([DataDaEncomenda])

Prof. Herberto Graça Página 105 de 217

Page 106: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVAPIVOT "Trimestre " & DatePart("q",[DataDaEncomenda],1,0) In ("Trimestre 1","Trimestre 2","Trimestre 3","Trimestre 4");

• Clientes e Fornecedores por Cidade

SELECT Cidade, NomeDaEmpresa, NomeDoContacto, "Clientes" AS [Relacionamento] FROM ClientesUNION SELECT Cidade, NomeDaEmpresa, NomeDoContacto, "Fornecedores"FROM FornecedoresORDER BY Cidade, NomeDaEmpresa;

Prof. Herberto Graça Página 106 de 217

Page 107: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

12 Relatórios

Um relatório é apenas um documento preparado para impressão. Isto é,quando falamos em relatórios, falamos num conjunto de dados organizados deforma a que seja possível imprimi-los. O conjunto de dados que são colocadosnum relatório podem provir de várias fontes, por exemplo, uma base de dados,uma folha de cálculo, um ficheiro XML ou um ficheiro CSV.

12.1 Ferramentas a utilizar

Existem várias ferramentas que se podem utilizar para realizar relatórios,e essas ferramentas são relativamente independentes do restante softwareque utilizamos para fazer uma aplicação. Daqui resulta que um relatório éconstruído com uma determinada ferramenta, tendo como resultado final umdocumento independente que depois será chamado por uma outra aplicação, aaplicação que nós criamos.

Uma das ferramentas mais utilizadas para criar relatórios chama-seCrystal Reports, que é utilizado sobretudo por aplicações baseadas emtecnologias Microsoft (mas não apenas), no entanto trata-se de um softwareproprietário e portanto seria necessário pagar para utilizarmos Crystal Reportsnas aplicações que criamos.

O software que vamos utilizar para criar relatórios chama-se JasperReports, e é open source, pelo que o podemos utilizar e incorporar nas nossasaplicações sem qualquer tipo de restrição. Além disso, é inteiramente feito emJAVA, pelo que é o software de relatórios mais utilizado em aplicações feitas emJAVA.

Para utilizarmos Jasper Reports, vamos necessitar de dois componentes:

1. O software nuclear, o motor, que consiste na biblioteca que criaefectivamente os relatórios (Jasper Reports);

2. O software de desenho de relatórios, que é uma aplicação ondedesenhamos, formatamos e configuramos os relatórios e que utilizao Jasper Reports para posteriormente criar os relatórios. Tambémaqui temos várias opções disponíveis:

◦ Os mesmos criadores do Jasper Reports disponibilizam umeditor chamado iReport, em versões para Windows, Linuxe Mac. É este o software que utilizaremos para criar osrelatórios.

◦ Ainda pela mesma instituição, temos o pacote JasperStudio, que é uma versão do iReport em forma de pluginpara Eclipse e que pode ser instalado no Eclipse a partir doseguinte link de instalação:http://jasperstudio.sourceforge.net/updates/ No entantoneste momento este software está ainda numa fase alfa.

Prof. Herberto Graça Página 107 de 217

Page 108: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

◦ Outra solução muito interessante consiste num plugin paraEclipse que se chama Jasper Assistant, no entanto é dequalidade inferior ao iReport e a versão disponível online éapenas uma versão de avaliação e que deixa uma marca deágua em todas as páginas.

◦ Jasper Assistant: http://www.jasperassistant.com/index.html

◦ Instalação no Eclipse (Help → Install new software):

▪ Instalação do GEF (necessário para o Jasper Assistant):

Name: GEF update site

http://download.eclipse.org/tools/gef/updates/releases/

▪ Instalação do Jasper Assistant:

Name: JasperAssistant update site

URL: http://www.jasperassistant.com/updates/3.x/

12.2 Desenhar um relatório

12.2.1 Ligar a uma fonte de dadosPara podermos construir um relatório com os dados que existem numa

base de dados, teremos de conseguir aceder a essa BD a partir do iReport (ououtro software de relatórios).

No iReports podemos utilizar uma BD de duas formas:

• Acesso para consultar a sua estrutura e os seus dados;

• Acesso para criar um relatório.

12.2.1.1 Acesso para consultar a sua estrutura e os seus dados

Para conseguirmos aceder à BD dentro do iReport, teremos de seguir asseguintes instruções para os drivers "derby.jar" e "derbyclient.jar":

1. Driver JDBC (JAR) copiado paraC:\JasperReports\jasperserver-pro-3.5.1\ireport\ide8\modules\ext,junto aos JARs do MySQL e PostgreSQL;

2. No iReport ir a Window->Services. Clickar em Drivers, New Driver...3. Adicionar o driver JDBC (JAR);

De seguida podemos ligar à base de dados:

1. No painel de “Serviços” chamamos o menu de contexto do driverque pretendemos usar para ligar;

2. Colocamos os dados de ligação, tendo em atenção que:

◦ Caso pretendamos usar o driver embedded, teremos deespecificar todo o caminho até à pasta da base de dados;

◦ Caso pretendamos usar o driver de cliente/servidor,primeiro

Prof. Herberto Graça Página 108 de 217

Page 109: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

temos de iniciar o servidor;

◦ Exemplo de dados de ligação por cliente/servidor:

▪ jdbc:derby://localhost:1527/Adamastor;user=me;password=mine

12.2.1.2 Acesso para criar um relatório

Para conseguirmos aceder à BD dentro do iReport, de forma aconseguirmos criar um relatório teremos de seguir as seguintes instruções paraos drivers "derby.jar" e "derbyclient.jar":

1. No menu “tools > options”, seleccionamos o separador “Classpath”e o botão “Add JAR”;

2. Navegamos ao local onde temos os drivers e adicionamos-los aambos (atenção, os ficheiros não são copiados para uma localizaçãodo iReport, são utilizados directamente da localização onde seencontrarem, pelo que se forem apagados o iReport deixará de ospoder utilizar);

3. Seleccionamos o botão “Report Datasources”5, da barra deferramentas, e de seguida em “New”. Alternativamente podemosseleccionar o primeiro botão de “quick start”6;

4. Seleccionamos o tipo “Database JDBC Connection”;

5. Introduzimos um nome para a nova ligação aos dados, por exemplo“Adamastor”;

6. Em “JDBC Driver” colocamos o nome do driver:“org.apache.derby.jdbc.ClientDriver”;

7. Em “JDBC URL” colocamos o endereço da BD, por exemplo:“jdbc:derby://localhost:1527/Adamastor”;

8. Se for caso disso, colocamos também o nome de utilizador e a chavede acesso.

9. Seleccionamos “Test” para testar a ligação à BD.

10. Seleccionamos “Save”, para guardar a nova ligação.

12.2.2 Obter os dadosAntes de começar a criar um relatório vamos alterar uma configuração

geral do iReports. Para que os relatórios compilados possam ser chamados apartir de um programa JAVA, o iReports tem de ser configurado para utilizarlinguagem JAVA. Para fazer essa configuração basta ir ao menu “Tools >Options” e em “Language” escolher “Java”.

5

6

Prof. Herberto Graça Página 109 de 217

Page 110: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Para obter os dados e criar o relatório vamos usar sempre um modelo jáfeito, que dá uma base de trabalha já feita e nos permitirá alterar o relatórioposteriormente, de modo a se adequar às nossas necessidades. No entanto,também nos é disponibilizado um modelo vazio, que nos permite fazer umrelatório totalmente novo.

Para criar um novo relatório vamos seleccionar a opção de menu “File >New”, ou o segundo botão de “quick start”7, e seguir as seguintes instruções:

1. São-nos apresentados vários modelos de relatório (incluindo algunsrelatórios em branco). Neste exemplo vamos utilizar o modelo“Simple Blue” e clickar em “Launch Report Wizard”;

2. Neste painel vamos dar um nome ao nosso relatório, por exemplo“Categorias”, e escolher o local onde este será guardado. O localonde guardaremos o relatório deverá ser algures dentro do nossoprojecto de Eclipse. Clickamos em “Next”;

3. Nesta terceira fase iremos construir a pesquisa SQL que nos dará oscampos da BD que utilizaremos no relatório, ou seja os campos cujosdados queremos mostrar no relatório. Neste caso iremos introduzir oseguinte SQL: “SELECT   *   FROM   Categorias”. Alternativamentepoderemos clickar no botão “Design Query”, que nos levará a umutilitário que nos auxiliará na construção de uma pesquisa SQL.Clickamos em “Next”;

4. Agora vamos escolher quais os campos, daqueles que a pesquisaSQL nos disponibiliza, que iremos utilizar no nosso relatório.Escolhemos todos os campos e clickamos em “Next”;

5. Neste quinto painel poderemos fazer agrupamentos de dados. Nestecaso não faremos nenhum agrupamento. Clickamos em “Next”;

6. No último painel apenas clickamos em “Finish”.

Após concluir o utilitário anterior, o nosso relatório base está concluído.Agora, para ajustar o relatório às nossas necessidades, utilizaremos os paineis“Report Inspector”, “Palette” e “Properties”, localizados nas laterais do iReport.

O aspecto final do relatório será o seguinte, no modo de edição:

Ilustração 20: Relatório de categorias, em modo de edição

No modo de visualização o aspecto final do relatório deverá ser oseguinte:

7

Prof. Herberto Graça Página 110 de 217

Page 111: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Ilustração 21: Relatório de categorias, em modo de visualização

12.2.3 Zonas do relatórioUm relatório é semelhante a um documento de um processador de texto,

no entanto tem diferenças significativas.

Um relatório é composto por várias secções, que são faixas horizontaisonde colocamos determinados conteúdos (texto ou imagens) e que se poderãorepetir de umas páginas para as outras, ou não, consoante a secção de que setrate. Estas secções podem ser utilizadas num relatório, ou não.

Na tabela 24 encontram-se todos os tipos de secções existentes nosrelatórios de Jasper Reports, com a respectiva descrição.

Prof. Herberto Graça Página 111 de 217

Page 112: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Secção Descrição

TituloÉ a primeira secção de um relatório e é imprimido apenas uma vez.

Cabeçalho da página É imprimida em todas as páginas do relatório.

Cabeçalho das colunasÉ imprimida em todas as páginas, se existir uma secção de “Detalhes”. É utilizada para colocar os titulos das colunas de um relatório.

DetalhesNesta secção são imprimidas todas as linhas de dados deum relatório.

Rodapé das colunas

É imprimida em todas as páginas, se existir uma secção de “Detalhes”. Pode ser imprimida imediatamente abaixo da última linha de dados de cada página, ou no final decada página.

Rodapé da páginaÉ imprimida em todas as páginas, podendo não ser imprimida na última página do relatório. É ideal para se colocar o número das páginas.

Rodapé da última página É imprimida apenas na última página.

SumárioÉ imprimida apenas uma vez, no final do relatório. Podeser imprimida numa página isolada.

BackgroundServe para configurar o fundo das páginas. Por exemplo,pode-se colocar uma marca de água em todas as páginas do relatório.

No DataPode ser imprimida, caso não existam dados para colocarno relatório.

Tabela 24: Secções de um relatório

Para acrescentar ou eliminar secções de um relatório utiliza-se o menu decontexto da respectiva secção, no painel “Report Inspector”. Para alterarmosas suas características, como por exemplo a sua altura, seleccionamos asecção em causa e alteramos essas propriedades no painel “Properties”, queaparece no lado direito da janela do iReport.

12.2.4 Formatação de dadosPara formatar os vários componentes de um relatório, podemos fazê-lo

através de:

• Opção “Padding and Borders”, do menude contexto de um item. Disponibilizaopções para configurar as margens eas linhas à volta do item;

Ilustração 22: Painel “Padding and Borders”

• Opção “Field pattern”, do menu decontexto de um item de dados.Disponibiliza opções para formatar a

Prof. Herberto Graça Página 112 de 217

Page 113: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

aparência, de acordo com o tipo de dados, nomeadamente: Número;Data; Hora; Moeda; Percentagem; Notação cientifica; Outraformatação manual.

Ilustração 23: Painel “Field pattern”

• Através do painel de propriedades decada elemento, que está acessível nolado direito da janela do iReport,quando se selecciona um elemento dorelatório. Aqui são disponibilizadas asopções para formatar o texto, como otamanho e tipo de letra, a cor do texto,a cor de fundo da caixa, etc.

Ilustração 24: Painel “Properties”

12.2.5 Agrupamentos, sumarização e ordenação de dados

12.2.5.1 Agrupamentos

Vamos agora criar um novo relatório, mas com agrupamento de dados.Será um relatório dos produtos existentes, mas agrupados pela respectivacategoria.

Começamos por criar um relatório da mesma forma que criámos orelatório das categorias de produtos. No entanto, vamos utilizar o utilitário decriação de pesquisas SQL. Nesse utilitário, começamos por escolher o esquema“Scheme” onde estão as nossas tabelas. Da listagem de tabelas que aparecem,vamos escolher as tabelas “Produtos” e “Categorias”. Dessas tabelas vamosescolher os campos “código”, ”nome”, ”quantidade” e “preços” da tabela deprodutos, e o campo “nome” da tabela de categorias.

Depois disso, quando chegamos ao painel de agrupamentos vamosescolher como campo de agrupamento o campo “Categorias”.

Prof. Herberto Graça Página 113 de 217

Page 114: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

O relatório será criado com os dados agrupados pela respectiva categoria,no entanto terá um aspecto algo estranho. Vamos alterar o relatório de modo atorná-lo aceitável:

1. No painel “Report Inspector” vamos chamar o menu de contexto doitem “group header 1” e vamos adicionar mais uma secção “groupheader”;

2. Na secção que acabámos de criar vamos colocar cabeçalhos para ascolunas. Podemos até copiar as etiquetas existentes na secção decabeçalhos das colunas. Colocamos nas etiquetas os titulosseguintes: “Código”, ”Nome”, ”Quantidade” e “Preço”;

3. Agora vamos ajustar a largura das colunas de dados e respectivoscabeçalhos e alinhamos os preços à esquerda;

4. Vamos também mudar o conteúdo da etiqueta do “group header 1”para “Categoria:”, e alinhamos verticalmente ao centro;

5. Podemos eliminar a secção dos cabeçalhos das colunas (“columnheader”), pois não é necessária;

6. Mudamos a linha que se encontra na secção “group header 1” demodo a que fique por cima da designação da categoria;

7. Alteramos o título do cabeçalho para “Produtos por categoria”.Ajustamos a sua área e a sua localização;

8. Colocamos a seguinte descrição: “Listagem dos produtos, agrupadospela respectiva categoria”. Ajustamos a sua área e a sua localização.

No final, o relatório em modo de edição deverá ter o seguinte aspecto:

Ilustração 25: Relatório de produtos agrupados, em modo de edição

Em modo de visualização, o mesmo relatório, deverá ter o seguinteaspecto:

Prof. Herberto Graça Página 114 de 217

Page 115: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Ilustração 26: Relatório de produtos agrupados, em modo de visualização

12.2.5.2 Sumarização

A sumarização de conteúdos de um relatório é realizada numa secção desumário, que apenas é exibida no final do relatório, opcionalmente numapágina à parte.

Esta secção é utilizada, por exemplo, para inserir o total de uma factura,em que os custos parciais são somados, ou a contagem da quantidade deprodutos que existem em categoria de produtos.

12.2.5.3 Ordenação

A ordenação dos dados do relatório é realizada usando os comandos deSQL apropriados, na pesquisa realizada aquando da criação do relatório.

12.2.6 Imagens A inserção de imagens pode ser feita de três modos diferentes:

Prof. Herberto Graça Página 115 de 217

Page 116: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• Inserção de imagens estáticas;

• Inserção de imagens da base de dados;

• Inserção de imagens de fundo.

12.2.6.1 Inserção de imagens estáticas

Para inserir uma imagem estática, basta arrastarmos a ferramenta“Image” do painel “Palette” para a secção do formulário onde pretendemoscolocar a imagem.

De seguida aparece uma janela onde escolhemos qual a imagem a inserir.

12.2.6.2 Inserção de imagens da base de dados

Para inserir uma imagem que se encontra guardada num campo de umabase de dados começamos por seleccionar o campo da imagem, no painel“Report Inspector > Fields”. De seguida, no painel de propriedades escolhemoso tipo de dados “java.io.InputStream” para esse campo.

Após esses passos iniciais realizamos os mesmos passos que faríamos aoinserir uma imagem estática. No entanto, ao aparecer a janela de escolha daimagem, cancelamos.

Seleccionamos o item que acabámos de colocar no formulário e alteramosas suas propriedades:

• Em “Image Expression” colocamos o campo correspondente àimagem;

• Em “Expression Class” colocamos “java.io.InputStream”.

Ainda de referir que a propriedade “Scale Image” permite escolher o modocomo a imagem aparecerá no relatório.

12.2.6.3 Inserção de imagens de fundo

Começamos por activar a secção de “Background” e colocamos a suaaltura em 802.

Arrastamos a ferramenta de imagem para a secção de “Background”,seleccionamos a imagem e redimensionamos-la de modo a que ocupe toda aárea disponível. Além disso, na propriedade “Scale Image” seleccionamos omodo “Fill Frame”.

12.2.7 Gráficos e Mapas Os gráficos são essenciais em qualquer aplicação de gestão. Com

JasperReports/iReports, podem ser construídos gráficos circulares, de barras,de barras empilhadas, de linhas, de áreas, de áreas empilhadas, de dispersão,em bolha, de séries de tempo, de cotações, de termómetro, com múltiploseixos, e mapas de Gantt.

Vamos criar um gráfico circular que relacione as vendas de cadaempregado. Vamos seguir os seguintes passos:

1. Os gráficos são colocados dentro de uma secção de sumário. Então,vamos criar um relatório em branco, do qual eliminaremos todas as

Prof. Herberto Graça Página 116 de 217

Page 117: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

outras secções. Aumentamos o tamanho da secção de sumário, demodo a fazer um quadrado;

2. No painel “Report Inspector” chamamos o menu de contexto donosso relatório e seleccionamos “Edit Query”. Inserimos o seguintecódigo SQL, e fechamos a janela:

SELECT EMPREGADOS.CODIGODOEMPREGADO, EMPREGADOS.NOME, EMPREGADOS.APELIDO, VENDAS.VALORDAVENDA

FROM EMPREGADOS INNER JOIN ( 

SELECT EMPREGADOS.CODIGODOEMPREGADO, SUM((DETALHES_DA_ENCOMENDA.PRECOUNITARIO * DETALHES_DA_ENCOMENDA.QUANTIDADE) * (1 ­ DETALHES_DA_ENCOMENDA.DESCONTO / 100)) AS VALORDAVENDA

FROM EMPREGADOS INNER JOIN (ENCOMENDAS INNER JOIN DETALHES_DA_ENCOMENDA ON ENCOMENDAS.CODIGODAENCOMENDA = DETALHES_DA_ENCOMENDA.CODIGODAENCOMENDA) ON EMPREGADOS.CODIGODOEMPREGADO = ENCOMENDAS.CODIGODOEMPREGADO

GROUP BY EMPREGADOS.CODIGODOEMPREGADO ) AS VENDAS

ON EMPREGADOS.CODIGODOEMPREGADO = VENDAS.CODIGODOEMPREGADO

3. Do painel “Palette” arrastamos o item “Chart” para o relatório;

Prof. Herberto Graça Página 117 de 217

Page 118: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

4. É-nos mostrada uma janela onde poderemos escolher o tipo degráfico que pretendemos;

Ilustração 27: Escolha do tipo de gráfico

5. Após escolhermos o tipo de gráfico escolhemos o campo que vaiidentificar cada uma das parcelas do gráfico e o campo que será ovalor que a parcela representará. Neste exemplo esses camposserão o código do empregado e o calor da venda, respectivamente;

Ilustração 28: Escolha dos identificadores de cada fatia do gráfico

Prof. Herberto Graça Página 118 de 217

Page 119: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6. Depois de terminarmos o utilitário ajustamos o tamanho do gráficode modo a ocupar toda a área da secção de sumário;

Ilustração 29: Vista do gráfico, em modo de edição

7. Neste momento o gráfico já estará terminado, mas ainda faltaajustar algumas caracteristicas. Chamamos o menu de contexto dográfico, seleccionamos a opção “Chart Data” e configuramos comoexemplificado a baixo;

Ilustração 30: Colocação das etiquetas correctas no gráfico8

8. No painel de propriedades respeitante ao gráfico, vamos ainda

8 Devido a um bug no iReport as etiquetas não vão aparecer. Sugiro colocar a “Label expression” na “Keyexpression”.

Prof. Herberto Graça Página 119 de 217

Page 120: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

alterar algumas propriedades, nomeadamente o “Title Expression”, o“Title Font”, o Subtitle Expression” e o “Legend Position”, comodemonstrado na imagem seguinte;

Ilustração 31: Configuração das propriedades do gráfico

9. No final, o gráfico terá o aspecto seguinte:

Ilustração 32: Vista do gráfico final, em modo de visualização

Prof. Herberto Graça Página 120 de 217

Page 121: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

12.3 Relatórios dinâmicos

12.3.1 Fórmulas e variáveisPara criarmos relatórios com cálculos podemos utilizar duas metodologias:

1. Realizamos os cálculos directamente em SQL, e depois apenasutilizamos os dados resultantes no relatório;

2. Utilizamos uma pesquisa SQL simples, para nos dar os campos base,e realizamos os cálculos em Jasper Reports. É este o método queiremos utilizar aqui.

Agora vamos criar uma factura de uma encomenda:

1. Criamos um relatório com o modelo “Simple Blue”;

2. Escolhemos os campos PreçoUnitário, Quantidade e Desconto databela Detalhes_da_Encomenda, e o campo NomeDoProduto databela Produtos;

3. Adicionamos uma clausula WHERE, em que o código da encomendaé igual a 10250;

4. Fazemos os ajustes necessários de modo a que o relatório fiquesemelhante ao seguinte exemplo:

Ilustração 33: 1º Relatório factura, em modo de edição

5. Agora adicionamos uma variável para calcular o total de cadaproduto. Na janela “Report Inspector” chamamos o menu decontexto do item “Variables” e escolhemos a opção “Add variable”;

6. Seleccionamos a variável que criámos e no lado direito do ecrã iráaparecer a janela de propriedades dessa variável. Ateramos asseguintes propriedades:

◦ Name: Total◦ Variable Class: java.lang.double

7. Clickamos no botão em frente à propriedade “Variable Expression”.Na janela que aparece iremos criar a expressão que irá somar asvariáveis;

8. Clickamos em “Fields” e de seguida inserimos a fórmula, usando oscampos disponíveis para a criar. A fórmula deverá ser:$F{DETALHES_DA_ENCOMENDA_PREÇOUNITÁRIO}*$F{DETALHES_DA_ENCOMENDA_QUANTIDADE}*(100­$F{DETALHES_DA_ENCOMENDA_DESCONTO})/100

Prof. Herberto Graça Página 121 de 217

Page 122: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

9. Agora teremos de reajustar o nosso relatório para fazer espaço parao novo campo. Depois criamos uma nova etiqueta para o titulo dacoluna e arrastamos a variável “Total”, do “Report Inspector” para orelatório. Neste momento o relatório deverá ter o seguinte aspecto:

Ilustração 34: Relatório factura com totais, em modo de edição

Ilustração 35: Relatório factura com totais, em modo de visualização

10. Agora vamos adicionar uma variável para calcular o total dafactura. Criamos uma nova variável, tal como fizemos antes, noentanto vamos dar-lhe o nome “TotalFactura” e na propriedade“Calculation” colocamos “Sum”.

11. Na janela “Variable Expression”, clickamos em “Variables” eacrescentamos a variável “Total”, que criámos antes. Uma vez que anossa variável “TotalFactura” está configurada para somar, irá somartodos os resultados da variável “Total”;

12. A variável “TotalFactura” será colocada na secção de sumáriodo relatório, de modo a que fique como exemplificado nasilustrações seguintes.

Ilustração 36: Relatório factura com total da factura, em modo de visualização

Prof. Herberto Graça Página 122 de 217

Page 123: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Ilustração 37: Relatório factura com total da factura, em modo de visualização

12.3.2 ParâmetrosNo relatório da factura, criado antes, visualizamos os dados relativos à

encomenda nº 10250. Assim, se quisermos ver uma factura de uma outraencomenda, teríamos de fazer um outro relatório, exactamente igual, para aoutra encomenda, apenas alterando o nº da encomenda no código SQLutilizado. Se tivéssemos mil encomendas teríamos de fazer mil relatórios, jápara não falar nas novas encomendas que se fossem introduzindo no sistema.

Para resolver este problema utilizamos parâmetros nos relatórios. Porexemplo, no relatório da factura iríamos criar um parâmetro que para que orelatório recebesse o nº da encomenda a mostrar. E é isso mesmo que vamosfazer de seguida:

1. Abrimos o relatório factura, que criámos antes;

2. No painel “Report Inspector” chamamos o menu de contexto do item“Parameters” e seleccionamos “Add Parameter”;

3. O parâmetro é adicionado e seleccionado. No lado direito da janelapodemos ver o painel de propriedades do novo parâmetro. Vamosalterar as propriedades:

• Name: numFactura• Parameter Class: java.lang.Integer (tipo de dados do parâmetro)

• Use as a prompt: sim (abre caixa de diálogo para pedir ao utilizador)

• Default Value Expression: new java.lang.Integer(10250)(Se não for fornecido valor, usa o valor 10250)

4. Agora vamos alterar a consulta do relatório. No painel “ReportInspector” chamamos o menu de contexto do relatório eseleccionamos a opção “Edit Query”;

5. A consulta usada é:

SELECT     DETALHES_DA_ENCOMENDA.PRECOUNITARIO AS PRECO_UNITARIO,     DETALHES_DA_ENCOMENDA.QUANTIDADE AS QUANTIDADE,     DETALHES_DA_ENCOMENDA.DESCONTO AS DESCONTO,     PRODUTOS.NOMEDOPRODUTO AS NOME_DO_PRODUTOFROM     PRODUTOS INNER JOIN DETALHES_DA_ENCOMENDA ON PRODUTOS.CODIGODOPRODUTO = DETALHES_DA_ENCOMENDA.CODIGODOPRODUTOWHERE     DETALHES_DA_ENCOMENDA.CODIGODAENCOMENDA = 10250

Vamos alterar e colocar o parâmetro criado no lugar o código da

Prof. Herberto Graça Página 123 de 217

Page 124: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

encomenda:

SELECT     DETALHES_DA_ENCOMENDA.PRECOUNITARIO AS PRECO_UNITARIO,     DETALHES_DA_ENCOMENDA.QUANTIDADE AS QUANTIDADE,     DETALHES_DA_ENCOMENDA.DESCONTO AS DESCONTO,     PRODUTOS.NOMEDOPRODUTO AS NOME_DO_PRODUTOFROM     PRODUTOS INNER JOIN DETALHES_DA_ENCOMENDA ON PRODUTOS.CODIGODOPRODUTO = DETALHES_DA_ENCOMENDA.CODIGODOPRODUTOWHERE     DETALHES_DA_ENCOMENDA.CODIGODAENCOMENDA = $P{numFactura}

6. No desenho do relatório acrescentamos o parâmetro em frente daetiqueta “Factura”, arrastando-o do painel “Report Inspector” para orelatório, como exemplificado na ilustração seguinte:

Ilustração 38: Relatório factura com o número da factura, em modo de edição

7. Ao Executarmos o relatório, ele vai pedir-nos o número da factura.Teremos de fornecer um valor que exista na base de dados.

Num relatório podemos criar e usar quantos parâmetros quisermos, epodem ser usados nas consultas ou, por exemplo, para definir o título dorelatório.

12.4 Subrelatórios

Consultar o capítulo 7 do livro “iReport 3.7”, de Shamsuddin Ahammad,pela editora Packt Publishing (Março de 2010).

12.5 Relatórios de tabelas cruzadas

Consultar o capítulo 8 do livro “iReport 3.7”, de Shamsuddin Ahammad,pela editora Packt Publishing (Março de 2010).

12.6 Exportar um relatório

Os relatórios podem ter dois formatos diferentes:

• jrxml : Formato de edição, que utilizamos ao criar e editar um

Prof. Herberto Graça Página 124 de 217

Page 125: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

relatório no iReports;

• jasper : Formato compilado, que utilizaremos posteriormente,quando incorporarmos um relatório na nossa aplicação JAVA;

No caso do iReport, sempre que pré-visualizarmos um relatório este serácompilado e será criado um documento “.jasper” na mesma pasta do relatórioem formato “.jrxml”.

Alternativamente, também poderemos visualizar o relatório e, nesse modode visualização, guardar o relatório, por exemplo, em formato PDF.

12.7 Usar um relatório numa aplicação JAVA

Recordo que, para que os relatórios compilados possam ser chamados apartir de um programa JAVA, o iReports tem de ser configurado para utilizarlinguagem JAVA.

Para fazer essa configuração basta ir ao menu “Tools > Options” e em“Language” escolher “Java”. Esta configuração deverá ser efectuada antes decomeçarmos a criar um relatório, caso contrário só poderemos alterar essaopção editando o XML directamente.

Para editar o XML do relatório directamente, com o relatório aberto noiReports, escolhemos o modo de visualização “XML” e eliminamoscompletamente a propriedade 'language="groovy"'.

12.7.1 Bibliotecas a importarPara podermos utilizar os relatórios criados, dentro de um programa JAVA

temos de utilizar algumas bibliotecas específicas, nomeadamente:

• commons-collections-x.x.x.jar

• commons-digester-x.x.jar

• commons-logging-x.x.jar

• jasperreports-x.x.x.jar

• iText-x.x.x.jar

Existem várias versões destas bibliotecas mas temos, necessariamente,de utilizar as mesmas versões que o iReports utiliza para criar os relatórios.Assim, vamos copiar estas bibliotecas da pasta de instalação do iReports (porexemplo: /opt/iReport­3.7.6/ireport/modules/ext ouc:\Programas\iReport­3.7.6\ireport\modules\ext).

12.7.2 Criar um visualizador interno numa aplicaçãoVamos criar a seguinte estrutura no nosso projecto:

Prof. Herberto Graça Página 125 de 217

Page 126: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Ilustração 39: Estrutura do projecto, com um subpacote para relatórios

Na estrutura acima estão definidas três classes, a saber:

• BD: Classe que faz a ligação à base de dados;

• MainUI: Classe que é a janela da aplicação principal, que irá chamaros relatórios (ver classe completa no Anexo 2);

• ReportViewer: Classe que irá lidar directamente com os relatórios,seja para pré-visualizar, ou para converter e guardar (ver classecompleta no Anexo 2).

O código da classe que faz a ligação a uma base de dados já foi estudadonum capítulo anterior, portanto não voltarei a exemplificar.

O código da classe que servirá de aplicação principal também já foiestudado antes, mas aqui justificam-se algumas explicações no momento dechamar os relatórios.

No nosso programa principal teríamos um menu em que algumas das suasopções nos permitiriam chamar relatórios. Esses relatórios podem, ou não, terparâmetros.

12.7.2.1 Chamar um relatório sem parâmetros

Caso o relatório a ser chamado não tenha parâmetros, apenasnecessitamos criar um novo objecto “ReportViewer” com o relatório emquestão, no programa principal (MainUI):

private void categoriasMenuItemActionPerformed(java.awt.event.ActionEvent evt){String localizacao="reports/", nomeFicheiro="categorias";try{

ReportViewer myiReportViewer= new ReportViewer(localizacao+nomeFicheiro+".jasper");myiReportViewer.setBounds(0, 0, desktopPane.getWidth(), desktopPane.getHeight());myiReportViewer.setVisible(true);desktopPane.add(myiReportViewer);myiReportViewer.setSelected(true);

}catch (PropertyVetoException pve){

pve.printStackTrace();}

}

12.7.2.2 Chamar um relatório com parâmetros

Caso o relatório a chamar tenha parâmetros será necessário criar umacaixa de diálogo para pedir os parâmetros ao utilizador. De seguida, para alémde fazer as necessárias conversões de dados, temos de criar um objecto dotipo HashMap, onde colocaremos os vários parâmetros. Finalmente, criamosum novo objecto “ReportViewer” com o relatório em questão e os parâmetros(no formato de um objecto do tipo HashMap), no programa principal (MainUI):

private void facturasMenuItemActionPerformed(java.awt.event.ActionEvent evt){String localizacao="reports/", nomeFicheiro="factura2";

Prof. Herberto Graça Página 126 de 217

Page 127: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

String input=JOptionPane.showInputDialog("Introduza o numero da encomenda");if(input!=null){

try{int numFactura=Integer.parseInt(input);HashMap parameters=new HashMap();parameters.put("numFactura",numFactura);ReportViewer myiReportViewer = new

ReportViewer(localizacao+nomeFicheiro+".jasper",parameters);myiReportViewer.setBounds(0, 0, desktopPane.getWidth(), desktopPane.getHeight());myiReportViewer.setVisible(true);desktopPane.add(myiReportViewer);myiReportViewer.setSelected(true);

}catch (PropertyVetoException pve){

pve.printStackTrace();}catch(NumberFormatException nfe){

JOptionPane.showMessageDialog(this,"Introduza apenas numeros inteiros entre 10248 e 11077");

}}

}

12.7.2.3 Criar o pré-visualizador do relatório

Na classe ReportViewer criamos um construtor que cria uma janela devisualização do relatório. Aqui, os passos importantes são os seguintes:

• Criamos a ligação à base de dados (con);

• Preenchemos o relatório com os dados da base de dados (print);

• Criamos o visualizador do relatório (viewer);

/** * Cria uma janela para visualizar o relatorio dentro de um outro programa * * @param fileName nome do ficheiro, com caminho e extensao * @param parameter parametros do relatorio, se os tiver. Se nao tiver inserimos null. */public ReportViewer(String fileName, HashMap parameter){

this();try{

//Create the connectionConnection con = BD.getConnection();

//Vai a BD buscar os dados do relatorio//Here the parameter file should be in .jasper extension i.e., the compiled reportJasperPrint print = JasperFillManager.fillReport( fileName, parameter, con);

JRViewer viewer=new JRViewer(print);

Container c=getContentPane();c.setLayout(new BorderLayout());c.add(viewer);

}catch(JRException jre){

jre.printStackTrace();}

}

12.7.2.4 Exportar o relatório para formato PDF

Na mesma classe ReportViewer podemos criar um método static que nospermita ter o relatório em formato PDF. Aqui, os passos são semelhantes aosanteriores e são os seguintes:

• Criamos a ligação à base de dados (con);

• Preenchemos o relatório com os dados da base de dados (print);

Prof. Herberto Graça Página 127 de 217

Page 128: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• Exportamos o relatório para um ficheiro;

/** * Cria e guarda o relatorio em formato PDF, na mesma localizaçao do relatorio compilado * * @param caminho caminho para o relatorio * @param fileName nome do ficheiro do relatorio, sem a extensao * @param parameter parametros do relatorio, se os tiver. Se nao tiver inserimos null. */public static void convertToPDF(String caminho, String fileName, HashMap parameter){

try{//Create the connectionConnection con = BD.getConnection();

//Vai a BD buscar os dados do relatorio//Here the parameter file should be in .jasper extension i.e., the compiled reportJasperPrint print = JasperFillManager.fillReport( caminho+fileName+".jasper", parameter,

con);

//exporta o relatorio em PDFJasperExportManager.exportReportToPdfFile(print, caminho+fileName+".pdf");

}catch(JRException jre){

jre.printStackTrace();}

}

Este método é o que devemos utilizar se estivermos a utilizar relatórios num ambiente web, isto é, após o utilizar pedir o relatório, este é executado e convertido para um ficheiro PDF, no servidor, sendo depois enviado para o cliente.

Também é possível exportar um relatório para outros formatos, como por exemplo HTML.

Prof. Herberto Graça Página 128 de 217

Page 129: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

12.8 Exercícios

1) No projecto Adamastor (criado num capítulo anterior) cria um novopacote chamado “Relatorios”. Nesse novo pacote deverás colocar osvários relatórios que criarás, bem como a classe JAVA para os utilizarna aplicação. Após esta classe estar criada deverás fazer as devidasalterações no CLI e no GUI do projecto, de modo a que o programaseja capaz de imprimir os vários relatórios. A classe a criar deveráser capaz de testar os vários relatórios criados, imprimindo-os emPDF. Os relatórios a criar são os seguintes:

a) Listagem de empregados

• Listagem simples, com todos os dados dos empregados.

b) Listagem de clientes

• Listagem simples, com todos os dados dos clientes.

c) Listagem de transitários

• Listagem simples, com todos os dados dos transitários.

d) Listagem de produtos

• Listagem simples de produtos, com o nome, o código, a quantidadepor unidade e o preço unitário.

Prof. Herberto Graça Página 129 de 217

Page 130: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

e) Listagem de vendas por produto

• Imprime uma listagem simples dos produtos com o respectivo totalde vendas.

f) Etiquetas dos Clientes

• Imprime os nomes e os endereços das empresas dos clientes emetiquetas.

Prof. Herberto Graça Página 130 de 217

Page 131: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

g) Totais das Vendas por Valor

• Imprime as vendas classificadas em ordem decrescente por valor.Imprime os dez melhores clientes na primeira página; imprime ototal da página no rodapé da página.

h) Dados de um cliente

• Pede o código do cliente e mostra os seus dados.

i) Listagem de valor total de cada encomenda do mês, trimestre,semestre e ano

• Pede a data de inicio e de fim, e mostra uma listagem com o código,o cliente e total de cada encomenda realizada nesse espaço detempo. No final do relatório apresenta a soma de todos os valores.

Prof. Herberto Graça Página 131 de 217

Page 132: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

j) Catálogo

• Imprime o catálogo dos produtos. Trata-se de uma listagem dosprodutos, agrupados pela respectiva categoria.

k) Factura

• Imprime cada factura numa página separada.

Prof. Herberto Graça Página 132 de 217

Page 133: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

l) Lista Alfabética dos Produtos

• Imprime os produtos em ordem alfabética. Não é necessárioestarem agrupados pela letra.

m)Vendas por cliente

• Cria um gráfico circular demonstrativo das parcelas de vendas porcada cliente.

n) Vendas por categoria

• Cria um gráfico circular demonstrativo das parcelas de vendas decada categoria.

o) Vendas por produto

• Cria um gráfico circular demonstrativo das parcelas de vendas decada produto.

p) Produtos por fornecedor

• Cria um gráfico circular demonstrativo da quantidade de produtosfornecidos por cada fornecedor.

Prof. Herberto Graça Página 133 de 217

Page 134: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

q) Vendas por Categoria

• Imprime as vendas de produtos de uma categoria. Mostra as vendasnum sub-relatório ou agrupamento de dados, e num gráfico.

Prof. Herberto Graça Página 134 de 217

Page 135: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

r) Resumo das Vendas por Ano

• Imprime um relatório resumo que mostra as vendas trimestrais paracada ano. É necessário usar sub-relatórios.

s) Resumo das Vendas por Trimestre

• Imprime um relatório de resumo que mostra vendas de vários anospara cada trimestre. É necessário usar sub-relatórios.

Prof. Herberto Graça Página 135 de 217

Page 136: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

t) Vendas dos Empregados por País

• Imprime vendas agrupadas por país e empregado. Calcula subtotais,total, percentagens; pede intervalo das datas, imprime-o norelatório; imprime mensagem quando o total do empregado atinge oobjectivo; redefine número de página para 1 para país novo. Énecessário usar sub-relatórios.

Prof. Herberto Graça Página 136 de 217

Page 137: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

13 Optimizações

Em geral, quando falamos em optimização, falamos em optimização com ointuito de aumentar a velocidade de um programa, e é nesse aspecto quevamos centrar este capítulo, no entanto também poderemos optimizar umprograma para que este utilize menos memória ou ainda para que seja maisfácil fazer a sua manutenção.

Por regra 90% do tempo de processamento de um programa é passado acorrer apenas 10% do seu código (também há quem utilize a regra 80-20),aquele que é executado com mais frequência. Optimizar os restantes 90% decódigo do programa, onde se passa 10% do tempo de processamento, não temqualquer efeito na performance do software. Por exemplo, se pudéssemos fazeresses 90% de código executar ao dobro da velocidade, o programa apenasficaria 5% mais rápido. Assim, a primeira tarefa a realizar será identificar os10% de código que consomem a maioria do tempo de processamento, e quenem sempre é aquele que se esperaria.

No entanto, antes de se pensar em optimizar código JAVA, devemospensar muito bem se realmente necessitamos de optimizar código, poisexistem várias razões para não o fazermos.

Esta questão é bastante crucial na programação, ao ponto de váriosprogramadores reputados serem frequentemente citados:

• “Rule 1: Don't do it. Rule 2 (for experts only): Don't do it yet.”, M.A.Jackson;

• “More computing sins are committed in the name of efficiency(without necessarily achieving it) than for any other single reason -including blind stupidity.”, W.A. Wulf;

• “We should forget about small efficiencies, say about 97% of thetime: premature optimization is the root of all evil.”, Donald Knuth;

• “The best is the enemy of the good.”, Voltaire;

Existem dois tipos de optimizações, as de baixo nível, relativas a pequenasalterações no código, e as de alto nível, relativas ao algoritmo utilizado.

Em geral, as razões para não optimizar código prendem-se com:

• Se o código criado funciona, optimizar é uma maneira de introduzirerros subtis (bugs);

• Algumas técnicas de optimização reduzem a extensibilidade docódigo;

• Optimizar o código numa plataforma pode torná-lo mais lento noutraplataforma, por exemplo, pode ficar mais rápido em ambienteWindows mas mais lento em ambiente Mac;

• Pode-se acabar por perder muito tempo em optimização de código,com pouco ganho em performance;

Prof. Herberto Graça Página 137 de 217

Page 138: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• Optimizar tende a tornar o código menos legível, e portanto maisdifícil de corrigir e alterar (fazer a sua manutenção). Uma vez que80% do custo de de um software (ao longo da sua vida) vai para asua manutenção e esta raramente é realizada pelos programadoresque o criaram, esta é uma razão de peso. Trata-se de optar entreuma programação defensiva, orientada para a legibilidade, e umaprogramação agressiva, orientada para a performance.

No entanto, se é realmente necessário optimizar o código, devem-seseguir as seguintes linhas orientadoras:

• Não optimizar à medida que se programa. Devemos escrever oprograma sem pensar em possíveis optimizações, concentrando-nosem manter o código limpo, correcto e legível. Se no final o programafor demasiado grande ou demasiado lento, então sim, devemospensar em optimizar;

• Não optimizar a não ser que seja mesmo necessário;

• Se necessitamos optimizar, devemos começar pelo algoritmo;

• Antes de optimizar as operações de baixo nível, devemoscronometrar o código existente para determinar onde se está agastar mais tempo;

• Devemos cronometrar novamente o código após realizar asoptimizações, de modo a comprovar o efeito das alteraçõesrealizadas.

No congresso sobre a linguagem JAVA, Devoxx 2010 foi dada uma palestrabastante completa e interessante, sobre optimização de código JAVA, que podeser vista em:

• http://devoxx.parleys.com/#id=2103&sl=4&st=5

13.1 Optimizações de baixo nível

Ao programarmos em JAVA, estamos a programar numa linguagem de altonível e, como já foi explicado antes, a este nível devemos fazer umaprogramação defensiva e optimizar o nosso código para a legibilidade.

A não ser que se esteja a programar especificamente para muito baixonível, como para um processador específico ou uma API que outrosprogramadores irão utilizar para criar as suas aplicações, a maioria dasoptimizações de baixo nível terão um efeito residual na performance do código.

Em teoria e na prática, o compilador irá lidar com a micro-optimização. Ocompilador JIT da JVM irá, provavelmente, realizar estas optimizações e mesmoque isso não aconteça para alguns casos, as modificações serão tão complexasque poderão acabar por deixar o código mais lento.

No entanto, há sempre alguns detalhes a que deveremos dar atenção:

• Escolher as estruturas de dados mais adequadas;

• Não usar objectos sincronizados (syncronized), a não ser em último

Prof. Herberto Graça Página 138 de 217

Page 139: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

caso;

• Evitar criar objectos explicitamente, ou implicitamente;

• Apenas reimplementar código da API do JAVA se tivermos certeza deque o código existente não serve os nossos propósitos;

• Devemos sempre usar pequenos testes independentes para testar aperformance de algoritmos e estruturas de dados que pretendamosoptimizar;

• Em último caso poderemos reescrever o nosso código e chamá-lo viaJNI, ou seja, utilizar código nativo.

13.1.1 Benchmark de algoritmos 13.1.1.1 Análise ao bytecode

Uma das formas de optimização do JAVA passa por analisar o bytecoderesultante da compilação do código JAVA. Para visualizar o bytecode usamos ocomando javap ­c, por exemplo:

javap -c Teste.class | more

Código 1: Comando para análise de bytecode

O comando javap refere-se a um utilitário presente na pasta bin do JDK.

13.1.1.2 Benchmark de velocidade

Para testar código específico devemos cronometrar o tempo que estedemora a executar. Para cronometrar o tempo de execução, guardamos omomento (tempo) de inicio e final de execução do código, fazendo depois a suasubtracção. Antes de iniciar a contagem do tempo devemos chamar o garbagecollector de modo a minimizar inconsistências devido à limpeza da memória ameio de um teste.

No entanto, na maioria dos casos, a execução de código é demasiadorápida e quase imensurável, pelo que teremos de fazer um ciclo com o nossocódigo lá dentro.

Vejamos o exemplo o caso da concatenação de strings. Já vimos que acriação de objectos deve ser evitada, pois é uma acção que demora muitotempo. A concatenação de strings, com o operador “+”, cria um novo objectoString em cada concatenação.

Vamos então testar a concatenação da string “abc”, 50000 vezes. Numteste usaremos o operador “+=” e noutro teste usaremos um objecto da classeStringBuilder, que concatena, sem criar novas instâncias da classe String:

String test = "";System.gc();long start = System.currentTimeMillis();for(int i = 0; i < 50000; i++) {

test += "abc";}System.out.println("Intervalo de tempo usando '+=': " +

(System.currentTimeMillis() - start) + " milissegundos");

Código 2: Teste de rapidez de concatenação de strings com o operador "+="

Prof. Herberto Graça Página 139 de 217

Page 140: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

test = "";System.gc();start = System.currentTimeMillis();StringBuilder builder = new StringBuilder();for(int i = 0; i < 50000; i++) {

builder.append("abc");}

System.out.println("Intervalo de tempo usando StringBuilder: " + (System.currentTimeMillis() - start) + " milissegundos");

Código 3: Teste de rapidez de concatenação de strings com um objecto StringBuilder

O resultado destes testes depende da plataforma em que são executados,no entanto num computador com processador Intel i5 a 2,67Ghz, a correrUbuntu 10.04, o output de um programa com os dois testes, foi o seguinte:

Intervalo de tempo usando '+=': 3543 milissegundosIntervalo de tempo usando StringBuilder: 3 milissegundos

Código 4: Resultados dos testes de rapidez de concatenação de strings

Ou seja, no caso em que não são instanciados objectos, o código executa1182 vezes mais rapidamente!!!

13.1.1.3 Benchmark de memória

Para saber o grau de ocupação da memória, podemos testar um algoritmode forma semelhante ao benchmark de velocidade descrito antes, massubstituindo a chamada ao método System.currentTimeMillis() por chamadas aométodo:

long freemem (){System.gc();return Runtime.getRuntime().freeMemory();

}

Código 5: Método que devolve o grau de ocupação da memória

13.1.1.4 Benchmark geral e automatizado

O benchmark de operações é realizado através de um software que testa aexecução de uma determinada operação, milhares ou até milhões de vezes.Estes testes vão-nos permitir saber quais as operações a evitar e por quaisoperações as substituir.

Estes bechmarks são especialmente importantes porque os seusresultados são diferentes para cada ambiente de execução, dependem dohardware, do Sistema Operativo e do compilador utilizado (se é interpretado,se é compilado com JIT ou com JNI).

Para realizar benchmarks poderemos usar a applet em:

• http://www.javaworld.com/jw-04-1997/jw-04-optimize.html?page=4

13.1.2 Técnicas de optimização gerais Existem várias técnicas de optimização que se aplicam a todas as

linguagens, no entanto nem todas se aplicam ao JAVA, pois não é compiladopara código máquina. As técnicas seguintes focam-se sobretudo nareestruturação de código e na substituição de umas operações por outrasequivalentes.

Prof. Herberto Graça Página 140 de 217

Page 141: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

13.1.2.1 Redução de força

Esta técnica ocorre quando se substitui uma operação por outraequivalente. O exemplo mais comum é a substituição da divisão oumultiplicação por um múltiplo de 2, pela “shiftagem” para a direita ou paraesquerda, respectivamente.

Por exemplo:

x>>2; //substitui x/4y<<1; //substitui y*2

Código 6: Substituição de operações de divisão e multiplicação

13.1.2.2 Eliminação de sub-expressões

A eliminação de sub-expressões elimina os cálculos redundantes.

Por exemplo:

double x = d * (lim / max) * sx;double y = d * (lim / max) * sy;

double depth = d * (lim / max);double x = depth * sx;double y = depth * sy;

Código 7: Substituição de cálculos redundantes

13.1.2.3 Movimento de código

Á semelhança do caso anterior, neste caso movemos as instruções, oucálculos, cujo resultado não muda. O código é movido para outro local, demodo a que só execute quando o seu resultado se poderá alterar, em vez deexecutar sempre. Acontece com mais frequencia em ciclos, mas também podeacontecer que seja código que é executado sempre que se chama um método.

Por exemplo:

for (int i = 0; i < x.length; i++)x[i] *= Math.PI * Math.cos(y);

double picosy = Math.PI * Math.cos(y);for (int i = 0; i < x.length; i++)

x[i] *= picosy;

Código 8: Movimentação de instruções redundantes

13.1.2.4 Redução de ciclos

A redução de ciclos implica a realização de mais que uma operação porciclo, e por consequência reduzindo os ciclos e a execução do código decontrolo dos ciclos.

Partindo do exemplo anterior, se soubermos que o tamanho do array ésempre um múltiplo de dois, poderemos reescrever o ciclo como:

double picosy = Math.PI * Math.cos(y);for (int i = 0; i < x.length; i += 2) {

x[i] *= picosy;x[i+1] *= picosy;

}

Código 9: Redução de ciclos

13.1.3 Técnicas de optimização específicas 13.1.3.1 Ciclos

O impacto da optimização dos ciclos depende da quantidade de ciclos,bem como da quantidade de instruções executadas em cada ciclo. No entanto,

Prof. Herberto Graça Página 141 de 217

Page 142: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

há algumas optimizações que se podem realizar na estrutura em si mesma.

1. Iterador local: O iterador do ciclo deverá ser sempre uma variávellocal, pois é mais rápido aceder a estas variáveis do que a umavariável global e o iterador será acedido sempre, pelo menos umavez, em cada ciclo;

2. Iterar de N-1 a 0: Se não for necessário que o iterador vá de 0 aN-1, então o ciclo deverá ser reestruturado para iterar de N-1 a 0,pois a comparação com 0 é mais rápida que a comparação com N, eesta comparação é realizada a cada ciclo.

Por exemplo:

for (i = 0; i < n; i++)// instruções

for (i = N; --i >= 0; )// instruções

Código 10: Optimização de ciclos

13.1.3.2 Arrays

1. Inicialização de arrays: Ao se inicializar um array, o compilador iráfazer a atribuição de valores, um a um, como mostra o exemploseguinte:

byte[][] myData = {{1, 2}, {3, 4}}; byte[][] myData = new byte[2][];myData[0] = new byte[2];myData[0][0] = 1;myData[0][1] = 2;myData[1] = new byte[2];myData[1][0] = 3;myData[1][1] = 4;

Código 11: Inicialização de arrays

Assim, uma vez que na realidade se trata da realização de váriasinstruções, devemos evitar colocar a inicialização de arrays dentrode um método, pois todas essas instruções seriam executadas acada vez que o método fosse chamado.

Como solução devemos declarar um array como variável de classe(static) ou de instância e inicializá-lo apenas uma vez. Mesmo quenecessitemos de uma nova versão do array dentro de um método, émais rápido realizar uma cópia de um array já inicializado.

2. Copiar arrays do mesmo tipo de dados: No caso de cópias dearrays do mesmo tipo (por exemplo de int para int, não de int parabyte) não se deve criar um ciclo que percorra todas as posições deambos os arrays, copiando cada uma das posições. Deveremos usaro método estático System.arraycopy() ou o método de instância doarray clone(). O método arraycopy() trata-se de um método nativo daAPI do JAVA, que está optimizado para copiar arrays do mesmo tipode dados. No entanto estes métodos apenas copiam arrays de umadimensão, ou a 1ª dimensão de um array multidimensional.

3. Evitar arrays com várias dimensões: O acesso a um array deduas dimensões pode chegar a ser duas vezes mais lento que oacesso a um array de uma dimensão. Assim, talvez seja vantajososubstituir um array multidimensional por um array unidimensional,tornado o código um pouco mais complexo. Este mesmo principio éválido para outros tipos de estruturas de dados.

Prof. Herberto Graça Página 142 de 217

Page 143: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

13.1.3.3 Variáveis

A performance de uma variável é determinada pelo seu âmbito e pelo seutipo.

Relativamente ao âmbito, as variáveis locais, de métodos, são as maisrápidas de se aceder.

Relativamente ao tipo, ao optimizar para rapidez, devemos sempreprivilegiar o tipo int, pois as operações entre variáveis do tipo byte, short, longe char são sempre realizadas como int, implicando conversões extra.

Vejamos, por exemplo, o seguinte código:

byte a, b, c;a=(byte) (b + c);

Código 12: Operações com conversões

Aqui, a soma entre duas variáveis byte, tem como resultado um valor int,que tem de ser convertido para byte, antes de ser colocado na variável “a”.Essa conversão, o cast, exige processamento extra.

13.1.3.4 Métodos

Existem duas categorias de métodos:

• Definidos estaticamente: que são definidos ao compilar o código,e portanto são mais rápidos quando, posteriormente, se executaesse código. Nesta categoria encontram-se os métodos que sãodeclarados como static, private e final, bem como os construtores.

• Definidos dinamicamente: que são definidos em tempo real, aoexecutar o código já compilado.

Assim, temos as seguintes técnicas para acelerar a chamada de métodos:

1. Eliminar a chamada de métodos: Se tivermos um método trivial,por exemplo apenas com uma linha de código, podemos eliminar otempo de chamada do método colocando o código directamenteonde se realizaria a chamada do método. No entanto, esta técnicadeve ser utilizada em casos muito excepcionais, onde a velocidadede execução seja um factor crítico, pois vai sacrificar a legibilidadedo código, bem como a sua manutenção. (method inlining)

2. Conversão para static, private ou final:

◦ Conversão para static: Quando o método não usamvariáveis de instância, nem chamam métodos de instância;

◦ Conversão para final: Quando o método não necessitaráser reconstruído numa subclasse (overriden);

◦ Conversão para private: Quando um método nãonecessita ser chamado fora da classe.

3. Métodos sincronizados (synchronized): Os métodossincronizados são os que demoram mais tempo a serem chamados eportanto a chamada a um método destes deve ser optimizadasempre que possível:

Prof. Herberto Graça Página 143 de 217

Page 144: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

◦ É um pouco mais rápido chamar um método sincronizadodo que entrar num bloco sincronizado;

◦ É mais rápido chamar um método sincronizado dentro deum bloco sincronizado que fora de um bloco sincronizado(se não contarmos com o tempo de entrada no blocosincronizado);

class Testes { static int x; void test () { meth1(); meth2(); // mais lento synchronized (this) { meth1(); // mais rápido meth2(); } } synchronized void meth1 () { x = 1; } void meth2 () { synchronized (this) { x = 1; } }}

Código 13: Chamada de métodos e blocos sincronizados

◦ Se tivermos uma classe em que se chamem métodossincronizados dentro de outros métodos sincronizados,devemos delegar tarefas em métodos não sincronizadosque poderão ser chamados em vários métodossincronizados. Isto evita que o programa tenha de esperarpara ter tempo de processador para entrar no primeirométodo e novamente no método interior. Por exemplo:

class X { public synchronized void setStuff (int i) { // código do método “setStuff” } synchronized void doLotsOfStuff () { setStuff();//chama “setStuff” // outras instruções... }}

class X { public synchronized void setStuff (int i) { doSetStuff(); } private doSetStuff () { // código do método “setStuff” } synchronized void doLotsOfStuff () { doSetStuff();//evita chamar “setStuff” // outras instruções... }}

Código 14: Como evitar chamar métodos sincronizados aninhados

13.1.3.5 Casts

Fazer um cast também é uma das operações que consomem mais tempode execução.

1. Evitar a repetição de casts: É preferível guardar o resultado deum cast numa variável local a realizar o mesmo cast várias vezes.

Prof. Herberto Graça Página 144 de 217

Page 145: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

boolean equals (Object obj) { if (obj instanceof Point) return (((Point)obj).x == this.x &&

((Point)obj).y == this.y); return false;}

boolean equals (Object obj) { if (obj instanceof Point) { Point p = (Point)obj; return (p.x == this.x &&

p.y == this.y); } return false;}

Código 15: Como evitar a repetição de casts

2. Criar um método para conversão: É preferível criar um métodoque permita converter de uma classe para outra, evitando anecessidade de realizar um cast (que será sempre mais lento).

13.1.3.6 Instanciação de objectos

Como já vimos antes, criar objectos é uma das instruções que consomemmais tempo e portanto devemos:

3. Evitar instanciar objectos dentro de ciclos;

4. Reutilizar objectos já instanciados;

5. Não inicializar variáveis de instância se o seu valor por defeito for omesmo com que se pretende inicializar essa variável.

13.1.3.7 Entradas e saídas de dados

Devemos usar classes como BufferedInputStream ou BufferedOutputStreamsempre que possível.

13.1.3.8 Substituição de classes da API

Algumas classes da API fazem mais do que o que necessitamos, com orespectivo aumento no tempo de execução. Nestes casos devemos criar umaversão especializada dessas classes, que fazem menos, mas executam maisrapidamente.

13.1.3.9 Substituição de métodos da API

Se estivermos a usar uma classe da API e detectarmos problemas deperformance num método, podemos criar uma subclasse dessa classe e fazeroverride desse método problemático, substituindo-o por um método maisrápido.

13.1.3.10 O método instanceof

O método instanceof é bastante lento, pelo que se for necessário utilizá-locom frequência, poderá ser vantajoso tornar a classe um pouco maiscomplexa, por exemplo criando um membro extra “id” que guarde o tipo dedados do objecto. Esta solução até fará com que o resultado possa ser utilizadonum switch.

13.1.3.11 A utilização de switchs

A estrutura switch é compilada para dois tipos de bytecode, um maisrápido que o outro, consoante os números a identificar estão mais dispersos oumais próximos, respectivamente. Assim, esta estrutura poderá ser testadacontra uma versão do mesmo algoritmo utilizando vários if.

Prof. Herberto Graça Página 145 de 217

Page 146: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

13.1.3.12 Processos

A utilização excessiva de processos pode levar a grandes atrasos, poisimplica adquirir e libertar o acesso exclusivo a determinados objectos, ou pior,deadlocks, em que o processo A fica à espera do processo B e o processo B ficaà espera do processo A.

Para evitar esses problemas devemos reduzir o número de processos.Assim, por exemplo, se tivermos um jogo com várias formas que se movemnum fundo, em vez de criarmos uma processo para cada forma devemos criarum gestor para essas formas, que utiliza um único processo.

13.1.4 Exercícios1) Utilizando a metodologia de benchmark específico, crie um

programa que faça uma tabela com os resultados do benchmark decada uma das seguintes alíneas:

a) Ciclo vazio, para retirar o tempo aos testes seguintes, que deverão ser realizados dentro deste ciclo: for (i=0; i<1000000; i++);

b) Atribuição de um valor a uma variável local: n=i;

c) Atribuição de um valor a uma variável de instância: this.n=i;

d) Atribuição de um valor a um elemento de um array: a[0]=i;

e) Incrementação de um byte: b++;

f) Incrementação de um short: s++;

g) Incrementação de um int: ii++;

h) Incrementação de um long: l++;

i) Incrementação de um float: f++;

j) Incrementação de um double: d++;

k) Criação de um objecto: new Object();

l) Criação de um array: new int[10];

m)Chamada de um método: null_func();

n) Chamada de uma função matemática: Math.abs();

o) Utilização de código inline: (x<0)? ­x : x;

13.2 Optimizações de alto nível

Hoje em dia os compiladores já realizam muitas optimizações de baixonível, e assim, os ganhos possíveis com optimizações de baixo nível sãorelativamente limitados.

A performance de um programa relaciona-se cada vez mais com a formacomo os componentes se relacionam entre si, através de redes, frameworks,

Prof. Herberto Graça Página 146 de 217

Page 147: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

aplicações ou sistemas distribuídos. Assim, é na gestão de processos, nagestão de memória e na comunicação entre componentes que se pode fazer adiferença na performance de uma aplicação.

Este tipo de problemas de desenho algorítmico de alto nível devem serresolvidos o mais cedo possível, pois com o tempo tendem a crescer no seuâmbito e na sua complexidade, tornando-se mais complexo e demoradoresolvê-los.

Assim, o processo de desenvolvimento deverá contemplar um processo deoptimização que permita detectar os problemas de asfixiamento deperformance assim que estes ocorrem. E isto depende muito das ferramentasutilizadas.

13.2.1 Processo de optimizaçãoO mais importante no processo de optimização é fazer a correcta definição

das necessidades de performance. A partir daí, trata-se apenas de criar testesde performance automáticos, utilizando uma ferramenta de testesautomatizados. Esse tipo de ferramenta tem o nome de “profiler” e é com umsoftware desses que vamos descobrir o código em que existe asfixiamento deperformance (botleneck), após o que teremos de compreender a razão para adegradação da performance e corrigir o problema.

13.2.1.1 1ª Fase: Definir necessidades de performance

Um caso de utilização é uma tarefa que um utilizador irá realizar com onosso programa. É por aqui que começamos por compreender e definir asnecessidades de performance da nossa aplicação, por exemplo:

• O caso necessita de uma resposta imediata ao utilizador, ounecessita apenas de produzir uma série de relatórios semgrandes requisitos de performance?

• O utilizador é um funcionário interno, ou um cliente final, comoum cliente online?

• Quantos utilizadores simultâneos são esperados, em média enos picos de utilização?

Recolher informações sobre os principais casos é o ponto de partida parapodermos gerir o resto do processo de optimização.

13.2.1.2 2ª Fase: Criar testes automatizados

O desenvolvimento de software deve começar com a criação dos casos deteste, onde se deverão incluir os testes de performance. Quando os testesforem cumpridos satisfatoriamente pela aplicação, a aplicação estaráterminada.

Ao utilizarmos testes de performance automatizados, trabalharemos esteaspecto do desenvolvimento de software na nossa rotina diária e seremosalertados assim que a performance do software não cumprir os requisitosnecessários. Quando isto acontece podemos centrar-nos imediatamente nesseproblema e resolver os eventuais problemas de algoritmia ou desenho dosoftware, enquanto estes são fáceis de resolver. Uma fraca performance pode

Prof. Herberto Graça Página 147 de 217

Page 148: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

ser corrigida como qualquer outro bug.

Este método de trabalho tem várias vantagens:

1. Em vez de tentarmos optimizar tudo, optimizamos apenas o quenecessita ser optimizado;

2. Em vez de esperar pelo fim do ciclo de desenvolvimento, fazemosoptimizações na nossa rotina diária, ao descobrir as falhas deperformance;

3. Temos a possibilidade de realizar alterações de desenho no inicio dociclo de desenvolvimento, quando ainda é relativamente fácilfazê-los.

Os casos de teste de performance incidem sobre dois aspectos:

• Tempo de resposta: São testes que medem o tempo entre o inicioe o final de uma tarefa. Esta tarefa pode ser apenas um método ouum conjunto de métodos, um caso de utilização da aplicação. Estestestes podem ser realizados na forma de apenas um teste ou váriostestes consecutivos, dos quais se calculará uma média, ou aindavários testes consecutivos, dos quais se ignorarão os primeirostestes.

• Escalabilidade: Consistem em testes de carga, que simulam autilização da aplicação por vários utilizadores ao mesmo tempo.

13.2.1.3 3ª Fase: Corrigir o problema

Após identificarmos as áreas do software que necessitam melhoramentos,passamos então para as optimizações. A chave para uma optimização eficazestá na qualidade das ferramentas utilizadas.

Este processo de optimização consiste em duas fases principais: identificaro problema e resolver o problema. Ambas as fases necessitam ferramentas desuporte:

• JUnit: É uma biblioteca para teste de código JAVA, e que se temvindo a tornar o standard para testes de utilização. O JUnit ajuda agarantir que os métodos criados funcionam como previsto, sem queseja necessário terminar a aplicação. Para fazer testes específicos,como XML ou bases de dados, existem extensões específicas;

• JUnitPerf: É uma extensão de JUnit que permite testar aperformance de velocidade e escalabilidade de uma unidade deteste (uma secção de código em teste). Esta extensão temprecisamente dois testes:

◦ TimedTest: Cronometra a duração de um determinado teste,e se ultrapassar o limite de tempo máximo predefinido, dáaviso de falha;

◦ LoadTest: Realiza um teste em que simula a utilização daunidade de teste por vários utilizadores concorrentes e váriasiterações;

• Borland Optimizeit Suite: Permite aos programadores detectar

Prof. Herberto Graça Página 148 de 217

Page 149: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

asfixiamentos de performance ao nível dos componentes edecompor o código até se chegar exactamente à linha de códigocausadora do problema. Contém as seguintes ferramentas:

◦ Request Analyzer: Permite detectar asfixiamentos deperformance nos nós de aplicações J2EE. Com estaferramenta os programadores poderão priorizar aperformance de requisições web de JDBC, JMS, JNDI, JSP, RMI,e EJB e detectar problemas no inicio do ciclo dedesenvolvimento;

◦ Profiler: Isola problemas de performance da memória e doprocessador. Entre outras funcionalidades pode detectarautomaticamente fugas de memória.

◦ Debugger de processos: Permite ver o estado de todas osprocessos e semáforos, em tempo real, possibilitando aprevisão de problemas como deadlocks antes de estesocorrerem.

◦ Code Coverage: Possibilita a realização de testes deperformance ao longo do ciclo de desenvolvimento;

• Precice's InDepth e Insight: Permitem monitorizar a performancede uma aplicação J2EE, após estar terminada, quando já está emfuncionamento.

As ferramentas de optimização são especialmente úteis para traçar operfil de performance do código, resolver fugas de memória e optimizarprocessos.

• Perfil de performance: Após os testes de utilização assinalaremum problema de performance, o primeiro passo é fazer a análise (operfil) do algoritmo. Essa análise não é apenas uma lista demétodos, pois um método irá chamar muitos outros, pelo que umaboa ferramenta de análise (profiler) permitirá fazer uma análisegráfica em árvore, possibilitando a detecção das secções de códigoque estão a demorar mais tempo. Assim, por exemplo, sedescobrirmos que a aplicação está a demorar muito tempo namanipulação de strings, iremos optimizar os algoritmos demanipulação de strings. Se por outro lado detectarmos que se está aperder muito tempo em comunicações pela rede, poderemos alteraro desenho da aplicação de modo a reduzir a quantidade decomunicações realizadas, utilizando uma cache ou uma sessão. Emtodo o caso, muitas vezes o profiler poderá dar informaçõessuficientes para localizar e resolver o problema.

• Fugas de memória: O JAVA utiliza um sistema chamado “garbagecollection” (recolha do lixo) para libertar a memória que está a serutilizada por objectos que já não estão a ser utilizados pelaaplicação. A JVM sabe que um objecto já não está a ser utilizado,quando já não existe nenhuma referencia a esse objecto. Quandoum objecto mantém uma referencia a um outro objecto (por ex. umavariável estática) que já não será necessário, então teremos umafuga de memória. Para resolver este tipo de problemas de memória

Prof. Herberto Graça Página 149 de 217

Page 150: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

é necessário visualizar a lista de todos os objectos em utilização, ecomparar essa listagem em vários momentos de execução. OBorland Optimizeit Suite permite realizar este tipo de análise,descobrindo muitas fugas de memória automaticamente.

• Optimização de processos: Estes são os problemas maiscomplicados de resolver, mesmo que o IDE utilizado tenha umdebugger que possibilite ver vários processos. Geralmente énecessária uma ferramenta especializada, pois ao visualizar váriosprocessos num debugger tradicional, haverá reflexos nocomportamento da aplicação, e portanto é necessário visualizar osprocessos no ambiente de produção. Um debugger adequado deverápossibilitar:

◦ Analisar a concorrência entre processos: Muitas vezesacontece que vários processos competem pelos recursos docomputador, levando a que vários processos possambloquear, enquanto esperam que os recursos necessáriosestejam disponíveis. Um bom debugger permitirá visualizar,graficamente, quais os recursos que estão a provocar maiorconcorrência e entre quais processos. Também permitirávisualizar quais os processos que estão a demorar demasiadotempo provocando atrasos em outros processos.

◦ Solucionar deadlocks: Normalmente quando uma aplicaçãobloqueia deixa de ser possível recolher mais informação. Umdebugger apropriado permitirá descobrir exactamente tanto oprocesso que está à espera como o recurso do qual ele está àespera.

13.2.2 Técnicas algorítmicas 13.2.2.1 Utilização dos algoritmos e estruturas de dados

correctas

A primeira regra a ter em conta é do senso comum: Devemos utilizarsempre os algoritmos e as estruturas de dados mais adequadas!

Por exemplo, porque usaremos um algoritmo de ordenação bublesort sepodemos usar um algoritmo quicksort, que é muito mais rápido?! Da mesmaforma, porquê usar um array para guardar dados pesquisáveis quando umaárvore binária ou uma tabela de hash permitem pesquisas muito maisrápidas?! Porque não testar um algoritmo iterativo em oposição a um algoritmorecursivo?!

13.2.2.2 Ocultação de processamento

Esta técnica não consiste na optimização real do código, mas antes emdar ao utilizador final a aparência de rapidez de processamento, melhorando ostempos de resposta nas secções de código que exigem interactividade com outilizador, fazendo com que o processamento mais lento ocorra em momentosmenos visíveis ao utilizador.

13.2.2.3 Avaliação de pré-condições

Em muitos casos, podemos evitar a realização de testes aos parâmetros

Prof. Herberto Graça Página 150 de 217

Page 151: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

de entrada, por exemplo na criação de objectos e na execução de métodos, seplanificarmos a aplicação de modo a garantir que só chegaremos a essassituações com os dados apropriados.

Por exemplo, poderemos desenhar a aplicação de modo a que a interfacecom o utilizador realize testes imediatos aos dados introduzidos pelo utilizador,não permitindo que os dados sejam enviados se não forem os adequados, ouforçando o utilizador a escolher de entre um grupo de opções, em vez depermitir que o utilizador introduza os dados que pretender.

13.2.2.4 Partilha de componentes

Em situações em que existem componentes que são usados em váriosobjectos, de forma redundante, podem ser unidos e combinados de forma aque um único componente seja partilhado por vários objectos,poupando oespaço em memória e o tempo de processamento exigido para criar novoscomponentes. Para este fim, podem ser utilizadas colecções ou repositórios deobjectos.

13.2.2.5 Repositórios de objectos

Já vimos antes que os objectos podem e devem ser reciclados, pois acriação de novos objectos tem elevados custos de tempo de processamento.Levar esta técnica um passo mais à frente é criar um repositório de objectos.

Um repositório de objectos consiste numa estrutura, como uma colecçãode objectos, que guarda os objectos (ou uma referencia a esses objectos) quejá não são necessários, mas que poderão voltar a ser necessários.

Utilizar esta técnica implica duas situações:

1. As classes deverão ter um método para realizar a reinicialização doobjecto (reInit);

2. Antes de criar um novo objecto com a instrução new, devemosprocurar um objecto, do mesmo tipo, no repositório e reiniciá-lo,caso exista um disponível. (Não percebi bem se tem de ser antes donew ou se pode ser no construtor da classe! Será necessário testar aimplementação de ambas as metodologias em termos de velocidadee memória para saber se o construtor pode apenas devolver umareferencia para um objecto já criado ou cria sempre um novoobjecto)

13.2.2.6 Estruturas finitas

A maioria das classes de colecções são desenhadas para não terem limitespara a quantidade de elementos que albergam. No entanto a maioria dasaplicações apenas necessitam de capacidades finitas, predeterminadas. Asestruturas com limites são, na maioria das situações, mais rápidas que asestruturas sem limitações.

13.2.2.7 Pré-construção de objectos

Há aplicações que passam tempo significativo a inicializar objectos, muitoantes de os utilizar. Por exemplo, um programa que utilize várias colecções deobjectos e que os cria e inicializa no arranque do programa.

Esta situação pode ser evitada criando uma versão do programa que

Prof. Herberto Graça Página 151 de 217

Page 152: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

utilize objectos que estão guardados persistentemente. Isto é, as referidascolecções de objectos poderão estar guardadas num ficheiro, sendosimplesmente recarregadas para memória ao iniciar o programa.

A eficiência desta técnica deverá ser sempre testada, pois depende daquantidade de objectos, da sua complexidade e da rapidez com que o sistemainformático carrega dados da memória secundária.

13.3 Optimizações para redução de tamanho

A redução de código é especialmente importante para as applets, que sãoprogramas em JAVA embutidos em páginas web, porque são transmitidasatravés de uma rede de computadores como a internet, e convém que sejam omais pequenas possível.

1. Usar ficheiros JAR, que têm algum grau de compressão e evitamabrir uma nova ligação de download para cada ficheiros de cadaclasse;

2. Não reinventar classes que já existem na API. As classesexistentes na API do JAVA devem ser usadas sempre que possível,quer as utilizemos directamente ou criando subclasses.

3. Utilizar o sistema de heranças no nosso próprio código.Quantos mais métodos pudermos herdar de uma classe para outra,menos código teremos necessidade de criar.

4. Separar o código comum. Colocar o código que é usado em várioslocais, no seu próprio método.

5. Não inicializar arrays grandes. Apesar da inicialização de umarray se realizar em apenas uma linha, ao compilar, transforma-seem várias linhas, cada uma inserindo um elemento. Podemos pouparespaço guardando os dados numa string e posteriormente fazer otratamento de modo a inserir cada item no array. Troca-se espaçopor tempo de processamento.

13.4 Optimizações para a manutenção de código

A legibilidade de código é especialmente importante numa linguagemorientada por objectos, como o JAVA, pois pretende-se que o código sejareutilizado sempre que possível. As optimizações referidas neste capítulopodem entrar em conflito com as optimizações referidas nos outros capítulos,pois os objectivos são diferentes.

1. Usar convenções de programação: As convenções deprogramação são importantes, por motivos já discutidos numcapitulo anterior, e devem ser sempre seguidas. As convenções deprogramação JAVA podem ser consultadas num dos anexos destemanual, ou no endereço:

http://www.oracle.com/technetwork/java/codeconv-138413.html

Prof. Herberto Graça Página 152 de 217

Page 153: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

2. Fazer código legível para humanos, não para compiladores:Não usar optimizações que resultem em código menos legível, maisdifícil de ler ou compreender;

3. Não presumir nada: Escrever código para o programador comum.Por exemplo, colocar parêntesis nas expressões, em vez de assumirque todos os programadores conhecem as regras de precedência;

4. Documentação: Usar Javadocs para criar documentação onlinepara as classes criadas. A documentação do utilitário davadoc podeser consultada em:

http://www.oracle.com/technetwork/java/javase/documentation/index-jsp-135444.html

Prof. Herberto Graça Página 153 de 217

Page 154: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

14 Empacotamento

14.1 Pacote executável

Depois de criado, um programa em JAVA pode ser executado directamentea partir do ficheiro com o código, no entanto, é muito mais elegante ter umficheiro com todo o nosso código, imagens, som, etc., que necessitamos.

14.1.1 Compilar e executar os nossos programasPara correr os programas que desenvolvemos temos de, primeiro,

compilar o ficheiro .java por nós criado e depois correr o executável gerado.

Para compilar o programa, na linha de comandos:

% javac NomeFicheiro.java

Para executar o programa:

% java NomeFicheiro

No entanto, devemos ter em atenção que:

O nome do ficheiro contendo código tem de ter o nome da classeexecutável mais a extensão “.java”.

A compilação da classe dá origem a um ficheiro com o mesmo nome, mascom a extensão “.class”.

Para executar, chama-se o nome da classe e não o nome do ficheiro (ex:java Hello e não java Hello.class).

14.1.2 Os ficheiros “.jar”Em ambiente Windows, um programa corrente, é executado a partir de um

ficheiro “.exe”, que é considerado um ficheiro executável uma vez que corredirectamente na plataforma para a qual foi criado.

O “executável” de um programa em JAVA, um ficheiro “.jar”,não éconsiderado um executável real, uma vez que é apenas um ficheirocomprimido, com todos os ficheiros necessários a um programa, e com umficheiro que contém a informação sobre qual a classe que deve ser executadaquando se pretende que o programa corra. Para além disso, não corredirectamente na plataforma, vai correr sobre a JVM (JAVA Virtual Machine).

Para criar um ficheiro “.jar”, o JAVA SDK fornece-nos uma ferramenta, umpequeno programa chamado “jar.exe”, que fica instalado na directoria“D:\j2sdk1.4.2_01\bin” e funciona através de linha de comandos. No nossocaso, não será necessário preocuparmo-nos com os detalhes do seufuncionamento, uma vez que o nosso IDE nos facilita o trabalho, no entanto, se

Prof. Herberto Graça Página 154 de 217

Page 155: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

quiseres saber mais sobre esta ferramenta podes consultar a suadocumentação em:

http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/jar.html

14.1.3 Criar um “.jar”Como disse antes, vamos utilizar o nosso IDE para criarmos os nossos

“.jar”.

Então, selecciona o menu “File > Export…”:

Ilustração 40: Exportação de um projecto

Depois, seleccionas “JAR file” e clickas em “next”:

Prof. Herberto Graça Página 155 de 217

Page 156: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Ilustração 41: Exportação de um projectopara um JAR

Agora tens de escolher quais os pacotes que te interessam incluir no teu“.jar”, bem como quaisquer outros ficheiros adicionais que sejam necessários.Deves também escolher para onde queres que esse ficheiro seja criado e qualo nome a dar-lhe:

Ilustração 42: Escolha dos pacotes aexportar

Prof. Herberto Graça Página 156 de 217

Page 157: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Seguidamente, clickas duas vezes em “next”, escolhes qual a classe quedeve ser executada no inicio, e finalmente escolhes, “Finish”!

Ilustração 43: Finalização da exportação

14.1.4 Problemas dos “.jar”Agora que tens o teu “executável”, será suficiente dar dois clicks no

ficheiro e o programa irá arrancar. No entanto, podem acontecer algunscontratempos.

Em primeiro lugar, pode acontecer que as variáveis de sistema “PATH” ou“CLASSPATH” não tenham as informações necessárias, pelo que deverás reveros passos no capitulo 1.1.2.

Pode também acontecer que os ficheiros “.jar”, não estejam ligados aoprograma correcto. Acontece bastantes vezes o Winzip ficar encarregue deabrir os ficheiros deste tipo, uma vez que um ficheiro “.jar” não é mais do queum ficheiro comprimido. Então, neste caso, deves seguir os seguintes passos:

1. Abre o Windows Explorer

2. Clicka “Tools” > “Folder options”

3. Selecciona “File Types”

4. Escolhe o tipo de ficheiros “.jar”

5. Clicka “Advanced”

6. Selecciona “Open”

7. No campo da aplicação escolhida para abrir este tipo de ficheiros, coloca o seguinte, corrigindo o caminho até ao teu “java.exe”:"C:\Program Files\Java\j2re1.4.2_01\bin\java.exe" "-jar" "%1"

Prof. Herberto Graça Página 157 de 217

Page 158: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Os problemas parecem ficar por aqui, mas o grande problema é que umutilizador comum não deve ficar dependente de estes “pequenos detalhes”para correr as nossas aplicações. A nossa aplicação deve ser capaz de correr,independentemente da localização do ficheiro “java.exe”, e do nosso ficheiro“.jar”.

A solução passa por criar um ficheiro “.bat” que vai fazer os testesnecessários ao sistema, reunir informação sobre a localização dos ficheiros elançar a nossa aplicação. Esse ficheiro deverá conseguir ir buscar o caminho deinstalação do JAVA, de modo a se poder saber a localização do ficheiro“java.exe” e das directorias “\lib”, “\lib\ext” e da directoria actual do ficheiro“.bat” que deverá ser a mesma do nosso programa. Uma vez que se tem essainformação, basta chamar o programa com um comando do tipo:

%javahome%\bin\java.exe -cp %javahome%\lib -cp %javahome%\lib\ext -jar programa.jar

14.1.5 Exercícios1) Cria um ficheiro “.jar” para o programa que fizeste no subcapitulo

anterior e executa-o.

Prof. Herberto Graça Página 158 de 217

Page 159: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

14.2 Pacote instalador

Um instalador é simplesmente um ficheiro executável que contém osvários ficheiros de uma aplicação e, ao instalar a aplicação, coloca os váriosficheiros nos locais apropriados. É, portanto, um programa que instala outroprograma. Podemos ser nós próprios a fazer esse programa instalador, masexistem aplicações que nos ajudam a criar esses pacotes instaladores9.

14.2.1 Instalador multi-plataformaIzPack10 é uma aplicação em JAVA que cria instaladores em JAVA. Assim,

esta mesma aplicação funciona em vários sistemas operativos e pode criarinstaladores para vários sistemas operativos desde que tenham uma JVMdisponível. O mesmo instalador pode ser utilizado em vários sistemasoperativos, apesar de cada sistema operativo ter características e localizaçõesdiferentes.

14.2.2 Pacotes MSI (MS Windows)Um pacote “.msi” é um ficheiro de instalação de uma aplicação no sistema

operativo Windows. Ao instalar uma aplicação por este método, será criada,automaticamente, um conjunto de instruções para desinstalação da aplicação,bem como ficará disponível uma opção para, mais tarde, alterar a instalação.

Para criar pacotes MSI, podemos usar várias ferramentas, sendo as maisconhecidas, as seguintes:

Ferramenta Descrição

Advanced Installer11Aplicação para criar pacotes MSI, com suporte específicopara aplicações em JAVA.Licença: Proprietária (Tem vers. Com 30 dias de testes)

MS Visual StudioConjunto de aplicações de desenvolvimento de software, que também pode criar ficheiros de instalação MSI.Licença: Proprietária.

WiX (Windows Installer XML)

Conjunto de ferramentas livres para ajudar a criar um ficheiro MSI a partir de um documento XML. Pode ser integrado no MS Visual Studio ou usado na linha de comandos.Licença: “Common Public License”

7-ZipUm programa compressor/descompressor que pode descomprimir um ficheiro MSI.Licença: “GNU Lesser General Public License”

Tabela 25: Ferramentas de criação e/ou manipulação de MSIs

14.2.3 Pacotes DEB (Linux / Debian)Ubucompilator é um software em ambiente gráfico para criar pacotes

“.deb”.

9 Ver: http://en.wikipedia.org/wiki/List_of_installation_software

10 http://izpack.org/

11 http://www.advancedinstaller.com/java

Prof. Herberto Graça Página 159 de 217

Page 160: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

14.2.4 Pacotes RPM (Linux / Red Hat)

14.2.5 Exercícios1) Cria um instalador MSI (simples), para um dos programas gráficos

que criaste num capítulo anterior, utilizando a aplicação “AdvancedInstaller”.

Prof. Herberto Graça Página 160 de 217

Page 161: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

15 Javadocs

Javadoc é uma ferramenta que gera documentação html, a partir decomentários colocados no código.

15.1 Comentários javadoc

O javadoc reconhece os comentários especiais /** … */, que sãoassinalados a azul, pelo IDE Eclipse (os comentários comuns // e /* … */ sãoassinalados a verde).

Ao colocar comentários javadoc antes das declarações de classes,construtores, membros, interfaces e métodos, estaremos a anexar essescomentários à documentação html gerada pelo javadoc.

15.2 Etiquetas javadoc

As etiquetas (tags) javadoc são palavras chave reconhecidas pelo javadoc,que definem o tipo de informação que segue cada etiqueta.

/** Descrição da classe MyClass * * @author John Doe * @author Jane Doe * @version 6.0z Build 9000 Jan 3, 1970. */public class MyClass{

/** Descrição do campo myIntField */public int myIntField;

/** Descrição da classe MyClass() * * @throws MyException Descrição da excepção myException */public MyClass() throws myException{

// Blah Blah Blah...}

/** Descrição do método myMethod(int a, String b) * * @param a Descrição de a * @param b Descrição de b * @return Descrição de c */public Object myMethod(int a, String b){

Object c;// Blah Blah Blah...return c;

}}

Código 16: Exemplo da utilização de comentários javadoc, com etiquetas

Prof. Herberto Graça Página 161 de 217

Page 162: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Etiquetas Descrição

@author

Apenas nas classes e interfaces.Serve para identificar o autor. Podem ser utilizadas várias destas etiquetas na mesma unidade para designar vários autores.

@versionApenas nas classes e interfaces.Identifica a versão da classe ou interface.

@param [nome] [descrição] Apenas em métodos e construtores.Para descrever o parâmetro de um método ou construtor.

@return [descrição]Descreve os dados devolvidos por um método. É desnecessário para construtores e métodos que devolvem void.

@exception [nome] [descrição] Descreve uma excepção enviada por um método.

@throws Equivalente a @exception.

@deprecated [comentário]Acrescenta um comentário referindo que esta API não deverá ser usada por estar obsoleta.

@see “texto”@see <a href="URL">texto</a>

Acrescenta um comentário remetendo o leitor para outra documentação. Pode ser utilizado um link para a outra documentação.

@serial [descrição do campo] Usado para descrever um membro serializável.

@serialData [descrição dos dados]Para documentar os tipos de dados e a ordem em que são colocados na sua forma serializada.

@serialField [nome] [tipo] [desc.] Documenta um componente ObjectSteamField de um membro serialPersistentFields uma classe serializável.

@since [texto]Especifica que esta unidade existe desde a versão do software, que é assinalada. Por ex.: @since 1.3

{@link} Serve para colocar um link para outro método, numa descrição.

{@docRoot}

Para referenciar um documento, dentro de um comentário.Por ex.: /** * See the <a href="{@docRoot}/copyright.html">Copy</a>. */

Tabela 26: Etiquetas javadoc

15.3 Gerar a documentação

15.3.1 Pela linha de comandosPara gerar a documentação das classes, pela linha de comandos, chamamos o utilitário,

seguido dos ficheiros sobre os quais queremos criar a documentação html.

No entanto, também temos disponíveis várias opções para gerar a documentação. A sintaxe de utilização é: “javadoc [opções] [ficheiros]”.

O seguinte exemplo cria e guarda, na mesma pasta, a documentação relativa às classes A, B e todas as classes que se encontrem na pasta “c:\OtherWork\”:

c:\MyWork> Javadoc A.java B.java c:\OtherWork\*.java

Código 17: Exemplo da utilização do javadoc, em linha de comandos

No exemplo seguinte, a documentação é gerada com a versão e os membros privados de

Prof. Herberto Graça Página 162 de 217

Page 163: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

todos os ficheiros “.java” presentes nas pastas “c:\MySource\” e “c:\YourSource\” que referenciem ficheiros em “c:\MyLib”, guardando a documentação em “c:\MyDoc”:

c:\> Javadoc -version -private -d c:\MyDoc -sourcepathlist c:\MySource;c:\YourSource\ -classpath c:\MyLib

Código 18: Exemplo da utilização do javadoc, em linha de comandos

Opção Descrição

-authorA documentação incluirá uma secção sobre os autores.

-classpath [path] Especifica um caminho para procurar os ficheiros “.class” referenciados.

-classpathlist [path];[path];...;[path] Especifica uma lista de localizações (separadas por ;) onde procurar ficheiros “.class”.

-d [path] Especifica onde será guardada a documentação gerada.

-privateA documentação incluirá os membros privados. (pordefeito, apenas são incluídos os membros públicose protegidos)

-sourcepath [path]Especifica ficheiros “.java” com os quais gerar documentação.

-sourcepathlist [path];[path];...;[path] Especifica uma lista de localizações (separadas por ;) onde procurar ficheiros “.java”.

-versionA documentação incluirá uma secção sobre as versões.

Tabela 27: Algumas das opções na linha de comandos do javadoc

15.3.2 Através do IDE EclipseO IDE Eclipse dispõe de um automatismo para gerar comentários javadoc,

bem como uma interface gráfica para gerar documentação, utilizando aferramenta javadoc.

15.3.2.1 Gerar comentários javadoc

1. Colocamos o cursor na declaração da classe ou membro;

2. Click direito → Source → Generate Element Comment;

3. São gerados comentários javadoc com as etiquetas adequadas, faltando apenas colocar as descrições.

15.3.2.2 Gerar a documentação javadoc

1. File → Export;

2. Seleccionamos “javadoc”;

3. Colocamos o caminho para a ferramenta javadoc, por ex.“c:\j2sdk1.5.0\bin\javadoc.exe”;

4. Escolhemos o projecto(s)/pacote(s)/classe(s) sobre os quaispretendemos criar a documentação;

5. Escolhemos a visibilidade dos membros que queremos criardocumentação;

6. Escolhemos o local onde será guardada a documentação;

Prof. Herberto Graça Página 163 de 217

Page 164: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

7. Nas páginas seguintes podemos ainda especificar mais opções, masas que foram especificadas acima, são as mais comuns, pelo quepodemos simplesmente seleccionar “finish”.

15.4 Exercícios

1) Crie a documentação completa das seguintes classes:

a) Classe MyClass, presente no capítulo 13.2.

b) Classe KeyboardInput, presente no anexo 2.

c) Classe MainUI, presente no anexo 2.

d) Classe ReportViewer, presente no anexo 2.

Prof. Herberto Graça Página 164 de 217

Page 165: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

16 Java Server Pages e Servlets

16.1 Introdução

16.1.1 O que são as ServletsServlets são programas em JAVA, que correm num servidor web e geram

HTML, criando quilo que se costuma chamar um website dinâmico. São os CGIda tecnologia JAVA. Este tipo de aplicações são úteis por várias razões:

• A página web é criada com dados introduzidos peloutilizador. Por exemplo as páginas de resultados dos motores debuscas são geradas desta forma, tal como o processamento depedidos nas lojas on-line.

• Os conteúdos mudam com frequência. Por exemplo as previsõesmeteorológicas, as noticias de um jornal on-line, as pautas de notasde uma escola ou a ementa do refeitório de uma escola.

• A página pode usar informações de uma Base de Dados deuma empresa. Por exemplo uma loja on-line que disponibilizeinformação sobre stocks de produtos, ou as faltas de alunos de umaescola.

16.1.2 Vantagens das ServletsAs servlets JAVA são mais eficientes, fáceis de usar, poderosas, portáveis e

baratas que os tradicionais CGI e alternativas semelhantes. Além disso osprogramadores de servlets são melhor pagos que os programadores de Perl!

• Eficiência: Os CGI tradicionais iniciam um novo processo por cadapedido http. Se o CGI vai executar um processamento simples erápido até pode acontecer que a criação de um novo processodemore mais tempo que a execução do CGI em si! Com as Servlets,a máquina virtual fica sempre a correr e cada pedido é executadopor um processo bastante mais leve que um processo do SistemaOperativo, utilizado pelos CGI. Do mesmo modo, se houver Npedidos para um determinado CGI, esse código é carregado emmemória N vezes, enquanto que com as servlets existem váriosprocessos mas apenas uma cópia do código.

• Conveniência: Se já sabemos JAVA, para quê aprender outralinguagem de programação?! Além disso as servlets têm umagrande quantidade de apoios ao HTML, http headers, sessões,cookies, etc.

• Poderosas: As servlets conseguem fazer várias coisas que os CGInão conseguem. Por exemplo partilhar dados entre servlets, manterinformação de pedido para pedido, simplificando o processamento

Prof. Herberto Graça Página 165 de 217

Page 166: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

de sessões e a manutenção de processamentos, em cache.

• Portabilidade: São escritas em JAVA e tem uma API standartizada.Como consequência, uma servlet corre com pouquíssimas, ounenhumas modificações, em vários servidores.

• Baixo custo: Existem vários servidores capazes de correr servlets eque são de baixo custo ou de borla, sendo o melhor o APACHE, atémesmo para websites de grande volume e processamento!

16.1.3 O que são as JSPAs JSP permitem-nos misturar HTML estático com HTML gerado

dinamicamente. Por exemplo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML>

<HEAD><TITLE>Welcome to Our Store</TITLE>

</HEAD><BODY>

<H1>Welcome to Our Store</H1><!-- User name is "New User" for first-time visitors --> <SMALL>Welcome, <% out.println(Utils.getUserNameFromCookie(request)); %> To access your

account settings, click<A HREF="Account-Settings.html">here.</A></SMALL><P>

Regular HTML for all the rest of the on-line store's Web page.</P>

</BODY></HTML>

16.1.4 Vantagens das JSPEstas são algumas das vantagens relativamente a outras tecnologias:

• ASP: ASP é uma tecnologia Microsoft. JSP é escrito em JAVA, não éuma tecnologia Microsoft e portanto é mais poderosa e portável.

• Servlets: JSP não nos dá mais que as servlets, no entanto é muitomais prático escrever e modificar HTML embebido de JSP do quecentenas de println para gerar HTML a partir de servlets. Além dissopode-se separar facilmente a tarefa de programação das servlets datarefa de construção do design da página com HTML.

• JavaScript: JavaScript consegue gerar HTML dinâmico no lado docliente, o que é útil, mas apenas quando a informação dinâmica ébaseada no ambiente do cliente. Pode aceder a cookies, forms, http,mas não a bases de dados ou qualquer informação localizada noservidor.

Prof. Herberto Graça Página 166 de 217

Page 167: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

16.2 O servidor

16.2.1 DownloadExistem muitas opções disponiveis, e até muitas que são software livre,

por exemplo:

• Blazix from Desiderata Software (1.5 Megabytes, JSP, Servlets andEJBs)

• TomCat from Apache (6.7 Megabytes)

• WebLogic from BEA Systems (44 Megabytes, JSP, Servlets and EJBs)

• WebSphere from IBM (105 Megabytes, JSP, Servlets and EJBs)

Nós vamos utilizar o servidor TomCat, que é software livre e um dos maisutilizados.

O seu download pode ser feito em:

• http://tomcat.apache.org/

Vamos fazer download dos seguintes pacotes:

• Windows Service Installer

• Administration Web Aplication (ZIP)

16.2.2 InstalaçãoVamos então instalar o tomcat na localização “…\Apache Group\Tomcat

X.X\”. As opções de instalação são as opções por defeito e portanto a suainstalação é simples.

Após instalar o tomcat, vamos descomprimir a pasta da aplicação deadministração e copia-la para a pasta de instalação do tomcat, sobrepondo osficheiros que seja necessário.

Prof. Herberto Graça Página 167 de 217

Page 168: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

16.2.3 Configuração do contexto de desenvolvimento 16.2.3.1 A estrutura de directórios

Em primeiro lugar vamos criar uma estrutura de directórios especifica,algures no nosso computador, e que vai ser o local onde vamos colocar todo onosso website. Essa estrutura deve ser a seguinte:

O directório “dev” pode ser por exemplo em “C:\...\My Documents\MyWeb Sites\dev\” e então os ficheiros HTML e JSP ficariam localizados em“C:\...\My Documents\My Web Sites\dev\web\”.

16.2.3.2 Definição do contexto de aplicação web

Depois de criada a estrutura de pastas, é necessário que o tomcat saibaonde está essa estrutura de pastas e quais as suas características. Para que otomcat saiba que essa estrutura existe, apenas necessitamos de criar umficheiro XML com as informações necessárias.

Uma vez que a raiz da estrutura de pastas é “dev”, o ficheiro com aconfiguração do contexto de desenvolvimento será “dev.xml” e será colocadoem: “CATALINA_HOME/conf/Catalina/localhost/dev.xml”.

O conteúdo desse ficheiro deve ser o seguinte:

<?xml version="1.0" encoding="iso-8859-1"?>

<Context path="/dev" docBase="C:/.../dev/web" reloadable="true" crossContext="true" debug="3"><Logger

className="org.apache.catalina.logger.FileLogger"prefix="localhost_dev_log." suffix=".txt" timestamp="true"verbosity="4"

/></Context>

A tag “Logger” está relacionada com o registo de erros, em que o campoverbosity designa o tipo de erros que ficam registados:

• 0 Apenas erros graves

• 1 Erros

Prof. Herberto Graça Página 168 de 217

Ilustração 44: Estrutura de directórios no desenvolvimento de servlets

Page 169: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

• 2 Avisos

• 3 Informação

• 4 Debug (tudo)

O contexto de desenvolvimento também pode ser configurado atravéz daferramenta de administração. Para isso, vamos abrir a página padrão dotomcat (http://localhost:8080) e abrir o link para a ferramenta de administração“Tomcat Administration”.

• Fazemos login com o utilizador criado na instalação (admin).

• Utilizando o menu à esquerda navegamos até: Tomcat Server >Service (Catalina) > Host (localhost)

• Utilizando a área principal escolhemos: Host Actions > Create NewContext

• Introduza os dados, tal como no ficheiro XML descrito acima.

No entanto devo chamar a atenção para o facto de que esta ferramentapode não funcionar correctamente.

16.2.3.3 Configuração do contexto de aplicação web

Agora vamos criar um ficheiro com a configuração específica da nossaaplicação. Esse ficheiro será colocado na pasta “WEB-INF” e vai ter o nome“web.xml”. Esse ficheiro é chado de contexto da aplicação ou contexto dedesenvolvimento e irá conter as seguintes informações:

• Informações textuais de título e comentário de descrição docontexto, úteis para identificação e documentação.

• Uma definição servlet associada à classe do invocador genéricoInvokerServlet do Tomcat, usada para executar os servlets quecriarmos.

• Um mapeamento (elemento servlet-mapping) genérico associando opadrão de endereço URI /servlet/* à definição do invoker criada,indicando que qualquer nome dentro do caminho /servlet/ nestecontexto deve ser reconhecido como servlet e portanto repassadoao invoker do Tomcat para execução

O nosso ficheiro web.xml terá o seguinte conteúdo:

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

<display-name>Desenvolvimento</display-name><description>

Descritor do contexto de desenvolvimento.</description>

<servlet><servlet-name>dev-invoker</servlet-name><servlet-class>

Prof. Herberto Graça Página 169 de 217

Page 170: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

org.apache.catalina.servlets.InvokerServlet</servlet-class><init-param>

<param-name>debug</param-name><param-value>0</param-value>

</init-param><load-on-startup>2</load-on-startup>

</servlet>

<servlet-mapping><servlet-name>dev-invoker</servlet-name><url-pattern>/servlet/*</url-pattern>

</servlet-mapping></web-app>

No final deste processo resta-nos reiniciar o tomcat para que ele vá ler asnovas configurações.

16.2.3.4 Testar o contexto de desenvolvimento

Para testar se o nosso contexto de desenvolvimento está a funcionarcorrectamente, vamos criar um ficheiro “index.html” e colocá-lo na pasta“dev\web\”.

Agora vamos tentar aceder ao nosso contexto de desenvolvimento atravézdo endereço http://localhost:8080/dev/. Se o for retornado algum erro, vamoster de rever todos os ficheiros de configuração e procurar erros. O mais comumé que sejam erros de sintaxe.

16.2.3.5 Bibliotecas de servlets

Para podermos compilar servlets vamos ter de adicionar as bibliotecas dotomcat à variável de sistema CLASSPATH:

CATALINA_HOME/common/lib/servlet-api.jar

CATALINA_HOME/common/lib/jsp-api.jar

Em que CATALINA_HOME é o caminho de instalação do tomcat.

Para além disto, caso seja necessário utilizar classes de terceiros,devemos colocar os ficheiros JAR com essas calasses, na pasta “WEB-INF\lib\”,para que o tomcat as encontre.

16.2.3.6 Testar as servlets

Para podermos compilar servlets vamos ter de adicionar as bibliotecas dotomcat à variável

16.2.3.7 Bibliotecas de servlets

Para podermos compilar servlets vamos ter de adicionar as bibliotecas dotomcat à variável

16.2.3.8 Analisar os logs

Para podermos compilar servlets vamos ter de adicionar as bibliotecas dotomcat à variável

Prof. Herberto Graça Página 170 de 217

Page 171: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

16.3 JSP

16.3.1 DownloadExistem muitas opções disponíveis, e até muitas que são software livre,

por exemplo:

Prof. Herberto Graça Página 171 de 217

Page 172: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Bibliografia

Bell, Doug (1997)Make Java fast: Optimize!(http://www.javaworld.com/jw-04-1997/jw-04-optimize.html)

DuBois, Paul (2003)Writing JDBC Applications with MySQL(http://www.kitebird.com/articles/jdbc.html)

Hardwick, Jonathan (2003)Java Optimization(http://www.cs.cmu.edu/~jch/java/optimization.html)

Lozano, F. (?). Programação Orientada a Objectos Java (http://www.lozano.eti.br/apostilas/java/oo-java.pdf)

MySQL Enterprise (2009)MySQL Connector/J (http://dev.mysql.com/downloads/connector/j/)

Ahammad, Shamsuddin (2010)Packt Publishing.Ireport 3.7

Rodrigues, B. (2009). Programação em Java – Iniciação(http://pplware.sapo.pt/2009/12/10/programacao-em-java-%E2%80%93-iniciacao-por-bruno-rodrigues/)

Rodrigues, B. (2010). Programação em Java – Iniciação II (http://pplware.sapo.pt/2010/01/12/mensagem-de-teste/)

Ruiz, E. (2008). Programação Orientada a Objectos (http://dfm.ffclrp.usp.br/~evandro/ibm1030/)

Sierra K. & Bates, B. (2003). SUN Certified Programmer & Developer for JAVA 2 Study GuideMcGraw Hill

SUN (2005), The JAVA tutorial(http://java.sun.com/docs/books/tutorial/)

The Middleware Company (2003)Optimizing Java Applications(http://www.theserverside.com/news/1364651/Optimizing-Java-Applications)

Prof. Herberto Graça Página 172 de 217

Page 173: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Índice de Ilustrações

Ranking da utilização das Linguagens de Programação.............................................................14

Exemplo de Objecto Computador..............................................................................................16

Exemplo do Objecto ”Cao”.........................................................................................................17

Comunicação entre Objectos.....................................................................................................18

Comunicação entre Objectos.....................................................................................................20

Polimorfismo..............................................................................................................................23

Organização de um projecto java..............................................................................................27

Estrutura de um ficheiro de código, em C e em JAVA.................................................................27

Comentário de classe................................................................................................................29

Comentários de membros..........................................................................................................30

Generalização dos comentários ao código.................................................................................30

Lista duplamente encadeada.....................................................................................................45

Exemplo de funcionamento de threads.....................................................................................61

Pseudocódigo de utilização de streams de leitura e escrita.......................................................65

Árvores de classes das streams de caracteres...........................................................................66

Árvores de classes das streams de bytes..................................................................................67

Arvore de classes da classe Applet............................................................................................70

Acesso a BD, no modelo de dois nós.........................................................................................88

Acesso a BD, no modelo de três nós..........................................................................................89

Relatório de categorias, em modo de edição...........................................................................117

Relatório de categorias, em modo de visualização..................................................................118

Painel “Padding and Borders”..................................................................................................119

Painel “Field pattern”...............................................................................................................119

Painel “Properties”...................................................................................................................120

Relatório de produtos agrupados, em modo de edição............................................................121

Relatório de produtos agrupados, em modo de visualização...................................................121

Escolha do tipo de gráfico........................................................................................................124

Escolha dos identificadores de cada fatia do gráfico...............................................................124

Vista do gráfico, em modo de edição.......................................................................................125

Colocação das etiquetas correctas no gráfico..........................................................................125

Configuração das propriedades do gráfico...............................................................................126

Vista do gráfico final, em modo de visualização......................................................................126

1º Relatório factura, em modo de edição.................................................................................127

Prof. Herberto Graça Página 173 de 217

Page 174: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Relatório factura com totais, em modo de edição....................................................................128

Relatório factura com totais, em modo de visualização...........................................................128

Relatório factura com total da factura, em modo de visualização...........................................128

Relatório factura com total da factura, em modo de visualização...........................................129

Relatório factura com o número da factura, em modo de edição............................................130

Estrutura do projecto, com um subpacote para relatórios.......................................................132

Exportação de um projecto......................................................................................................162

Exportação de um projecto para um JAR..................................................................................163

Escolha dos pacotes a exportar...............................................................................................163

Finalização da exportação........................................................................................................164

Estrutura de directórios no desenvolvimento de servlets........................................................175

Prof. Herberto Graça Página 174 de 217

Page 175: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Índice de Tabelas

Tipos de dados nativos..............................................................................................................31

Descrição de alguns operadores................................................................................................33

Precedência de operadores........................................................................................................33

Tipos de estruturas de controlo existentes em JAVA..................................................................34

Palavras-chave da declaração de classes..................................................................................47

Palavras-chave da declaração de membros...............................................................................48

Níveis de acesso possíveis de atribuir a um membro................................................................48

Os métodos da classe "Applet"..................................................................................................71

Métodos para desenho de applets.............................................................................................72

Atributos específicos da tag <APPLET>.....................................................................................74

Pacotes utilizados na construção de GUI....................................................................................76

Aspectos disponibilizados pelo JAVA...........................................................................................77

Argumentos para selecção de um aspecto visual......................................................................77

Os Layout Managers..................................................................................................................80

Acções que resultam em eventos..............................................................................................82

Lista de plugins de Bases de Dados...........................................................................................91

Tipos de movimentação permitidos um objecto ResultSet.........................................................96

Tipos de permissões de acesso a um objecto ResultSet............................................................96

Métodos para circular na tabela de dados de um objecto da classe ResultSet..........................97

Alguns métodos para aceder aos dados de uma linha da tabela de dados................................98

Métodos relevantes na actualização de dados da base de dados............................................100

Métodos disponíveis, na classe CallableStatement, para executar stored procedures.............105

Tipos de parâmetros possíveis nos stored procedures.............................................................105

Secções de um relatório..........................................................................................................118

Ferramentas de criação e/ou manipulação de MSIs.................................................................166

Etiquetas javadoc....................................................................................................................169

Algumas das opções na linha de comandos do javadoc..........................................................170

Prof. Herberto Graça Página 175 de 217

Page 176: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Índice de Código

Comando para análise de bytecode.........................................................................................145

Teste de rapidez de concatenação de strings com o operador "+=".......................................146

Teste de rapidez de concatenação de strings com um objecto StringBuilder...........................146

Resultados dos testes de rapidez de concatenação de strings ...............................................146

Método que devolve o grau de ocupação da memória ...........................................................146

Substituição de operações de divisão e multiplicação ............................................................147

Substituição de cálculos redundantes......................................................................................147

Movimentação de instruções redundantes..............................................................................147

Redução de ciclos....................................................................................................................148

Optimização de ciclos..............................................................................................................148

Inicialização de arrays.............................................................................................................148

Operações com conversões.....................................................................................................149

Chamada de métodos e blocos sincronizados..........................................................................150

Como evitar chamar métodos sincronizados aninhados..........................................................151

Como evitar a repetição de casts............................................................................................151

Exemplo da utilização de comentários javadoc, com etiquetas...............................................168

Exemplo da utilização do javadoc, em linha de comandos......................................................169

Exemplo da utilização do javadoc, em linha de comandos......................................................170

Prof. Herberto Graça Página 176 de 217

Page 177: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Anexos

Prof. Herberto Graça Página 177 de 217

Page 178: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Anexo 1: Alguns componentes do pacote swing

Para ter uma explicação do funcionamento destes componentes deve ser consultada a seguinte página: http://java.sun.com/docs/books/tutorial/uiswing/components/components.html

Tipo Classe Exemplo

Applet java.applet.Applet -

Caixa de diálogo javax.swing.JDialog

Janela javax.swing.JFrame

Painel javax.swing.JPanel

Painel com barras de scroll javax.swing.JScrollPane

Painel dividido javax.swing.JSplitPane

Painel com tabulações javax.swing.JTabbedPane

Barra de ferramentas javax.swing.JToolBar

Janela interior de outrajanela

javax.swing.JInternalFrame

Prof. Herberto Graça Página 178 de 217

Page 179: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Tipo Classe Exemplo

Painel com camadas javax.swing.JLayeredPane

Painel de raiz javax.swing.JRootPane

Botões javax.swing.JButton

Caixa de listagem javax.swing.JComboBox

Lista javax.swing.JList

Menu javax.swing.JMenu

Regulador javax.swing.JSlider

Caixa de numeração javax.swing.JSpinner

Caixa de texto javax.swing.JTextField

Etiquetasjavax.swing.JLabel

Barra de progressão javax.swing.JProgressBar

Caixa de dicas javax.swing.JToolTip

Prof. Herberto Graça Página 179 de 217

Page 180: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Tipo Classe Exemplo

Caixa para escolher umacôr

javax.swing.JColorChooser

Caixa para escolher umacôr

javax.swing.JFileChooser

Tabela javax.swing.JTable

Texto javax.swing.text.JTextComponent

Arvore javax.swing.JTree

Prof. Herberto Graça Página 180 de 217

Page 181: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Anexo 2: Classes utilizadas

Capítulo 4Classe KeyboardInput: utilizada para dar entrada de dados pela consola.

package xpto;

import java.io.* ;/** * A simple input class to read values typed at the command line. If * an error occurs during input, any exceptions thrown are caught and * a default value returned. * * @version 1.0 1.7.97 * @author Graham Roberts */public class KeyboardInput{ /** * The stream that is the keyboard wrapped so that we can read * from it sensibly. */ private final BufferedReader in = new BufferedReader(new InputStreamReader(System.in)) ; /** * Read an int value from keyboard input. */ public final synchronized int readInteger(){ // // The place to hold the data received from the keyboard so // that we can parse it to find the int value. // String input = "" ; // // Read a String of characters from the keyboard. // try{ input = in.readLine() ; }catch (IOException e) {} // // Parse the String to construct an int value. // int val = 0 ; try{ val = Integer.parseInt(input) ; } catch (NumberFormatException e) {} return val ; } /** * Read a long value from keyboard input. */ public final synchronized long readLong(){ // // The place to hold the data received from the keyboard so // that we can parse it to find the long value. // String input = "" ; // // Read a String of characters from the keyboard. // try{ input = in.readLine() ; } catch (IOException e) {} // // Parse the String to construct a long value. // long val = 0L ; try{ val = Long.parseLong(input) ; } catch (NumberFormatException e) {}

Prof. Herberto Graça Página 181 de 217

Page 182: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

return val ; } /** * Read a double value from keyboard input. */ public final synchronized double readDouble(){ // // The place to hold the data received from the keyboard so // that we can parse it to find the double value. // String input = "" ; // // Read a String of characters from the keyboard. // try{ input = in.readLine() ; } catch (IOException e) {} // // Parse the String to construct a double value. // double val = 0.0D ; try{ val = (Double.valueOf(input)).doubleValue() ; } catch (NumberFormatException e) {} return val ; } /** * Read a float value from keyboard input. */ public final synchronized float readFloat(){ // // The place to hold the data received from the keyboard so // that we can parse it to find the long value. // String input = "" ; // // Read a String of characters from the keyboard. // try{ input = in.readLine() ; } catch (IOException e) {} // // Parse the String to construct a float value. // float val = 0.0F ; try{ val = (Float.valueOf(input)).floatValue() ; } catch (NumberFormatException e) {} return val ; } /** * Read a char value from keyboard input. */ public final synchronized char readCharacter(){ // // No need to parse anything, just get a character and return // it.. // char c = ' ' ; try{ c = (char)in.read() ; } catch (IOException e) {} return c ; } /** * Read an String value from keyboard input. */ public final synchronized String readString(){ // // No need to parse anything, just get a string and return // it.. // String s = ""; try{ s = in.readLine() ; }

Prof. Herberto Graça Página 182 de 217

Page 183: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

catch (IOException e) {} return s ; }}

Capítulo 10Classe MainUI: Cria uma aplicação de teste, de onde se podem chamar

vários relatórios.

package ui;

import ui.reports.ReportViewer;import java.beans.PropertyVetoException;import java.util.HashMap;import javax.swing.JOptionPane;

/**** @author Shamsuddin Ahammad* @author Herberto Graça*/public class MainUI extends javax.swing.JFrame {

private javax.swing.JDesktopPane desktopPane;private javax.swing.JMenuBar menuBar;private javax.swing.JMenu reportsMenu;private javax.swing.JMenuItem productListMenuItem;private javax.swing.JMenuItem salesDetailsMenuItem;//====================================================================/** Creates new form MainUI */public MainUI() {

initComponents();setSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());

}//====================================================================/** * This method is called from within the constructor to initialize the form. */private void initComponents() {

desktopPane = new javax.swing.JDesktopPane();menuBar = new javax.swing.JMenuBar();//---------------------------------------------------------------reportsMenu = new javax.swing.JMenu();reportsMenu.setText("Reports");productListMenuItem = new javax.swing.JMenuItem();productListMenuItem.setText("Categorias");productListMenuItem.addActionListener(

new java.awt.event.ActionListener() {public void actionPerformed(java.awt.event.ActionEvent evt){

categoriasMenuItemActionPerformed(evt);}

});reportsMenu.add(productListMenuItem);salesDetailsMenuItem = new javax.swing.JMenuItem();salesDetailsMenuItem.setText("Sales Details");salesDetailsMenuItem.addActionListener(

new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt){

facturasMenuItemActionPerformed(evt);}

});reportsMenu.add(salesDetailsMenuItem);menuBar.add(reportsMenu);//---------------------------------------------------------------setJMenuBar(menuBar);//---------------------------------------------------------------setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());getContentPane().setLayout(layout);layout.setHorizontalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(

Prof. Herberto Graça Página 183 de 217

Page 184: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

desktopPane,javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE

));layout.setVerticalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(

desktopPane,javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE

));pack();

}//====================================================================private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {

System.exit(0);}//====================================================================private void categoriasMenuItemActionPerformed(java.awt.event.ActionEvent evt){

String localizacao="reports/", nomeFicheiro="categorias";try{

ReportViewer myiReportViewer = new ReportViewer(localizacao+nomeFicheiro+".jasper");

myiReportViewer.setBounds(0, 0, desktopPane.getWidth(), desktopPane.getHeight());

myiReportViewer.setVisible(true);desktopPane.add(myiReportViewer);myiReportViewer.setSelected(true);

}catch (PropertyVetoException pve){

pve.printStackTrace();}

}//====================================================================private void facturasMenuItemActionPerformed(java.awt.event.ActionEvent evt){

String localizacao="reports/", nomeFicheiro="factura2";String input=JOptionPane.showInputDialog("Introduza o numero da encomenda");if(input!=null){

try{int numFactura=Integer.parseInt(input);HashMap parameters=new HashMap();parameters.put( "numFactura" ,numFactura);ReportViewer myiReportViewer = new

ReportViewer(localizacao+nomeFicheiro+".jasper",parameters);myiReportViewer.setBounds(0, 0, desktopPane.getWidth(),

desktopPane.getHeight());myiReportViewer.setVisible(true);desktopPane.add(myiReportViewer);myiReportViewer.setSelected(true);

}catch (PropertyVetoException pve){

pve.printStackTrace();}catch(NumberFormatException nfe){

JOptionPane.showMessageDialog(this,"Introduza apenas numeros inteiros entre 10248 e 11077");

}}

}//====================================================================/*** @param args the command line arguments*/public static void main(String args[]) {

java.awt.EventQueue.invokeLater(new Runnable() {public void run() {

new MainUI().setVisible(true);}

});}

}

Classe ReportViewer: trabalha directamente com os relatórios,

Prof. Herberto Graça Página 184 de 217

Page 185: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

preparando a sua pré-visualização ou conversão.

package ui.reports;

import java.awt.BorderLayout;import java.awt.Container;import java.sql.Connection;import java.util.HashMap;

import BD.BD;import net.sf.jasperreports.engine.JRException;import net.sf.jasperreports.engine.JasperExportManager;import net.sf.jasperreports.engine.JasperFillManager;import net.sf.jasperreports.engine.JasperPrint;import net.sf.jasperreports.view.JRViewer;

/*** @author Shamsuddin Ahammad* @author Herberto Graça*/

public class ReportViewer extends javax.swing.JInternalFrame {

/** Creates new form ReportViewer */private ReportViewer(){

super("Report Viewer",true,true,true,true);initComponents();setBounds(10,10,600,500);setDefaultCloseOperation(DISPOSE_ON_CLOSE);

}

public ReportViewer(String fileName){this(fileName,null);

}/** * Cria uma janela para visualizar o relatório dentro de um outro programa * * @param fileName nome do ficheiro, com caminho e extensão * @param parameter parametros do relatório, se os tiver. Se não tiver inserimos null. */public ReportViewer(String fileName,HashMap parameter){

this();try{

//Create the connectionConnection con = BD.getConnection();

//Vai a BD buscar os dados do relatorio//Here the parameter file should be in .jasper extension i.e., the compiled reportJasperPrint print = JasperFillManager.fillReport( fileName, parameter, con);

JRViewer viewer=new JRViewer(print);Container c=getContentPane();c.setLayout(new BorderLayout());c.add(viewer);

}catch(JRException jre){

jre.printStackTrace();}

}

/** * Cria e guarda o relatorio em formato PDF, na mesma localizaçao do relatorio compilado * * @param caminho caminho para o relatorio * @param fileName nome do ficheiro do relatorio, sem a extensao * @param parameter parametros do relatorio, se os tiver. Se nao tiver inserimos null. * @throws IllegalAccessException * @throws InstantiationException */public static void convertToPDF(String caminho, String fileName, HashMap parameter){

try{//Create the connectionConnection con = BD.getConnection();

//Vai a BD buscar os dados do relatorio//Here the parameter file should be in .jasper extension i.e., the compiled reportJasperPrint print = JasperFillManager.fillReport( caminho+fileName+".jasper",

parameter, con);

//exporta o relatorio em PDFJasperExportManager.exportReportToPdfFile(print, caminho+fileName+".pdf");

Prof. Herberto Graça Página 185 de 217

Page 186: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

}catch(JRException jre){

jre.printStackTrace();}

}

/** * This method is called from within the constructor to initialize the form.*/private void initComponents() {

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());getContentPane().setLayout(layout);layout.setHorizontalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 394, Short.MAX_VALUE)

);layout.setVerticalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 274, Short.MAX_VALUE)

);pack();

}

/*** @param args the command line arguments* @throws IllegalAccessException * @throws InstantiationException */public static void main(String args[]) throws InstantiationException, IllegalAccessException {

ReportViewer.convertToPDF("reports/","categorias", null);}

}

Prof. Herberto Graça Página 186 de 217

Page 187: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Anexo 3: Resolução dos exercícios

Exercícios do Cap. 4.111)

public class Ex_01 {public static void main(String[] args){

System.out.println("Ola mundo!");}

}

2)

import java.io.*;

public class Ex_02 {

static int numero;

public static void main(String[] args) throws IOException {

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));String a=null;

System.out.print("Insira um número: ");a=ler.readLine();//numero=3;

//transforma as strings em inteiros e depois em reais (float)numero=Integer.parseInt(a);

System.out.println();System.out.println("O número seguinte é: " + (numero+1));

}}

3)

import java.io.*;

public class Ex_03 {

static int numero;

public static void main(String[] args) throws IOException {

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));String a=null;

System.out.println("calculo de x²+x*2+3");System.out.print("Insira x: ");a=ler.readLine();//numero=3;

//transforma as strings em inteiros e depois em reais (float)numero=Integer.parseInt(a);

System.out.println();System.out.println("O número lido foi "+numero+" e o resultado é " +

(numero*numero+2*numero+3));}

}

4)

import java.io.*;

Prof. Herberto Graça Página 187 de 217

Page 188: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

public class Ex_04 {

public static void main(String[] args) throws IOException {

String a=null ,b=null ;float x,y;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//lê os dados do teclado, como stringsSystem.out.print("Insira x: ");a=ler.readLine();System.out.print("Insira y: ");b=ler.readLine();

//transforma as strings em inteiros e depois em reais (float)x=Integer.parseInt(a);y=Integer.parseInt(b);

//faz os calculos e manda os resultados para foraSystem.out.println();System.out.println("soma: "+ (x+y));System.out.println("diferença: "+ (x-y));//se x e y forem do tipo int, o resultado da zero e nao 0.833 :System.out.println("divisão: "+ (x/y)); System.out.println("multiplicação: "+ (x*y));

}}

5)

import java.io.*;

public class Ex_05 {

public static void main(String[] args) throws IOException {String a=null ,b=null ;float x,y;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira x: ");a=ler.readLine();System.out.print("Insira y: ");b=ler.readLine();

//transforma as strings em inteiros e depois em reais (float)x=Integer.parseInt(a);y=Integer.parseInt(b);

System.out.println("A média é: "+((x+y)/2));}

}

6)

import java.io.*;

public class Ex_06 {

public static void main(String[] args) throws IOException {String a=null;float x,y;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira x: ");a=ler.readLine();

//transforma as strings em inteiros e depois em reais (float)x=Integer.parseInt(a);

//calcula a raiz quadraday=(float) Math.sqrt(x);

Prof. Herberto Graça Página 188 de 217

Page 189: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

System.out.println("A raiz quadrada é: "+y);}

}

7)

import java.io.*;

public class Ex_07 {

public static void main(String[] args) throws IOException {String a=null;float x,y;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//lê os dados do teclado, como stringsSystem.out.print("Insira x: ");a=ler.readLine();

//transforma as strings em inteiros e depois em reais (float)x=Integer.parseInt(a);

//calcula a raiz quadraday=(float) Math.pow(x,2);

System.out.println("O quadrado de "+x+" é: "+y);}

}

8)

import java.io.*;

public class Ex_08 {

public static void main(String[] args) throws IOException {

String a=null ,b=null ;float x,y;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira o cateto a: ");a=ler.readLine();System.out.print("Insira o cateto b: ");b=ler.readLine();

//transforma as strings em inteiros e depois em reais (float)x=Integer.parseInt(a);y=Integer.parseInt(b);

//faz os calculos e manda os resultados cá para foraSystem.out.println("A hipotenusa do trinagulo com os catetos a="+a+" e b="+b+" é: "+

(Math.sqrt(Math.pow(x,2)+Math.pow(y,2))));}

}

9)

import java.io.*;import java.text.DecimalFormat;

public class Ex_09 {

public static void main(String[] args) throws IOException {String a=null;float x;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira x: ");a=ler.readLine();

Prof. Herberto Graça Página 189 de 217

Page 190: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

//transforma a string em reais (float)x=Float.parseFloat(a);

DecimalFormat df2 = new DecimalFormat("###.##");System.out.println(df2.format(x));

System.out.println((int)x);

System.out.println(Math.round(x));}

}

10)

import java.io.*;

public class Ex_10 {

public static void main(String[] args) throws IOException {String a=null;int x;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira o multiplicador: ");a=ler.readLine();

//transforma as strings em inteiros e depois em reais (float)x=Integer.parseInt(a);

for (int i=0; i<11; i++){System.out.println(" "+x+"x"+i+"= "+x*i);

}}

}

11)

import java.io.*;

public class Ex_11 {

public static void main(String[] args) throws IOException {String nome=null ,ano=null, ano_nasc_str=null, turma=null, nota_str=null;int ano_nasc, idade;float nota;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira o nome: ");nome=ler.readLine();System.out.print("Insira o ano: ");ano=ler.readLine();System.out.print("Insira o ano de nascimento: ");ano_nasc_str=ler.readLine();ano_nasc=Integer.parseInt(ano_nasc_str);System.out.print("Insira a turma: ");turma=ler.readLine();System.out.print("Insira a nota: ");nota_str=ler.readLine();nota=Float.parseFloat(nota_str);

System.out.print(nome+" "+ano+" "+turma+" ");

idade=2009-ano_nasc;if(idade<18){

System.out.print("Menor ");}else{

System.out.print("Maior ");}

if (nota<10) System.out.print("Reprovado "); else System.out.print("Aprovado ");

Prof. Herberto Graça Página 190 de 217

Page 191: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

}}

12)

import java.io.*;

public class Ex_12 {

public static void main(String[] args) throws IOException {String operacao=null;int op;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira a operação (1,2,3,4): ");operacao=ler.readLine();op=Integer.parseInt(operacao);

switch (op){case 1:System.out.println("Adição"); break;case 2:System.out.println("Subtracção"); break;case 3:System.out.println("Multiplicação"); break;case 4:System.out.println("Divisão"); break;default: System.out.println("Operação inexistente!");

}}

}

13)

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;

public class Ex_13 {

public static void main(String[] args) throws IOException {String nota_str=null;int nota;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira a nota: ");nota_str=ler.readLine();nota=Integer.parseInt(nota_str);

switch (nota){case 0:case 1:case 2:case 3:case 4:System.out.println("Mt. Insuficiente"); break;case 5:case 6:case 7:case 8:case 9:System.out.println("Insuficiente"); break;case 10:case 11:case 12:case 13:System.out.println("Suficiente"); break;case 14:case 15:case 16:case 17:System.out.println("Bom"); break;case 18:case 19:case 20:System.out.println("Mt. Bom"); break;default: System.out.println("Nota inválida!");

}}

}

Prof. Herberto Graça Página 191 de 217

Page 192: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

14)

import java.io.*;

public class Ex_14 {

public static void main(String[] args) throws IOException {String nota_str=null;int nota;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira a nota: ");nota_str=ler.readLine();nota=Integer.parseInt(nota_str);

if ((0<=nota) && (nota<=20))if (nota<4) System.out.println("Mt. Insuficiente");else

if (nota<10) System.out.println("Insuficiente");else

if (nota<14) System.out.println("Suficiente");else

if (nota<18) System.out.println("Bom");else

System.out.println("Mt. Bom");else

System.out.println("Nota inválida!");}

}

15)

public class Ex_15 {

public static void main(String[] args) {int i, soma;

for(i=0, soma=0; i<20; i++)soma+=i;

System.out.print("soma= "+soma);}

}

16)

import java.io.*;

public class Ex_16 {

public static void main(String[] args) throws IOException {String ano_str=null;int ano,y;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira o ano: ");ano_str=ler.readLine();ano=Integer.parseInt(ano_str);

y=ano;

if ((ano % 100)==0) y=ano/100;

if ((y % 4)==0) System.out.println("É bissexto");else System.out.println("Não é bissexto");

}}

17)

Prof. Herberto Graça Página 192 de 217

Page 193: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

import java.io.*;

public class Ex_17 {

public static void main(String[] args) throws IOException {String in=null;int num;float soma=0,contador=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

do{//le os dados do teclado, como stringsSystem.out.print("Insira um numero: ");in=ler.readLine();num=Integer.parseInt(in);

soma=soma+num;

if (num!=0) contador++;}while (num!=0);

System.out.println("A média é: "+soma/contador);}

}

18)

import java.io.*;

public class Ex_18 {

public static void main(String[] args) throws IOException {String in=null;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira um nome: ");in=ler.readLine();

for (int i=0; i<20; i++)System.out.println((i+1)+" - "+in);

}}

19)

import java.io.*;

public class Ex_19 {

public static void main(String[] args) throws IOException {String in=null;int num;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for (int i=0; i<15; i++){//le os dados do teclado, como stringsSystem.out.print("Insira um numero: ");in=ler.readLine();num=Integer.parseInt(in);

if (num<0) System.out.println("Negativo");else

if (num>0) System.out.println("Positivo");else System.out.println("Zero");

}}

}

20)

Prof. Herberto Graça Página 193 de 217

Page 194: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

import java.io.*;

public class Ex_20 {

public static void main(String[] args) throws IOException {String in=null;int num,count=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for (int i=0; i<20; i++){//le os dados do teclado, como stringsSystem.out.print("Insira um numero: ");in=ler.readLine();num=Integer.parseInt(in);

if (num==0) count++;}System.out.println("Foram introduzidos "+count+" zeros.");

}}

21)

import java.io.*;

public class Ex_21 {

public static void main(String[] args) throws IOException {String in=null;int num;float soma=0,contador=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

while (contador<20){//le os dados do teclado, como stringsSystem.out.print("Insira um numero: ");in=ler.readLine();num=Integer.parseInt(in);

soma=soma+num;

contador++;}

System.out.println("Media: "+soma/contador);}

}

22)

import java.io.*;

public class Ex_22 {

static final int preco=10;

public static void main(String[] args) throws IOException {String in=null;float peso=0,custo=0, oferta=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Qual a quantidade comprada? ");in=ler.readLine();peso=Integer.parseInt(in);

custo=peso*preco;

if ((70<custo) && (custo<100)) oferta=(float) 0.5;

elseif (100<=custo) oferta=1;

Prof. Herberto Graça Página 194 de 217

Page 195: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

System.out.println("Valor comprado: "+custo+"�");System.out.println("Ganho: "+oferta+"Kg");

}}

23)

import java.io.*;

public class Ex_23 {

public static void main(String[] args)throws IOException {String in=null;int num=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

//le os dados do teclado, como stringsSystem.out.print("Insira um num: ");in=ler.readLine();num=Integer.parseInt(in);

if(num%2==0) System.out.println("PAR");else System.out.println("IMPAR");

}}

24)

import java.io.*;

public class Ex_24 {

public static void main(String[] args) throws IOException {String in=null;int num;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for (int i=0; i<5; i++){//le os dados do teclado, como stringsSystem.out.print("Insira um numero: ");in=ler.readLine();num=Integer.parseInt(in);

System.out.println("O dobro de "+num+" fica: "+(num*2));}

}}

25)

import java.io.*;

public class Ex_25 {

public static void main(String[] args) throws IOException {String in;int count=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for (int i=0; i<50; i++){//le os dados do teclado, como stringsSystem.out.print("Insira uma letra: ");in=ler.readLine();if (in.contentEquals("a")) count++;

}System.out.println("A quantidade de A inseridos foi: "+count);

}}

26)

Prof. Herberto Graça Página 195 de 217

Page 196: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

import java.io.*;

public class Ex_26 {

public static void main(String[] args) throws IOException {String nome;int total=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

while (total<20){nome=ler.readLine();System.out.println("Nome= "+nome);total++;

}}

}

27)

import java.io.*;

public class Ex_27 {

public static void main(String[] args) throws IOException {String in;int n=0, resultado=1;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Insira um numero: ");in=ler.readLine();n=Integer.parseInt(in);

do{ resultado=resultado * (n--);}while(n>=1);

System.out.println("O resultado é: "+resultado);}

}

28)

import java.io.*;

public class Ex_28 {

public static void main(String[] args) throws IOException {String in;int num=0, expoente=1, resultado=1;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Insira o numero: ");in=ler.readLine();num=Integer.parseInt(in);

System.out.print("Insira o expoente: ");in=ler.readLine();expoente=Integer.parseInt(in);

for (int i=1; i<=expoente;i++) resultado*=num;

System.out.println("O resultado é: "+resultado);}

}

29)

import java.io.*;

Prof. Herberto Graça Página 196 de 217

Page 197: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

public class Ex_29 {

public static void main(String[] args) throws IOException {String in;int num_a=0, num_b=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Insira o numero: ");in=ler.readLine();num_a=Integer.parseInt(in);

System.out.print("Insira o numero: ");in=ler.readLine();num_b=Integer.parseInt(in);

if (num_a<num_b) System.out.println(num_a+" < "+num_b);else

if (num_a>num_b) System.out.println(num_a+" > "+num_b);else System.out.println(num_a+" = "+num_b);

}}

30)

import java.io.*;

public class Ex_30 {

public static void main(String[] args) throws IOException {

String in;int mes=0;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Insira o mes: ");in=ler.readLine();mes=Integer.parseInt(in);

switch(mes){case 1: System.out.print("Janeiro"); break;case 2: System.out.print("Fevereiro"); break;case 3: System.out.print("Março"); break;case 4: System.out.print("Abril"); break;case 5: System.out.print("Maio"); break;case 6: System.out.print("Junho"); break;case 7: System.out.print("Julho"); break;case 8: System.out.print("Agosto"); break;case 9: System.out.print("Setembro"); break;case 10: System.out.print("Outubro"); break;case 11: System.out.print("Novembro"); break;case 12: System.out.print("Dezembro"); break;default: System.out.print("Esse mes não existe"); break;

}}

}

Exercícios do Cap. 4.121)

import java.io.*;

public class Ex_01 {

public static void main(String[] args) throws IOException {int[] lista = new int[5];

String in;

Prof. Herberto Graça Página 197 de 217

Page 198: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<5; i++){System.out.print("Insira o numero: ");in=ler.readLine();lista[i]=Integer.parseInt(in);

}

for(int i=0; i<5; i++){System.out.println(Math.sqrt(lista[i])+" "+Math.pow(lista[i], 2));

}}

}

2)

import java.io.*;

public class Ex_02 {

public static void main(String[] args) throws IOException {int[] lista = new int[12];int op=0, i=0, soma=0;float media;

String in;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(i=0; i<lista.length; i++){System.out.print("Insira a despesa do mês "+(i+1)+": ");in=ler.readLine();lista[i]=Integer.parseInt(in);

}

do{System.out.print("Qual o mes que quer consultar (0 para sair) ? ");in=ler.readLine();op=Integer.parseInt(in);if(op!=0)

System.out.println("A despesa do mes foi: "+lista[(op-1)]);}while (op!=0);

for(i=0; i<lista.length; i++){soma=soma+lista[i];

}media=soma/i;

System.out.println("A média é: "+media);}

}

3)

import java.io.*;

public class Ex_03 {

public static void main(String[] args) throws IOException {int[] lista = new int[5];int indice_do_maior=0;

String in;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<5; i++){System.out.print("Insira o numero: ");in=ler.readLine();lista[i]=Integer.parseInt(in);

}

for(int i=1; i<5; i++){if (lista[i]>lista[indice_do_maior]) indice_do_maior=i;

}System.out.println("O indice é: "+indice_do_maior+" e o maior é:

Prof. Herberto Graça Página 198 de 217

Page 199: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

"+lista[indice_do_maior]);}

}

4)

import java.io.*;

public class Ex_04 {

public static void main(String[] args) throws IOException {int[] lista = new int[5];

String in;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<5; i++){System.out.print("Insira o numero: ");in=ler.readLine();lista[i]=Integer.parseInt(in);

}

for(int i=0; i<5; i++){System.out.println("Em escudos é: "+lista[i]+" e em euros é: "+

(((float)lista[i])/200));}

}}

5)

import java.io.*;

public class Ex_05 {

public static void main(String[] args) throws IOException {int[] despesas = new int[6];int[] receitas = new int[6];int[] resultado = new int[6];int total=0;

String in;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<6; i++){System.out.print("Insira a receita: ");in=ler.readLine();receitas[i]=Integer.parseInt(in);

System.out.print("Insira a despesa: ");in=ler.readLine();despesas[i]=Integer.parseInt(in);

}

for(int i=0; i<6; i++){resultado[i]=receitas[i]-despesas[i];total+=resultado[i];System.out.println("No mes "+i+": "+resultado[i]);

}System.out.print("Total: "+total);

}}

6)

import java.io.*;

public class Ex_06 {static int tamanho=5;

public static void main(String[] args) throws IOException {int[] lista = new int[tamanho];

Prof. Herberto Graça Página 199 de 217

Page 200: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

String pares="Foram inseridos os seguintes numeros pares: ";String maiores="Os valores maiores que a média são: ";int menor=999999999,maior=0,soma=0,media=0;

String in;

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<tamanho; i++){System.out.print("Insira um numero: ");in=ler.readLine();lista[i]=Integer.parseInt(in);

}

for(int i=0; i<tamanho; i++){if (lista[i]%2==0) pares+=lista[i]+" ";

if(i==0) menor=lista[i];else

if (lista[i]<menor) menor=lista[i];

if(i==0) maior=lista[i];else

if (lista[i]>maior) maior=lista[i];

soma+=lista[i];}media=soma/tamanho;for(int i=0; i<tamanho; i++){

if (lista[i]>media) maiores+=lista[i]+" ";}System.out.println(pares);System.out.println("O menor é: "+menor);System.out.println("O maior é: "+maior);System.out.println("A média é: "+media);System.out.println(maiores);

}}

7)

import java.io.*;

public class Ex_07 {

public static void main(String[] args) throws IOException {int[][] tabela = new int[3][3];int loja,mes;

String in,sair="";

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<tabela.length; i++)for(int j=0; j<tabela[0].length; j++){

System.out.print("Insira o valor: ");in=ler.readLine();tabela[i][j]=Integer.parseInt(in);

}

do{System.out.print("Qual a loja que quer consultar? ");in=ler.readLine();loja=Integer.parseInt(in);System.out.print("Qual o mes que quer consultar? ");in=ler.readLine();mes=Integer.parseInt(in);

System.out.print("As vendas da loja "+loja+" no mes "+mes+" foram: "+tabela[loja-1][mes-1]);

System.out.println("Quer consultar mais lojas?");sair=ler.readLine();

}while(sair.contentEquals("s"));}

}

Prof. Herberto Graça Página 200 de 217

Page 201: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

8)

public class Ex_08 {

public static void main(String[] args) {int[][] tabela = new int[4][2];int[] soma_de_cada_linha= new int[4];int[] soma_de_cada_coluna= new int[2];int soma=0;

tabela[0][0]=5; tabela[0][1]=7;tabela[1][0]=2; tabela[1][1]=4;tabela[2][0]=6; tabela[2][1]=3;tabela[3][0]=1; tabela[3][1]=6;

for(int i=0; i<tabela.length; i++)for(int j=0; j<tabela[0].length; j++){

soma_de_cada_linha[i]+=tabela[i][j];soma_de_cada_coluna[j]+=tabela[i][j];soma+=tabela[i][j];

}

for(int i=0; i<soma_de_cada_linha.length; i++)System.out.println("linha "+i+" : "+soma_de_cada_linha[i]);

System.out.println();

for(int i=0; i<soma_de_cada_coluna.length; i++)System.out.println("coluna "+i+" : "+soma_de_cada_coluna[i]);

System.out.println();System.out.println("total : "+soma);

}}

9)

import java.io.*;

public class Ex_09 {

public static void main(String[] args) throws IOException {int[][] tabela = new int[3][12];int total=0;/*tabela[0][0]=5; tabela[0][1]=7; tabela[0][2]=6; tabela[0][3]=3;tabela[0][4]=5; tabela[0][5]=7; tabela[0][6]=6; tabela[0][7]=3;tabela[0][8]=5; tabela[0][9]=7; tabela[0][10]=6; tabela[0][11]=3;

tabela[1][0]=2; tabela[1][1]=4; tabela[1][2]=6; tabela[1][3]=3;tabela[1][4]=5; tabela[1][5]=7; tabela[1][6]=6; tabela[1][7]=3;tabela[1][8]=5; tabela[1][9]=7; tabela[1][10]=6; tabela[1][11]=3;*/String in="";

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<tabela.length; i++)for(int j=0; j<tabela[0].length; j++){

System.out.print("Insira o valor: ");in=ler.readLine();tabela[i][j]=Integer.parseInt(in);

}

for (int i=0; i<tabela.length-1; i++)for(int j=0; j<tabela[0].length; j++){

tabela[2][j]+=tabela[i][j];}

for (int i=0; i<tabela[0].length; i++){System.out.println("total do mes "+(i+1)+" "+tabela[2][i]);total+=tabela[2][i];

}System.out.println("O total final é: "+total);

}}

Prof. Herberto Graça Página 201 de 217

Page 202: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

10)

import java.io.*;

public class Ex_10 {

public static void main(String[] args) throws IOException {float[][] tabela = new float[7][2];float[] medias_diarias = new float[7];float media=0, soma=0, somatotal=0, contagemtemps=0;boolean acimadamedia=false;

/*tabela[0][0]=5; tabela[0][1]=7;tabela[1][0]=2; tabela[1][1]=4;tabela[2][0]=6; tabela[2][1]=3;tabela[3][0]=1; tabela[3][1]=1;tabela[4][0]=5; tabela[4][1]=7;tabela[5][0]=2; tabela[5][1]=4;tabela[6][0]=6; tabela[6][1]=3; */

String in="";

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<tabela.length; i++)for(int j=0; j<tabela[i].length; j++){

System.out.print("Insira o valor: ");in=ler.readLine();tabela[i][j]=Integer.parseInt(in);

}

for(int i=0; i<tabela.length; i++){soma=0;for(int j=0; j<tabela[i].length; j++){

soma+=tabela[i][j];somatotal+=tabela[i][j];contagemtemps++;

}medias_diarias[i]=soma/tabela[i].length;

}media=somatotal/contagemtemps;

System.out.println("As médias diárias foram:");for(int i=0; i<medias_diarias.length; i++)

System.out.println("O dia "+(i+1)+" teve a temperatuda média de: "+medias_diarias[i]);

System.out.println("A temperatuda média da semana foi: "+media);

for(int i=0; i<tabela.length; i++){acimadamedia=false;for(int j=0; j<tabela[i].length; j++){

if (tabela[i][j]>media) acimadamedia=true;}if (acimadamedia)

System.out.println("O dia "+(i+1)+" teve pelo menos uma temperatura acima da media");

}}

}

11)

import java.io.*;

public class Ex_11 {

public static void main(String[] args) throws IOException {float[][] tabela = new float[3][2];float[] medias_alunos = new float[3];float[] medias_discs = new float[2];

/*tabela[0][0]=15; tabela[0][1]=7;

Prof. Herberto Graça Página 202 de 217

Page 203: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

tabela[1][0]=2; tabela[1][1]=10;tabela[2][0]=6; tabela[2][1]=13;*/

String in="";

BufferedReader ler = new BufferedReader(new InputStreamReader(System.in));

for(int i=0; i<tabela.length; i++)for(int j=0; j<tabela[i].length; j++){

System.out.print("Insira o valor: ");in=ler.readLine();tabela[i][j]=Integer.parseInt(in);

}

for(int i=0; i<tabela.length; i++){for(int j=0; j<tabela[i].length; j++){

medias_alunos[i]+=tabela[i][j];medias_discs[j]+=tabela[i][j];

}medias_alunos[i]=medias_alunos[i]/medias_discs.length;

}

medias_discs[0]=medias_discs[0]/medias_alunos.length;medias_discs[1]=medias_discs[1]/medias_alunos.length;

for(int i=0; i<medias_alunos.length; i++){System.out.println("O aluno "+(i+1)+" teve a média de: "+medias_alunos[i]);

}

for(int i=0; i<medias_discs.length; i++){System.out.println("A disciplina "+(i+1)+" teve a média de:

"+medias_discs[i]);}

}}

12)

public class Ex_12 {

public static void main(String[] args) {int[][] matriz_1 = new int[3][3];int[][] matriz_2 = new int[3][3];int[][] matriz_soma = new int[3][3];

matriz_1[0][0]=15; matriz_1[0][1]=7; matriz_1[0][2]=7;matriz_1[1][0]=2; matriz_1[1][1]=10; matriz_1[1][2]=7;matriz_1[2][0]=6; matriz_1[2][1]=13; matriz_1[2][2]=7;

matriz_2[0][0]=15; matriz_2[0][1]=7; matriz_2[0][2]=7;matriz_2[1][0]=2; matriz_2[1][1]=10; matriz_2[1][2]=7;matriz_2[2][0]=6; matriz_2[2][1]=13; matriz_2[2][2]=7;

for(int i=0; i<matriz_soma.length; i++){for(int j=0; j<matriz_soma[i].length; j++){

matriz_soma[i][j]=matriz_1[i][j]+matriz_2[i][j];}

}

System.out.println("A matriz soma é:");for(int i=0; i<matriz_soma.length; i++){

for(int j=0; j<matriz_soma[i].length; j++){System.out.print(matriz_soma[i][j]+" ");

}System.out.println();

}}

}

Exercícios do Cap. 5.21) Exercício 2

Prof. Herberto Graça Página 203 de 217

Page 204: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

/** * @author Herberto Graça * Esta classe representa uma carta de um baralho. */public class Carta {

int num;String naipe;

/** * Constructor da classe Carta, que inicializa os membros "num" e "naipe". * * @param "n" refere-se ao valor da carta [1,13]. * @param "np" refere-se ao naipe da carta [0,3]=>{copas,espadas,paus,ouros}. */public Carta (short n, short np){

if ( 0<n && n<14 && 0<=np && np<4 ){num=n;switch (np){

case 0: naipe="copas";break;case 1: naipe="espadas";break;case 2: naipe="paus";break;case 3: naipe="ouros";break;

}}

}}

2) Exercícios 3 e 4

import java.io.IOException;import java.util.Calendar;import java.util.Random;

/** * @author Herberto Graça */public class Baralho {

private Carta[][] baralho= new Carta[4][13];

/** * Constructor da classe Baralho, que inicializa um array * com valores que representam as cartas de um baralho.<BR> * * O membro "baralho" é um array 4x13. */public Baralho() {

for (short i=0; i<4; i++){for (short j=0; j<13; j++){

baralho[i][j]= new Carta((short)(j+1),i);}

}}

/** * Troca as posições de duas cartas. * @param (a,b)- coordenadas da 1ª carta, no array que representa o baralho. * @param (c,d)- coordenadas da 2ª carta, no array que representa o baralho. */private void troca(short a,short b,short c,short d){

Carta tmp;

tmp=baralho[c][d];baralho[c][d]=baralho[a][b];baralho[a][b]=tmp;

}

/** * Troca as posições de várias cartas do baralho. */public void baralha(){

short c,d;Calendar data=Calendar.getInstance();Random rdm= new Random(data.getTimeInMillis());

for (short i=0; i<4; i++){for (short j=0; j<7; j++){

c=(short)(rdm.nextInt()%(4));d=(short)(rdm.nextInt()%(13));

Prof. Herberto Graça Página 204 de 217

Page 205: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

if (c<0) c*=(-1);if (d<0) d*=(-1);troca(i,j,c,d);

}}

}

/** * Mostra as cartas do baralho. */public void mostra(){

for (short i=0; i<4; i++){for (short j=0; j<13; j++){

System.out.print(baralho[i][j].num + " " + baralho[i][j].naipe + " | ");

}System.out.println();

}}

/** * Cria um baralho, baralha-o, e mostra-o. */public static void main(String[] args) {

Baralho bar = new Baralho();bar.baralha();bar.mostra();try {

System.in.read();} catch (IOException e) {

// TODO Auto-generated catch blocke.printStackTrace();

}}

}

1)

/** * * @author Herberto Graça * @author Marcus Vinicius * * @description Classe que representa uma carta genérica * */public abstract class Carta {

/** * Variável de instancia que representa o número de uma carta */private int numero ;/** * Variável de instancia que representa a cor de uma carta */private String naipe;

/** * função para definir o numero da carta * @param numero da carta */public void setNum(int n){

numero=n;}

/** * função para definir o naipe da carta * @param naipe */public void setNaipe(String n){

naipe=n;}

/** * função para obter o numero da carta * @return numero da carta

Prof. Herberto Graça Página 205 de 217

Page 206: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

*/public int getNum(){

return numero;}

/** * função para obter o naipe da carta * @return naipe da carta */public String getNaipe(){

return naipe;}

}

/** * * @author Herberto Graça * @author Marcus Vinicius * * @description Classe que representa uma carta de um baralho latino * */public class CartaLatina extends Carta{

/** * Costrutor */public CartaLatina(int n,String naip){

setNum(n);setNaipe(naip);

}

/** * método para converter o objecto em string * @return o objecto em formato de string */public String toString(){

switch(getNum()+1){case 1:return("|"+"A"+","+getNaipe()+"|");case 11:return("|"+"J"+","+getNaipe()+"|");case 12:return("|"+"Q"+","+getNaipe()+"|");case 13:return("|"+"K"+","+getNaipe()+"|");default: return("|"+(getNum()+1)+","+getNaipe()+"|");

}}

/** * Código para testar a classe * @param args */public static void main(String args[]){

Carta x= new CartaLatina(0,"copas");System.out.println(x);

}

}

/** * * @author Herberto Graça * @author Marcus Vinicius * * @description Classe que representa um baralho genérico * */public abstract class Baralho {

/** * array com todas as cartas do baralho */protected Carta [][] baralho ;

/** * metodo para baralhar cartas */

Prof. Herberto Graça Página 206 de 217

Page 207: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

public void baralhar(){int n=0,naip=0;Carta x;for(int i=0;i<baralho.length;i++){

for(int j=0;j<baralho[i].length;j++){n=(int)(Math.random()*(baralho[i].length-1));naip=(int)(Math.random()*(baralho.length-1));x=this.getCarta(i, j);setCarta(i,j,this.getCarta(naip, n));setCarta(naip,n,x);

}}

}

/** * metodo para colocar uma carta numa posição * @param i linha * @param j coluna * @param x carta */public void setCarta(int i,int j,Carta x){

baralho[i][j]=x;}

/** * metodo para devolver uma carta numa posição * @param naip linha * @param n coluna * @return a carta na linha e na coluna indicadas */public Carta getCarta(int naip,int n){

return baralho[naip][n];}

/** * método para converter o objecto em string * @return o objecto em formato de string */public String toString(){

String x="";for(int i=0;i<baralho.length;i++){

for(int j=0;j<baralho[i].length;j++){x+=getCarta(i,j);

}x+="\n";

}x+="\n";return x;

}

}

/** * * @author Herberto Graça * @author Marcus Vinicius * * @description Classe que representa um baralho latino * */public class BaralhoLatino extends Baralho {

/** * Costrutor */public BaralhoLatino(){

baralho= new Carta [4][13];for(int i=0;i<baralho.length;i++){

for(int j=0;j<baralho[i].length;j++){switch(i){

case 0 :baralho[i][j]=new CartaLatina(j,"♥");break;case 1 :baralho[i][j]=new CartaLatina(j,"♠");break;case 2 :baralho[i][j]=new CartaLatina(j,"♣");break;case 3 :baralho[i][j]=new CartaLatina(j,"♦");break;

}}

}

Prof. Herberto Graça Página 207 de 217

Page 208: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

}

/** * Código para testar a classe * @param args */public static void main(String args[]){

BaralhoLatino b=new BaralhoLatino();System.out.println(b);b.baralhar();System.out.println(b);

}

}

Prof. Herberto Graça Página 208 de 217

Page 209: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Exercícios do Cap. 6.21)

public static void main(String[] args) throws IOException {

if (args.length == 0) {System.out.println("A sintaxe é: Ex61411.jar <ficheiro>");return;

}

FileInputStream in;try {

in = new FileInputStream(args[0]);}catch (FileNotFoundException e) {

System.out.println("O ficheiro '" + args[0] + "' não foi encontrado!");return;

}

int ch;while ((ch = in.read()) != -1) {

System.out.print((char) ch);}System.out.println();

in.close();}

2)

public static void main(String[] args) throws IOException {

if (args.length == 0) {System.out.println("A sintaxe é: Ex61412.jar <ficheiro>");return;

}

FileInputStream fin;try {

fin = new FileInputStream(args[0]);}catch (FileNotFoundException e) {

System.out.println("O ficheiro '" + args[0] + "' não foi encontrado!");return;

}

DataInputStream din = new DataInputStream(fin);try {

int i;for (;;) {

i = din.readInt();System.out.println(i);

}}catch (EOFException e) {}

fin.close();}

Prof. Herberto Graça Página 209 de 217

Page 210: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

3)

import java.io.*;import java.util.*;/** * @author Herberto Graça */public class Ex6142 {

public static void main(String[] args) throws IOException {// 1. Verificar os parâmetros de entrada.if (args.length == 0) {

System.out.println("A sintaxe é: Ex6142.jar <ficheiro>");return;

}// 2. Criar uma stream de leitura do ficheiro. FileInputStream in = null;try {

in = new FileInputStream(args[0]);}catch (FileNotFoundException e) {

System.out.println("O ficheiro '" + args[0] + "' não foi encontrado!");return;

}

// 3. Ler o ficheiro para dentro de um buffer.StringBuffer buf = new StringBuffer();try {

int ch;while ((ch = in.read()) != -1) {

buf.append((char) ch);}

}finally {

in.close();}

// 4. Separar o conteúdo por palavras.// 5. Inverter a ordem das palavras.StringTokenizer tok = new StringTokenizer(buf.toString());Stack stack = new Stack();while (tok.hasMoreTokens()) {

stack.push(tok.nextToken());}

// 6. Imprimir no ecrã.while (!stack.empty()) {

System.out.println((String) stack.pop());}

}}

4)

public class myException extends Exception {

public myException(String msg) {super(msg);

}

public myException() {super("Mensagem de erro de myException");

}}

Prof. Herberto Graça Página 210 de 217

Page 211: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

public class testException {public testException (){}

public void doException() throws myException {throw new myException("Lançando uma exception de testException");

}

public static void main(String[] args) {testException tst= new testException ();try {

tst.doException();} catch (myException e) {

System.out.println(e.getMessage());e.printStackTrace();

}}

}

5)

public class Producer extends Thread {private CubbyHole cubbyhole;private int number;

public Producer(CubbyHole c, int number) {cubbyhole = c;this.number = number;

}

public void run() {for (int i = 0; i < 10; i++) {

cubbyhole.put(i);System.out.println("Producer #"+ this.number +" put: "+ i);try {

sleep((int)(Math.random() * 100));} catch (InterruptedException e) { }

}}

}

public class Consumer extends Thread {private CubbyHole cubbyhole;private int number;

public Consumer(CubbyHole c, int number) {cubbyhole = c;this.number = number;

}

public void run() {int value = 0;for (int i = 0; i < 10; i++) {

value = cubbyhole.get();System.out.println("Consumer #"+ this.number +" got: "+ value);

}}

}

public class ProducerConsumerTest {public static void main(String[] args) {

CubbyHole c = new CubbyHole();Producer p1 = new Producer(c, 1);Consumer c1 = new Consumer(c, 1);

p1.start();c1.start();

}}

Prof. Herberto Graça Página 211 de 217

Page 212: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

Exercícios do Cap. 6.3

1)import java.io.*;

public class Copy2 { public static void main(String[] args) throws IOException { File inputFile = new File("boogie.jpg"); File outputFile = new File("out.jpg");

FileInputStream in = new FileInputStream(inputFile); FileOutputStream out = new FileOutputStream(outputFile); int c;

while ((c = in.read()) != -1) out.write(c);

in.close(); out.close(); }}

2)import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;

public class Serializa_1 {

public Serializa_1() {super();

}

public static void escrever(String str) throws IOException{FileOutputStream out = new FileOutputStream("ficheiro.txt");ObjectOutputStream s = new ObjectOutputStream(out);s.writeObject(str);s.flush();

}

public static String ler() throws IOException, ClassNotFoundException{FileInputStream in = new FileInputStream("ficheiro.txt");ObjectInputStream s = new ObjectInputStream(in);String str= (String)s.readObject();return str;

}

public static void main(String[] args){String str="uma string";System.out.println(str);try {

escrever(str);System.out.println(ler());

} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}

}}

Prof. Herberto Graça Página 212 de 217

Page 213: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

3)import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.Date;

public class Serializa_2 {

public Serializa_2() {super();

}

public static void escrever(String str, Date dt) throws IOException{FileOutputStream out = new FileOutputStream("ficheiro.txt");ObjectOutputStream s = new ObjectOutputStream(out);s.writeObject(str);s.writeObject(dt);s.flush();

}

public static void ler() throws IOException, ClassNotFoundException{FileInputStream in = new FileInputStream("ficheiro.txt");ObjectInputStream s = new ObjectInputStream(in);String str= (String)s.readObject();Date dt= (Date)s.readObject();System.out.println(str);System.out.println(dt.toString());

}

public static void main(String[] args){String str="uma string";Date dt=new Date();

System.out.println(str);System.out.println(dt.toString());

try {escrever(str,dt);ler();

} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}

}}

Exercícios do Cap. 73)

import java.awt.Graphics;import java.awt.Color;import java.util.Date;

public class Clock_2 extends java.applet.Applet implements Runnable {private Thread clockThread = null;String cor_de_fundo;String cor_de_font;

public void init() {cor_de_fundo = getParameter("bkgrdColor");if (cor_de_fundo == null) {

cor_de_fundo = "FFFFFF";}int bkgrd_color = Integer.valueOf(cor_de_fundo, 16).intValue();setBackground(new Color(bkgrd_color));

cor_de_font = getParameter("fontColor");if (cor_de_font == null) {

cor_de_font = "000000";}

Prof. Herberto Graça Página 213 de 217

Page 214: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

}

public void start() {if (clockThread == null) {

clockThread = new Thread(this, "Clock");clockThread.start();

}}public void run() {Thread myThread = Thread.currentThread();

while (clockThread == myThread) {repaint();try { Thread.sleep(1000);} catch (InterruptedException e){ }

}}public void paint(Graphics g) {

Date now = new Date();int h=now.getHours();int m=now.getMinutes();int s=now.getSeconds();String horas="0";String minutos="0";String segundos="0";

if ((h>=0)&&(h<=9)){ horas="0"+h; }else{ horas=Integer.toString(h); }if ((h>=0)&&(h<=9)){ minutos="0"+m; }else{ minutos=Integer.toString(m); }if ((h>=0)&&(h<=9)){ segundos="0"+s; }else{ segundos=Integer.toString(s); }

int font_color = Integer.valueOf(cor_de_font, 16).intValue();g.setColor(new Color(font_color));g.drawString(horas + ":" + minutos + ":" + segundos, 5, 10);

}public void stop() {

clockThread = null;}

}

Exercícios do Cap. 81)

public class HelloWorldBt {public static void main(String[] args) {

JFrame frame = new JFrame("HelloWorldSwing"); //cria a janelaframe.getContentPane().setBackground(Color.BLUE);JPanel pane = new JPanel();final JButton bt = new JButton("Hello world!"); //cria um botão com texto

pane.add(bt);//coloca o botão no painel

frame.getContentPane().add(pane); //coloca o painel na janela

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.pack(); //adapta o tamanho da janela aos seus

conteúdosframe.setVisible(true); //torna a janela visivel

}}

2)

import javax.swing.*;import java.awt.*;

public class Dia extends JButton {int dia, mes, ano;

/** * @param d dia * @param m mes * @param a ano

Prof. Herberto Graça Página 214 de 217

Page 215: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

*/public Dia(int d, int m, int a) {

super(""+d);Font font= new Font("",Font.PLAIN,10);setFont(font);dia=d;mes=m;ano=a;this.setMargin(new Insets(0,0,0,0));

}

public static void main(String[] args) {JFrame frm= new JFrame("Dia");Dia bt= new Dia(4,12,1999);

frm.getContentPane().add((new JPanel()).add(bt));frm.pack();frm.setVisible(true); //torna a janela visivel

}}

3)

import javax.swing.*;import javax.swing.border.TitledBorder;import java.awt.*;import java.util.*;

public class Mes extends JPanel {int mes, ano;Dia [] dias;String [] nomeMeses={"Janeiro","Fevereiro","Março",

"Abril","Maio","Junho",

"Julho","Agosto","Setembro",

"Outubro","Novembro","Dezembro"};/** * @param m mes [1;12] * @param a ano */public Mes(int m, int a) {

super();Dia d;Calendar calendar=Calendar.getInstance();int dias_do_mes;mes=m;ano=a;

setLayout(new GridLayout(6,7)); calendar.set(a,m-1,1);dias_do_mes=calendar.getActualMaximum(Calendar.DAY_OF_MONTH);dias= new Dia[dias_do_mes];

// insere os slots vazios na grelha, // antes de chegar ao dia da semana em que o mes começafor (int i=1; i<calendar.get(Calendar.DAY_OF_WEEK); i++){

add(new JPanel());}// insere os botoes correspondenes aos dias, na grelhafor (int i=0 ; i<dias_do_mes ; i++ ){

d=new Dia(i+1,mes,ano);add(d);dias[i]=d;

}// insere os slots vazios na grelha,// até chegar ao fim da grelhafor (int i=0; i<(42-(calendar.get(Calendar.DAY_OF_WEEK)+dias_do_mes)); i++){

add(new JPanel());}//coloca o titulo e a margemTitledBorder titulo =

BorderFactory.createTitledBorder(nomeMeses[calendar.get(Calendar.MONTH)]);this.setBorder(titulo);

}

public static void main(String[] args) {JFrame frm= new JFrame("Mês");Mes m= new Mes(1,2004);

Prof. Herberto Graça Página 215 de 217

Page 216: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

frm.getContentPane().add(m);frm.setSize(70,140);frm.setVisible(true); //torna a janela visivel

}}

4)

import java.awt.GridLayout;import javax.swing.*;import javax.swing.border.TitledBorder;

public class Ano extends JPanel {int ano;Mes [] meses= new Mes[12];/** * @param a ano */public Ano(int a) {

super();Mes m;

ano=a;setLayout(new GridLayout(4,3));

// insere os meses, na grelhafor (int i=0 ; i<12 ; i++ ){

m=new Mes(i+1,ano);add(m);meses[i]=m;

}//coloca o titulo e a margemTitledBorder titulo = BorderFactory.createTitledBorder((new

Integer(ano)).toString());this.setBorder(titulo);

}

public static void main(String[] args) {JFrame frm= new JFrame("Ano");Ano a= new Ano(2004);frm.getContentPane().add(a);frm.setSize(450,500);frm.setResizable(false);frm.setVisible(true); //torna a janela visivel

}}

5)

//...

import java.awt.event.*;

/** * @author Herberto Graça */public class Dia extends JButton implements ActionListener{

//...public Dia(int d, int m, int a) {

//...this.addActionListener(this);

}

//...

/* * O que o boto devera fazer */public void actionPerformed(ActionEvent arg0) {

JOptionPane.showMessageDialog(this, dia+"-"+mes+"-"+ano);}//...

}

Prof. Herberto Graça Página 216 de 217

Page 217: Manual de Iniciação ao JAVA

Manual de Iniciação ao JAVA

6)

//...

import java.awt.event.*;

/** * @author Herberto Graça */public class Dia extends JButton implements ActionListener{

//...public Dia(int d, int m, int a) {

//...Calendar calendar=Calendar.getInstance();calendar.set(a,m-1,d);int dia_da_semana=calendar.get(Calendar.DAY_OF_WEEK);if (dia_da_semana==1 || dia_da_semana==7) this.setForeground(new

Color(0x00,0xcc,0x00));setFont(new Font("",Font.PLAIN,10));

//...}

//...}

Prof. Herberto Graça Página 217 de 217