Você está na página 1de 0

UNIVERSIDADE FEDERAL DE VIOSA

DEPARTAMENTO DE INFORMTICA
JAVA NA PRTICA
Alcione de Paiva Oliveira
Vincius Valente Maciel
2002
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
1
Sumrio
Captulo I - Introduo ....................................... 6
CONVENES........................................................................................................................... 10
Captulo II - Programao Orientada a Objetos .................. 11
CLASSES E OBJ ETOS E LINGUAGENS DE PROGRAMAO......................................................... 12
Ocultando de Informao................................................................................................... 16
Especializao e Herana.................................................................................................. 17
Sobrescrita, Sobrecarga e Polimorfismo............................................................................ 18
INTRODUO DIAGRAMA DE CLASSES ................................................................................. 20
Diagrama de Classes.......................................................................................................... 20
Captulo III - Introduo Linguagem Java ..................... 27
PALAVRAS RESERVADAS......................................................................................................... 30
LITERAIS.................................................................................................................................. 31
SEPARADORES.......................................................................................................................... 34
TIPOS DE DADOS....................................................................................................................... 35
Tipos de dados simples....................................................................................................... 35
Tipos de dados compostos.................................................................................................. 37
CONVERSO DE TIPOS.............................................................................................................. 41
OPERADORES........................................................................................................................... 42
Expresses e Precedncia entre Operadores ..................................................................... 50
COMENTRIOS......................................................................................................................... 51
BLOCOS E ESCOPO................................................................................................................... 52
ESTRUTURAS DE CONTROLE .................................................................................................... 53
Seleo ............................................................................................................................... 53
Repetio............................................................................................................................ 57
break e continue......................................................................................................... 60
ARGUMENTOS DA LINHA DE COMANDO.................................................................................... 61
ASSERT (ASSERTIVAS) ............................................................................................................. 63
Sintaxe e semntica ............................................................................................................ 63
Habilitando e Desabilitando Assertivas ............................................................................. 64
Captulo IV Classes, Packages e Interfaces ................... 66
CLASSES .................................................................................................................................. 66
Construtores ....................................................................................................................... 68
Valor de Retorno ................................................................................................................ 68
OBJ ETOS.................................................................................................................................. 69
MODIFICADORES DE ACESSO.................................................................................................... 72
Outros Modificadores......................................................................................................... 74
REFERNCIAS COMPARTILHADAS............................................................................................ 78
COPIANDO OBJ ETOS................................................................................................................. 81
O objeto this ................................................................................................................... 81
PACKAGES............................................................................................................................... 83
Usando Packages ............................................................................................................... 83
Criando Packages .............................................................................................................. 84
O Mecanismo de Extenso ................................................................................................. 86
DERIVANDO CLASSES............................................................................................................... 88
super................................................................................................................................... 90
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
2
A classe Object ............................................................................................................... 91
Sobrescrita e Polimorfismo ................................................................................................ 92
CLASSES E MTODOS ABSTRATOS........................................................................................... 95
INTERFACES............................................................................................................................. 96
CLASSES INTERNAS.................................................................................................................. 99
Classes Internas Annimas............................................................................................... 101
CONVERSO........................................................................................................................... 103
EXCEES.............................................................................................................................. 103
A hierarquia de Excees................................................................................................. 105
Capturando mais de uma exceo.................................................................................... 106
Lanando excees........................................................................................................... 107
Comportamento do Sistema diante das Excees ............................................................ 109
Criando suas prprias excees....................................................................................... 110
A clusula finally....................................................................................................... 111
DOCUMENTANDO O CDIGO................................................................................................... 112
Rtulos.............................................................................................................................. 113
HTML embutida ............................................................................................................... 115
AGENDA ELETRNICA VERSO CONSOLE 1.0........................................................................ 115
Captulo V Entrada e Sada (java.io) ...................... 122
ACESSO SEQUENCIAL............................................................................................................. 122
ACESSO DIRETO..................................................................................................................... 127
Captulo VI java.util ..................................... 131
LIDANDO COM COLEES...................................................................................................... 131
As Interfaces Iterator e Enumeration................................................................... 131
Vector ........................................................................................................................... 133
Stack.............................................................................................................................. 136
Hashtable .................................................................................................................... 138
MISCELNEA DE CLASSES DO PACOTE JAVA.UTIL................................................................. 141
Arrays ........................................................................................................................... 141
Date ................................................................................................................................ 144
Observable.................................................................................................................. 146
StringTokenizer...................................................................................................... 150
AGENDA ELETRNICA VERSO CONSOLE 2.0........................................................................ 152
Captulo VII - Serializao e Persistncia .................... 159
AGENDA ELETRNICA VERSO CONSOLE 2.1........................................................................ 161
Captulo VIII AWT (Abstract Window Toolkit) ............... 164
A HIERARQUIA DE COMPONENTES......................................................................................... 164
OL MUNDO AWT................................................................................................................ 166
TRATAMENTO DE EVENTOS ................................................................................................... 167
Modelo de Eventos 1.1 ..................................................................................................... 167
Tratamento de Eventos com classes Internas................................................................... 171
EXEMPLO BSICO.................................................................................................................. 176
ACRESCENTANDO CORES....................................................................................................... 180
GERENCIANDO O LAYOUT...................................................................................................... 181
Exemplo com BorderLayout....................................................................................... 182
Exemplo com FlowLayout ........................................................................................... 183
Exemplo com CardLayout ........................................................................................... 184
Exemplo com GridLayout ........................................................................................... 186
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
3
Exemplo com GridBagLayout .................................................................................... 187
UTILIZANDO LISTAS............................................................................................................... 189
TRABALHANDO COM MENUS E DILOGOS............................................................................. 192
CAPTURANDO EVENTOS DO TECLADO................................................................................... 196
PRINCIPAIS CLASSES.............................................................................................................. 196
Color.............................................................................................................................. 196
Component .................................................................................................................... 198
Button ........................................................................................................................... 200
Label.............................................................................................................................. 201
List ................................................................................................................................ 202
TextField .................................................................................................................... 203
TextArea....................................................................................................................... 204
CONTAINERS.......................................................................................................................... 205
Panel.............................................................................................................................. 207
Frame.............................................................................................................................. 208
AGENDA ELETRNICA VERSO GRFICA 1.0......................................................................... 211
Captulo IX - Applets ....................................... 217
DESCRIO DO CDIGO HTML ............................................................................................. 221
MTODOS DA CLASSE APPLET............................................................................................... 222
EXIBINDO UMA IMAGEM ........................................................................................................ 226
UDIO.................................................................................................................................... 229
OBTENDO PARMETROS......................................................................................................... 230
EXECUTANDO UM APPLET COMO APLICAO........................................................................ 232
PREPARANDO APPLETS PARA PRODUO E ARQUIVOS J ARS................................................. 232
CRIANDO OS PRPRIOS ARQUIVOS MANIFEST......................................................................... 235
AGENDA ELETRNICA VERSO APPLET 1.0........................................................................... 236
Captulo X JavaBean ......................................... 237
O QUE UM J AVABEAN?....................................................................................................... 237
J AVABEANS E FERRAMENTAS RAD....................................................................................... 237
PROPRIEDADES ...................................................................................................................... 238
Simples ............................................................................................................................. 238
Indexada........................................................................................................................... 239
Ligada (Bound)................................................................................................................. 240
Restringidas(Constrained) ............................................................................................... 241
EVENTOS................................................................................................................................ 243
DESENVOLVIMENTO DO EXEMPLO......................................................................................... 244
TimerEventListener .......................................................................................................... 244
TimerEvent ....................................................................................................................... 245
TimerBean ........................................................................................................................ 245
INSTALANDO O BEANS DEVELOPMENT KIT (BDK)................................................................ 249
TESTANDO EXEMPLO NO BDK............................................................................................... 249
Captulo XI - Concorrncia .................................... 255
CRIANDO THREADS EM J AVA ................................................................................................. 257
Criando threads por meio da interface Runnable ........................................................ 259
A CLASSE THREAD................................................................................................................. 259
Hierarquia........................................................................................................................ 259
Construtores ..................................................................................................................... 259
Mtodos ............................................................................................................................ 259
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
4
Variveis pblicas ............................................................................................................ 259
CICLO DE VIDA DOS THREADS............................................................................................... 259
sleep(), yield(), join(), destroy(), stop(), suspend() e resume(). .............. 259
DAEMON THREADS................................................................................................................ 259
INFLUNCIA DO SISTEMA OPERACIONAL NO COMPORTAMENTO DOS THREADS..................... 259
Forma de escalonamento de threads................................................................................ 259
Relacionamento entre os nveis de prioridades definidas na linguagem Java e os nveis de
prioridades definidas nos Sistemas Operacionais............................................................ 259
COMPARTILHAMENTO DE MEMRIA E SINCRONIZAO........................................................ 259
Atomicidade de Instrues e Sincronizao do Acesso Sesses Crticas ...................... 259
Comunicao entre Threads: wait() e notify() ................................................................. 259
Captulo XII - Animao ....................................... 259
Captulo XIII - Programao em rede ......................... 259
CONCEITOS SOBRE PROTOCOLOS USADOS NA INTERNET....................................................... 259
TCP................................................................................................................................... 259
UDP.................................................................................................................................. 259
IDENTIFICAO DE HOSTS (Nmero IP).................................................................... 259
Identificao de Processos (Portas)................................................................................. 259
PROGRAMAO EM REDE COM J AVA..................................................................................... 259
Comunicao Bsica Entre Aplicaes............................................................................ 259
Comunicao Sem Conexo (UDP) ................................................................................. 259
Comunicao por meio de URL ....................................................................................... 259
Captulo XIV Computao Distribuda (RMI) ................. 259
CRIANDO NOSSA AGENDA DISTRIBUDA................................................................................. 259
Implementar interface do objeto remoto .......................................................................... 259
Captulo XV - Acesso a Banco de Dados ....................... 259
MODELOS DE ACESSO A SERVIDORES.................................................................................... 259
TIPOS DE DRIVERS J DBC....................................................................................................... 259
Obtendo os Drivers JDBC................................................................................................ 259
PREPARANDO UM BANCO DE DADOS..................................................................................... 259
Configurando o ODBC..................................................................................................... 259
EXEMPLO INICIAL .................................................................................................................. 259
Carregando o Driver........................................................................................................ 259
Estabelecendo a conexo ................................................................................................. 259
Criando e Executando Comandos .................................................................................... 259
RECUPERANDO VALORES....................................................................................................... 259
TRANSAES E NVEL DE ISOLAMENTO................................................................................. 259
Transao......................................................................................................................... 259
Nveis de isolamento......................................................................................................... 259
PREPARED STATEMENTS........................................................................................................ 259
PROCEDIMENTOS ARMAZENADOS (STORED PROCEDURES).................................................... 259
AGENDA ELETRNICA VERSO J DBC................................................................................... 259
Captulo XVI Servlets e JSP ................................. 259
SERVLETS .............................................................................................................................. 259
Applets X Servlets............................................................................................................. 259
CGI X Servlets .................................................................................................................. 259
A API SERVLET..................................................................................................................... 259
Exemplo de Servlet ........................................................................................................... 259
COMPILANDO O SERVLET....................................................................................................... 259
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
5
Instalando o Tomcat ......................................................................................................... 259
PREPARANDO PARA EXECUTAR O SERVLET............................................................................ 259
Compilando o Servlet ....................................................................................................... 259
Criando uma aplicao no Tomcat .................................................................................. 259
EXECUTANDO O SERVLET...................................................................................................... 259
Invocando diretamente pelo Navegador........................................................................... 259
Invocando em uma pgina HTML.................................................................................... 259
Diferenas entre as requisies GET e POST.................................................................. 259
CONCORRNCIA..................................................................................................................... 259
OBTENDO INFORMAES SOBRE A REQUISIO.................................................................... 259
LIDANDO COM FORMULRIOS................................................................................................ 259
LIDANDO COM COOKIES......................................................................................................... 259
LIDANDO COM SESSES......................................................................................................... 259
J SP......................................................................................................................................... 259
PHP X JSP ....................................................................................................................... 259
ASP X JSP ........................................................................................................................ 259
Primeiro exemplo em JSP ................................................................................................ 259
Executando o arquivo JSP................................................................................................ 259
Objetos implcitos............................................................................................................. 259
Tags JSP........................................................................................................................... 259
Comentrios ..................................................................................................................... 259
Diretivas ........................................................................................................................... 259
Extraindo Valores de Formulrios................................................................................... 259
Criando e Modificando Cookies....................................................................................... 259
Lidando com sesses ........................................................................................................ 259
O Uso de JavaBeans......................................................................................................... 259
REENCAMINHANDO OU REDIRECIONANDO REQUISIES....................................................... 259
UMA ARQUITETURA PARA COMRCIO ELETRNICO............................................................... 259
Tipos de aplicaes na WEB............................................................................................ 259
Arquitetura MVC para a Web .......................................................................................... 259
Agenda Web: Um Exemplo de uma aplicao Web usando a arquitetura MVC.............. 259
Captulo XVII Perguntas Frequentes .......................... 259
Bibliografia ................................................ 259
Links ....................................................... 259
ndice ...................................................... 259
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
6
Captulo I - Introduo
J ava uma linguagem de programao desenvolvida pela Sun
Microsystems e lanada em verso beta em 1995. O seu desenvolvimento foi
iniciado em 1991 pela equipe liderada por J ames Gosling visando o mercado de
bens eletrnicos de consumo. Por isso foi projetada desde o incio para ser
independente de hardware, uma vez que as caractersticas dos equipamentos
variam amplamente neste nicho de desenvolvimento. Outro objetivo
estabelecido desde sua concepo foi o de ser uma linguagem segura. Segura
tanto no sentido de evitar algumas falhas comuns que os programadores
costumam cometer durante o desenvolvimento, como no sentido de evitar
ataques externos. Isto importante no mercado de bens eletrnicos de consumo
por que ningum gostaria de adquirir um produto que necessitasse desligar e
religar para que voltasse a funcionar corretamente. Estas caractersticas
despertaram o interesse para utilizao de J ava em outro ambiente que tambm
necessitava de uma linguagem com este perfil: a Internet. A Internet tambm
um ambiente constitudo por equipamentos de diferentes arquiteturas e necessita
muito de uma linguagem que permita a construo de aplicativos seguros.
Muitas pessoas argumentaro que estas caractersticas podem ser encontradas
em outras linguagens e portanto isto no explica o sbito sucesso da linguagem.
Podemos arriscar alguns palpites apesar de este ser um terreno um pouco
pantanoso para se aventurar, at por que as linguagens de programao tendem
assumir um carter quase religioso. Uma das razes que na nossa opinio
favoreceram a rpida adoo da linguagem foi a sintaxe. J ava sintaticamente
muito semelhante linguagem C/C++, apesar de existirem diferenas
fundamentais na filosofia de implementao entre as duas linguagens. Isto
facilitou a migrao de uma legio imensa de programadores C/C++para a nova
linguagem. Outra razo que no pode ser desprezada o momento atual onde os
desenvolvedores esto ansiosos para se libertarem de sistemas proprietrios.
Portanto, apesar de no serem novas as idias embutidas na linguagem J ava, a
reunio delas em uma s linguagem, juntamente com a facilidade migrao dos
programadores e o momento atual, contriburam para o rpido sucesso da
linguagem.
Hoje, segundo a International Data Corp. (IDC), existem mais de 2
milhes de programadores J ava no mundo e a estimativa que o nmero de
desenvolvedores ultrapasse os 5 milhes em 2004. O nmero de programadores
J ava deve ultrapassar o de programadores C++ainda este ano (2002), segundo a
consultoria americana Evans Data. Os profissionais que dominam a linguagem
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
7
esto entre os mais bem pagos da rea de Tecnologia da Informao (TI), com
salrios variando de 3 a 10 mil reais, podendo em alguns casos chegar 16 mil
reais, segundo a revista Info Exame (dezembro de 2001).
A lista abaixo apresenta as principais caractersticas de J ava de modo que
o leitor tenha uma viso geral da linguagem:
Orientao a objetos. J ava no uma linguagem totalmente orientada a
objetos como Smalltalk, onde tudo objeto ou mtodos de objetos. Por
questes de eficincia foram mantidos alguns tipos primitivos e suas
operaes. No entanto, J ava possui um grau de orientao a objetos bem
maior que C/C++, o que a torna bem mais harmoniosa e fcil de assimilar,
uma vez que o programador tenha compreendido esta forma de
desenvolvimento.
Compilao do cdigo fonte para cdigo de uma mquina virtual
(Bytecodes). Esta caracterstica visa tornar a linguagem independente de
plataforma de Hardware e Sistema Operacional. Obviamente necessrio
que exista um programa capaz de interpretar o cdigo em Bytecodes para
cada Sistema Operacional, denominado de Mquina Virtual. No entanto,
nada impede que o cdigo fonte seja traduzido diretamente para o cdigo
executvel na mquina de destino. J existem ambientes de desenvolvimento
que apresentam este tipo de opo. Alternativamente, possvel projetar
equipamentos que processem em hardware os Bytecodes. A Sun
desenvolveu um processador que executa operaes em Bytecodes,
denominado de J avaChip. O diagrama abaixo ilustra as etapas envolvidas na
execuo de um cdigo J ava.
Figura I-1. Fases para execuo de um programa fonte em Java
Ausncia de manipulao explcita de ponteiros. Em linguagens como
C/C++e Pascal existe o tipo ponteiro como tipo primitivo da linguagem. A
especificao original de Pascal restritiva no uso de ponteiros, permitindo
que sejam usados apenas para referenciar memria obtida na rea de
alocao dinmica (heap) e no permite que o programador examine o valor
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
8
da varivel do tipo ponteiro, nem que realize operaes aritmticas com
ponteiros. J a linguagem C/C++ permite que o valor armazenado na
varivel do tipo ponteiro faa referncia a qualquer rea de memria,
inclusive rea esttica e automtica (pilha), alm de permitir aritmtica de
ponteiros e o exame direto do valor armazenado. A manipulao do tipo
ponteiro exige uma grande dose de ateno por parte do programador e
mesmo programadores experientes frequentemente cometem erros no seu
uso. Alm disso, o uso de ponteiros uma fonte de insegurana na
linguagem, uma vez que permite que o usurio faa acesso a memria que
pode pertencer a outros processos, abrindo a possibilidade para
desenvolvimento de programas hostis ao sistema. A linguagem J ava no
possui o tipo ponteiro. Isto no que dizer que no seja possvel realizar
alocao dinmica de memria. Todo objeto criado alocado na rea de
heap, mas o usurio no pode manipular a referncia ao objeto
explicitamente.
Recuperao automtica de memria no utilizada (Coleta de Lixo
Garbage Collection). Nas linguagens onde existe alocao dinmica de
memria, o programador responsvel pela liberao de memria
previamente obtida na rea de alocao dinmica e que no est sendo mais
utilizada. Se houver falhas na execuo desta responsabilidade ocorrer o
problema que conhecido sob a denominao de vazamento de memria.
Este problema faz com que a partir de certo ponto o programa no consiga
obter memria para criao de novos objetos, apesar de existir rea que no
est sendo mais usada mas que no foi devolvida ao gerente de memria.
Outro erro comum a tentativa de acesso reas de memria j liberadas.
Todos os programadores que trabalham com linguagens que permitem
alocao dinmica conhecem bem estes problemas e sabem o quanto difcil
implementar programas que no possuam estes tipos de erros. A maior parte
dos erros que ocorrem no uso destas linguagens devido a problemas na
alocao/liberao de memria. Visando o desenvolvimento de aplicaes
robustas, livres deste tipo de falha, os projetistas de J ava incorporaram um
procedimento de coleta automtica de lixo mquina virtual. Deste modo, os
objetos que no esto sendo mais usados so identificados pelo
procedimento, que libera a memria para ser utilizada na criao de novos
objetos.
Segurana. As pessoas costumam dizer que J ava uma linguagem segura.
Mas o que ser uma linguagem de programao segura? Segurana possui
significados distintos para pessoas diferentes. No caso da linguagem J ava na
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
9
verso 1.0 segurana significa impedir que programas hostis que possam
causar danos ao ambiente computacional, ou que busquem informaes
sigilosas em computadores remotos para uso no autorizado. Na verso 1.1
foi adicionada a capacidade de permitir a verificao da identidade dos
programas (autenticao) e na verso 1.2 os dados que os programas enviam
e recebem podem ser criptografados por meio do uso de um pacote adicional.
Na verso 1.4 o pacote de criptografia J CE (J ava
TM
Cryptography Extension)
foi incorporado ao J 2SDK.
Suporte Concorrncia. A construo de servidores, a criao de
programas com interfaces grficas, e programas semelhantes que tem em
comum a necessidade de que o atendimento de uma solicitao no
incapacite o sistema de responder a outras solicitaes concorrentemente,
demandam o uso de uma linguagem que facilite o desenvolvimento deste
tipo de programa. As linguagens projetadas antes do surgimento destas
necessidades, como C/C++, no previam facilidades para este tipo de
programao, o que obrigou a incorporao destes recursos posteriormente,
por meio de funes adicionais. Como a programao concorrente uma
forma de programao que difere bastante da programao sequencial
convencional, a simples adio de novas funes para tentar adaptar a
linguagem a esta forma de codificao, no cria um ajuste perfeito com a
linguagem subjacente. Por outro lado, J ava foi projetada visando facilitar a
programao concorrente. Isto faz com que a criao linhas de execuo
(threads) seja bem mais natural dos que nas linguagens
tradicionais.Programao em rede. J ava possui em seu ncleo bsico
classes para comunicao em rede por meio dos protocolos pertencentes
pilha de protocolos TCP/IP. A pilha de protocolos TCP/IP a utilizada pela
Internet e tornou-se o padro de fato para comunicao entre computadores
em uma rede heterognea. Isto torna J ava particularmente atrativa para o
desenvolvimento de aplicaes na Internet. Alm disso J ava est incorpora
um amplo de conjunto de solues para computao distribuda, como
CORBA (Common Object Request Broker Architecture), RMI (Remote
Method Invocation) e Servlets/J SP (aplicaes J ava que so executadas por
servidores Web).
Aps o lanamento da verso beta da linguagem em 1995, a Sun tem
liberado diversas evolues da linguagem na forma de verses e releases de um
conjunto de ferramentas denominado de J ava Development Kit (J DK) at a
verso 1.2, quando se passou a denominar J ava 2 SDK (Standard Development
Kit). Isto ocorreu porque outros kits de desenvolvimento com propsitos
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
10
especficos foram lanados, como o J 2EE (J ava 2 Enterprise Edition), voltado
para aplicaes distribudas escalveis e o J 2ME (J ava 2 Micro Edition), voltado
para aplicaes embutidas em dispositivos eletrnicos (Celulares, handheld,
etc.). Durante a elaborao deste livro, a ltima verso estvel do SDK era a de
nmero 1.3.1 que pode ser obtida gratuitamente no site http://java.sun.com/.
Convenes
As seguintes convenes so usadas neste livro.
1. Fontes com larguras constantes so usadas em:
exemplos de cdigo
public class Ponto {
private int x,y;
}
nomes de mtodos, classes e variveis mencionadas no texto.
2. Fontes com larguras constantes em negrito so usadas dentro de exemplos de
cdigos para destacar palavras chave.
3. Fontes em itlico so usadas:
em termos estrangeiros;
na primeira vez que for usado um termo cujo significado no for
conhecimento generalizado.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
11
Captulo II - Programao Orientada
a Objetos
O mundo pode ser visto como um conjunto de objetos que se relacionam.
Por exemplo, uma pessoa, uma casa, uma cadeira da casa, etc. Os objetos no
so necessariamente fsicos. Podem possuir uma natureza abstrata, como um
evento (uma partida de futebol) ou algo inexistente no mundo real (elefante cor-
de-rosa). Na verdade, o conceito de objeto atua no nvel lgico e no no real. Se
iremos representar algo como objeto ou no depende apenas de uma deciso a
nvel lgico que pode facilitar a simulao de determinado aspecto da realidade.
Os objetos se agrupam em classes, segundo propriedades ou atributos
comuns. Por exemplo, a classe dos retngulos agrupa todas as formas
geomtricas com a propriedade de possuir quatro lados formando ngulos de
90
o
. A relao entre um objeto e uma classe de pertinncia. Dizemos que um
objeto pertence a uma classe ou, mais comumente, que uma instncia de uma
classe. O Figura abaixo ilustra exemplos de classes.
Figura II-1. Classe dos (a) retngulos e dos (b) dos tringulos.
As classes podem ser relacionar com outra classe no sentido que uma
classe pode conter outra. Por exemplo, a classe de retngulos est inserida em
uma classe mais genrica, a classe dos polgonos. A classe mais genrica
denominada de Superclasse e as classes mais especficas so denominadas de
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
12
Subclasses. As subclasses herdam as propriedades das superclasses. No nosso
exemplo, os polgonos possuem as propriedades de ter uma rea, uma posio no
plano, um nmero n de vrtices e n-1 ngulos. Todas essas propriedades so
herdadas tanto pela classe dos retngulos como pela classe do tringulos.
Podemos desta forma organizar os objetos em uma hierarquia onde as classes
mais especficas herdam as propriedades das classes mais genricas.
Figura II-2. Classe dos polgonos.
Os objetos de uma classe possuem comportamentos que podem alterar o
valor de suas propriedades. Por exemplo, um carro pode sofrer uma acelerao
ou ser freado e com isso alterar a sua velocidade. Um objeto qualquer pode ser
deslocado, alterando assim as suas coordenadas no espao.
Classes e Objetos e Linguagens de Programao
As linguagens de programao so utilizadas para construir simulaes
de aspectos da realidade no computador. Quanto mais facilmente pudermos
expressar os conceitos capturados da realidade, mais facilmente construiremos a
simulao. Seguindo este raciocnio podemos concluir que as linguagens que
possuem facilidades para representao de objetos permitem uma modelagem
mais fcil dos conceitos do mundo real. No entanto, podemos utilizar uma
linguagem de programao convencional para modelar as classes e objetos
abstrados da realidade. Por exemplo, podemos modelar a classe dos retngulos
por meio de um registro (record) em Pascal.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
13
type Classe_Retangulo = record
X1,Y1,X2,Y2: integer;
end;
Exemplo II-1. Representao da Classe Retngulo em Pascal.
No Exemplo II-1 o retngulo definido por dois pontos, sendo X1 e Y1 o
ponto superior esquerdo e X2 e Y2 o ponto inferior direito. Os objetos podem
ser representados por meio de variveis do tipo definido:
type Classe_Retangulo = record
X1,Y1,X2,Y2: integer;
end;
var Retangulo1 : Classe_Retangulo;
Exemplo II-2. Criao de objetos em Pascal.
procedure intRetangulo(XA,YA,XB,YB: integer; var R:
Classe_Retangulo);
begin
R.X1 := XA;
R.Y1 := YA;
R.X2 := XB;
R.Y2 := YB;
end;
procedure MudaPos(X,Y: integer; var R: Classe_Retangulo);
begin
R.X2 := X+(R.X2-R.X1);
R.Y2 = Y+(R.Y2-R.Y1);
R.X1 = X;
R.Y1 = Y;
end;
Exemplo II-3. Definio das operaes em Pascal.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
14
As propriedades dos objetos podem ser manipuladas atravs de funes e
procedimentos. Por exemplo, podemos ter uma operao para inicializar os
valores da estrutura e outra para alterar a posio do retngulo. O Exemplo II-3
mostra essas duas operaes.
Contudo, existem algumas limitaes das linguagens convencionais que as
tornam inadequadas para a modelagem de objetos:
No existem recursos para ocultar a estrutura de dados de procedimentos
que no foram projetados para a sua manipulao. muito importante
que a linguagem fornea recursos para se implementar este tipo de
isolamento. Se acessarmos uma estrutura apenas por meio dos
procedimentos projetados para este fim, quando a estrutura for alterada
apenas os procedimentos que manipulam a estrutura sofreriam
modificaes. No entanto, se no agirmos desta forma ser necessrio
procurar em todo o programa os acessos diretos estrutura. Claro que
este comportamento pode ser adotado em qualquer linguagem, mas
mais seguro se a linguagem fornece meios para o programador forar
este tipo de comportamento. A capacidade de esconder a estrutura de
dados de acessos diretos chamada de ocultao de informao.
No existem recursos para herana de propriedades entre classes e
subclasses. Se precisarmos implementar uma estrutura que uma
especializao de outra j implementada, ser preciso codificar
novamente todas as propriedades, mesmo as comuns, e todos os
procedimentos de acesso. Isto dificulta o reaproveitamento de cdigo, o
que, consequentemente aumenta o tempo de desenvolvimento e a
possibilidade de erros.
No existe uma forma de relacionar explicitamente as estruturas de dados
com os procedimentos que as manipulam. O relacionamento entre os
procedimentos que manipulam uma estrutura de dados e a estrutura
estabelecido implicitamente, por meio de alguma conveno definida
pelo programador. importante que a linguagem obrigue o programador
relacionar explicitamente os procedimentos com a estrutura de dados, de
modo que fique claro qual a interface de acesso ao objeto.
A adoo de uma linguagem programao orientada a objetos resolve todos
esses problemas. Existem vrias linguagens comerciais com esta caracterstica:
Smalltalk, Eiffel, C++, etc. Algumas com elementos no orientados a objetos
como C++, outras puramente orientadas a objetos como Smalltalk, onde tudo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
15
objeto. J ava uma linguagem orientada a objetos mais pura do que C++,
fugindo desta orientao apenas em alguns pontos bem definidos, em nome da
eficincia de execuo. Em J ava podemos representar diretamente as classes e
objetos. Por exemplo, a classe retngulo seria declarada da seguinte forma:
class Retangulo
{
int X1,Y1,X2,Y2;
public Retangulo(int XA, int YA, int XB, int YB)
{
X1 = XA;
Y1 = YA;
X2 = XB;
Y2 = YB;
}
void MudaPos(int X, int Y)
{
X2 = X+(X2-X1);
Y2 = Y+(Y2-Y1);
X1 = X;
Y1 = Y;
};
}
Exemplo II-4.Representao da Classe Retngulo em Java.
No Exemplo II-4 mudamos o nome do procedimento iniRetangulo para
Retangulo, que o mesmo nome da classe. No momento no importante
entendermos a razo desta mudana, que ser esclarecida no prximo captulo.
Note que os procedimentos so declarados dentro do corpo da classe, tornando
explcito relacionamento entre a classe e os procedimento. As funes
declaradas nas classes so chamadas de mtodos e a partir de agora nos
referenciaremos a eles como tal. Note tambm que diferentemente do exemplo
em Pascal, no preciso passar o objeto como parmetro, uma vez que as
variveis que esto sendo modificadas pertencem ao objeto corrente, ao qual est
associado o mtodo. como se para cada objeto de uma classe fossem criadas
verses de todos os mtodos da classe, de modo que cada mtodo s opera sobre
as variveis do objeto a quem pertencem. Para declarar uma varivel do tipo da
classe basta preceder a varivel com o nome da classe.
Retangulo ret;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
16
At esse momento nenhum objeto foi criado. Para criar um objeto
(instncia) usado o operador new.
ret = new Retangulo(10,10,20,30);
Note que o operador new seguido de uma chamada ao mtodo com o
mesmo nome da classe. O mtodos com esta caracterstica so chamados de
construtores e s podem ser invocados durante a criao de um objeto. Como
veremos mais tarde, uma classe pode ter mais de um construtor. Aps a criao
do objeto possvel acessar os outros mtodos do objeto atravs do operador ..
Por exemplo, podemos mudar a posio do objeto por meio do mtodo MudaPos.
ret.MudaPos(40,40);
Como j dissemos, no preciso passar o objeto como argumento, j que
criada uma cpia do mtodo para cada objeto. A grosso modo podemos dizer
que cada instncia da classe recebe uma cpia da variveis e dos mtodos da
classe.
Ocultando de Informao
O projetista cuidadoso deve ocultar a representao interna da classe,
permitindo o acesso aos atributos da classe via mtodos predefinidos. Desta
forma a representao interna fica isolada do restante do programa e fica mais
fcil alter-la sem que seja preciso alterar outras partes do cdigo. A ocultao
de informao obtida por meio de qualificadores, como o private, que
impede o acesso variveis via mtodos definidos em outras classes. O nvel de
ocultao depende do qualificador utilizado. Todos os qualificadores sero
abordados com detalhes no Captulo IV. O exemplo II-5 mostra como impedir
que as variveis declaradas na classe Retangulo sejam acessadas diretamente.
class Retangulo
{
private int X1,Y1,X2,Y2;
public Retangulo(int XA, int YA, int XB, int YB)
{
X1 = XA;
Y1 = YA;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
17
X2 = XB;
Y2 = YB;
}
void MudaPos(int X, int Y)
{
X2 = X+(X2-X1);
Y2 = Y+(Y2-Y1);
X1 = X;
Y1 = Y;
};
}
Exemplo II-5. Ocultando informao em Java.
Especializao e Herana
Para criar uma subclasse de uma classe pr-existente utilizamos o
operador extends. Por exemplo, podemos definir uma subclasse da classe
Retangulo, chamada de RetanguloColorido, que possui, alm das variveis e
mtodos herdados da superclasse, uma varivel para armazenar a cor do
retngulo, juntamente com um mtodo para alterar o valor.
class RetanguloColorido extends Retangulo
{
private Color Cor;
void AtribuiCor(Color C)
{
Cor = C;
};
}
Exemplo II-6. Declarando subclasses em Java.
A princpio, subclasse pode acessar todos os mtodos e variveis da
superclasse. No entanto, isto tambm pode ser alterado via qualificadores.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
18
Sobrescrita, Sobrecarga e Polimorfismo
Podemos definir mais de um mtodo com o mesmo nome na mesma
classe ou subclasses. Caso o mtodo possua a mesma assinatura (nmero e tipos
de argumentos e tipo de retorno) que outro mtodo, ento o mtodo no pode
pertencer mesma classe do anterior. Se ambos os mtodos estiverem na mesma
linha hierrquica (classe/subclasse), dizemos que o mtodo da subclasse
sobrescreve o mtodo da superclasse. O mtodo que ser executado depender
da classe do objeto.
class Empregado
{
protected float salario;
public float getSalario() {return salario;}
}
class Vendedor extends Empregado
{
protected float comissao;
public float getSalario() {return salario+comissao;}
}
Exemplo II-7. Sobrescrita do mtodo getSalario().
No exemplo II-7 o mtodo getSalario() da classe Vendedor
sobrescreve o mtodo do mesmo nome da classe Empregado.
Se a assinatura do mtodo for diferente de outro mtodo com o mesmo
nome definido anteriormente na mesma classe ou em outra classe da mesma
linha hierrquica, ento estamos realizando uma sobrecarga sobre o
identificador do mtodo. Quando for usado o identificador dentro do cdigo de
um programa o mtodo invocado ser determinado pela classe a que pertence o
objeto do mtodo e pelo nmero e tipos dos argumentos passados para o mtodo.
O termo sobrecarga advm do fato de um mesmo identificador denotar mais de
mtodo.
class Empregado
{
protected float salario;
public void aumento() {salario= salario*10.0;}
public void aumento(float porcent)
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
19
{
salario= salario*porcent;
}
}
Exemplo II-8. Sobrecarga do mtodo aumento().
No exemplo II-8 o identificador aumento pode referenciar dois mtodos
distintos. Um aumenta o salrio em 10% e no outro o aumento depende do valor
da porcentagem passado como parmetro. Note que as assinaturas do mtodos
diferem entre si.
Alguns autores chamam sobrecarga de polimorfismo, que a habilidade
de um determinado objeto se comportar ou ser visto de diferentes formas,
quando na verdade a sobrecarga um tipo particular de polimorfismo, chamado
de polimorfismo ad hoc . Na sobrecarga um identificador representa vrios
mtodos com computaes distintas. Existe tambm o polimorfismo
paramtrico, onde um mtodo pode realizar a mesma computao sobre objetos
de tipos distintos. Isso pode ser implementado em J ava definindo um mtodo
que recebe e retorna objetos da classe Object. Como a classe Object a me
de todas as classes o mtodo pode operar da mesma forma independente da
classe a qual o objeto realmente pertence, desde que a computao seja
independente da classe.
class Poli
{
public Object identidade(Object objeto)
{
return Object;
}
}
Exemplo II-9. Polimorfismo paramtrico.
No Exemplo II-9 o mtodo identidade() retorna o objeto passado
como parmetro. Este mtodo realiza a mesma computao, independentemente
da classe do objeto. Obviamente um exemplo muito simples e sem utilidade
prtica mas serve para ilustrar o conceito de polimorfismo paramtrico.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
20
Introduo Diagrama de Classes
possvel registrar diretamente em uma linguagem de programao os
objetos percebidos em uma determinada realidade. No entanto, melhor
utilizarmos uma notao grfica intermediria para melhor visualizarmos os
objetos e as relaes entre objetos, e ir alterando esta representao at estarmos
seguros que possumos um entendimento razovel do problema, e ai sim,
partirmos para a codificao da soluo. Muitas vezes preciso recorrer a mais
de uma notao grfica, de modo a expressar vrias facetas da realidade que est
sendo modelada. Neste livro, recorreremos ao uso de notao grfica em alguns
exemplos para ilustrarmos a arquitetura dos programas antes de apresentarmos o
cdigo. Acreditamos que desta forma o leitor compreender melhor os
exemplos.
A notao grfica que adotamos mostra as relaes estticas entre classes
de objetos. Ela faz parte do conjunto de notaes da UML (Unified Modeling
Language ou Linguagem de Modelagem Unificada) proposta por Grady Booch,
J ames Rumbaugh e Ivar J acobson em 1995. A UML um conjunto de notaes
que tem por objetivo modelar diversos aspectos de um sistema em diferentes
nveis de abstrao. Ou seja, pode ser utilizado para a captura de requisitos de
um sistema assim como em projeto de programas. voltada para anlise e
projeto de sistemas orientados a objetos. A rea de anlise e projeto orientados a
objetos ainda no possui uma notao vencedora como existe para a anlise e
projeto estruturado. Contudo, a UML vem se popularizando rapidamente, e
encontrada com facilidade em textos de programao, sobretudo em se tratando
de J ava. Portanto, um conhecimento sobre as principais notaes que constituem
a UML importante para qualquer um que deseja ingressar na rea de
programao orientada a objetos. Este livro utiliza uma das linguagens, ou
diagramas, que compem a UML: o diagrama de classes.
Diagrama de Classes
O Diagrama de Classes representa graficamente as classes do sistema e o
relacionamento esttico entre as classes, isto , o relacionamento que no muda
com o tempo. Por exemplo, em um sistema acadmico, um aluno cursa vrias
disciplinas. O nmero de disciplinas e a disciplina que efetivamente est sendo
cursada pode alterar, mas o vnculo aluno-cursa-displinas permanece. Para
ilustrar o nosso estudo dos diagramas da UML utilizaremos exemplos sobre
modelagem de aspectos realidade acadmica.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
21
Uma classe representada no diagrama de classes por meio de um
retngulo, que pode ser dividido em at trs sees horizontais, como mostrado
na figura abaixo:
Figura II-3. Forma geral para representao de uma classe.
A seo superior usada para registrar o nome da classe. A seo
intermediria reservada para registro das propriedades da classe, caso existam,
e na seo inferior registrado a assinatura dos mtodos que pertencem classe,
caso existam. Por assinatura do mtodo queremos dizer o nome do mtodo,
juntamente com seus argumentos e valor de retorno. A figura abaixo mostra uma
representao da classe das disciplinas.
Figura II-4. Representao da classe das disciplinas
De modo geral, por razes de simplicidade, no se representam os
mtodos que tratam da alterao dos atributos e construtores. Se Assumi que
toda classe possui estes mtodos. Portanto, podemos simplificar a representao
acima, omitindo a seo do mtodos.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
22
Figura II-5. Representao simplificada da classe das disciplinas.
Podemos indicar tanto nos atributos quanto nas classes a visibilidade
deles em relao a outras classes. As visibilidades possveis, juntamente com os
smbolos adotados esto listados na tabela abaixo:
Visibilidade Smbolo Descrio
Pblica + Sem restrio de acesso.
Protegida # Pode ser acessado apenas na prpria classe e
por subclasses.
Privada - Pode ser acessado apenas na prpria classe.
Tabela II-1. Visibilidades possveis para atributos e mtodos.
A visibilidade atribuda a um atributo ou mtodo precedendo a
declarao do mtodo com o smbolo adequado, como na figura abaixo:
Figura II-6. Representao com visibilidade.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
23
As classes podem se relacionar de diversas formas: por associao
comum, por agregao e generalizao. Abaixo apresentada cada forma de
relacionamento, juntamente com suas as notaes.
Associao comum
A notao utilizada para associar duas classes simplesmente uma linha
unindo as classes. A figura II.7 mostra a associao entre a classe dos alunos e a
classe das disciplinas.
Figura II-7. Associao entre Aluno e Disciplina.
A figura acima expressa que alunos se associam com disciplinas mas no
indica se um aluno se relaciona com vrias ou apenas uma disciplina. Esta
informao chamada de cardinalidade da relao e expressa anotando-se o
valor da cardinalidade na associao junto classe que est sendo relacionada.
Assim, a figura II.8 expressa que um aluno se relaciona com vrias disciplinas.
Figura II-8. Associao de um Aluno com vrias Disciplinas.
Como uma disciplina se relaciona com vrios alunos, o diagrama
completo o representado na figura II-9.
Figura II-9. Associao de vrios Aluno com vrias Disciplinas.
A tabela II-2 mostra algumas representaes de cardinalidade:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
24
Notao Descrio
1 Exatamente um
* ou 0..* Zero ou mais
0..1 Opcional (zero ou um)
n..m Mximo e mnimo
Tabela II-2. Representaes de cardinalidade.
At agora apresentamos apenas associaes entre duas classes, mas nada
impede que mais de duas classes participem de uma associao. Por exemplo, a
figura II-10 ilustra uma associao ternria que representa o fato de um aluno
cursar uma disciplina em um perodo.
Figura II-10. Associao entre aluno, disciplina e perodo.
Uma associao pode ter atributos prprios. Ou seja, atributos que no
pertenam a nenhuma das classes envolvidas na associao mas sim prpria
associao. Na associao entre alunos e disciplina o atributo nota, no pertence
a aluno, tampouco disciplina, uma vez que para saber uma nota preciso saber
quem o aluno e qual a disciplina. A representao de atributos da associao
representada por meio de um retngulo ligado associao por meio de uma
linha tracejada.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
25
Figura II-11. Representao de atributos de associao.
Agregao
Alguns objetos so compostos por outros objetos. Por exemplo, um carro
composto por chassi, lataria, pneus e motor, que por sua vez composto pelo
carburador, pistes, bloco, etc. Este tipo de associao representada por uma
linha com um losango na ponta.
Figura II-12. Agregao entre Curso e Disciplina.
Generalizao
O ltimo tipo de associao entre classes o que o ocorre entre
superclasses e subclasses. Uma superclasse uma generalizao das suas
subclasses, que herdam os atributos e mtodos da primeira. A notao utilizada
para representar a generalizao uma linha com um tringulo na extremidade
da associao no lado da classe mais genrica.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
26
Figura II-13. Representao da generalizao.
A figura II-14 procura representar todas associaes discutidas em um
nico diagrama.
Figura II-14. Associao entre as classes do domnio acadmico.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
27
Captulo III - Introduo
Linguagem Java
Existe uma tradio entre os programadores que estabelece que ao se
comear a aprender uma nova linguagem de programao, o primeiro programa
a ser escrito deve ser um que imprima a frase Ol mundo em um dispositivo
de sada. Dizem que isto atrai a sorte e espanta os bugs. Independente da crena
geral, existem algumas razes bastante justificveis para se comear o
aprendizado de uma linguagem executando logo um programa, mesmo sem ter
muita idia do que se est fazendo. Primeiramente, existe o fator psicolgico.
Iniciar o aprendizado executando um programa sem erros, aumenta confiana do
aluno e elimina temores de se estar aprendendo algo muito complexo. Existe
tambm o fato de que apesar de um programa muito simples dar uma viso um
pouco limitada da linguagem, j possvel observar alguns elementos
importantes. Afinal trata-se de um programa completo. Portanto, para no fugir a
tradio, eis o programa OlaMundo em J ava:
public class OlaMundo
{
public void exibeOla()
{
System.out.println(Ola, Mundo!);
}
public static void main(String args[])
{
OlaMundo obj = new OlaMundo();
Obj.exibeOla();
}
}
Exemplo III-1. Programa OlaMundo.
O programa acima composto por uma nica classe que possui apenas
dois mtodos. Isto importante, porque no possvel fazer um programa J ava
sem recorrer s classes, uma vez que os procedimentos so definidos como
mtodos de classes. Isto no verdade em linguagens como C++, o que diminui
o seu grau de orientao a objetos.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
28
Os mtodos com o nome main so mtodos especiais e servem como
ponto inicial para execuo do programa. Ou seja, a execuo do programa ser
iniciada a partir da execuo de um mtodo main(). A assinatura do mtodo
main sempre a mesma e a sua descrio em detalhes ser vista na seo
Argumentos da linha de comando. Podemos adiantar apenas que o qualificador
public estabelece que este mtodo pode ser chamado por mtodos ou
procedimentos externos classe. O qualificador static significa que o mtodo
pertence classe e no s instncias da classe, e deste modo pode ser invocado
mesmo antes de ser criado algum objeto para a classe. void indica que o mtodo
no retornar valor algum. J argumento String args[] um array de
Strings contendo os parmetros passados na linha de comando.
O corpo do mtodo main() possui duas linhas. A primeira instruo cria
um objeto da classe OlaMundo e o atribui varivel obj. A segunda linha invoca
o mtodo exibeOla() do objeto recm criado. O mtodo exibeOla() invoca o
mtodo println() do objeto out da classe System, que faz parte do pacote de
classes fornecido com a linguagem. Este mtodo exibe no dispositivo de sada
padro a String que passada como argumento.
Se voc olhar os programas OlaMundo mostrados em outros livros
sobre J ava ir notar que o programa apresentado aqui um pouco mais
complicado que o exibido nesses livros. Geralmente este programa inicial
apresentado apenas com um mtodo: o mtodo main(). A razo de termos usado
uma abordagem diferente que desejamos desenvolver um hbito saudvel na
programao em J ava: procure usar o mtodo main() apenas para criar os
objetos e deixe que os objetos executem a lgica do problema.
Este programa deve ser salvo em um arquivo contendo O MESMO
NOME DA CLASSE e com as mesmas letras maisculas e minsculas (
importante frisar, uma vez que esquecer este detalhe um erro muito comum), e
com a extenso .java. Portanto o arquivo contendo o programa acima dever
se chamar OlaMundo.java. Se voc instalou o J ava 2 development kit (SDK),
que pode ser obtido gratuitamente no site http://java.sun.com/products/, ento
para compilar o programa basta digitar o comando:
javac OlaMundo.java
O cdigo J ava traduzido (o termo mais comum compilado) para
instrues de uma mquina virtual (bytecodes) para que possa ser executado de
forma independente da plataforma (sistema operacional e hardware). O cdigo
em bytecodes armazenado em um arquivo com o mesmo nome do original e
com a extenso .class. Assim aps a execuo do comando acima ser
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
29
gerado o arquivo OlaMundo.class. A invocao da mquina virtual para
executar o cdigo em bytecodes efetuada por meio do seguinte comando:
java OlaMundo
Neste ponto nota-se uma desagradvel idiossincrasia do SDK. Para
compilar o programa para bytecode foi necessrio explicitar a extenso do
arquivo, porm, para executar o cdigo preciso omitir a extenso .class.
Apesar de ser um detalhe que aparentemente no prejudica o uso do ambiente,
confunde o usurio, principalmente o iniciante.
Quando recebe um arquivo de bytecodes para a executar, a mquina
virtual procura o mtodo main() em uma classe com o mesmo nome do arquivo.
Uma vez encontrado o mtodo a execuo iniciada com a execuo do mtodo.
Isto significa que em nosso exemplo ser procurado o mtodo main() da classe
OlaMundo para servir de ponto de entrada. Podem existir outros mtodos main()
em outras classes codificadas no mesmo arquivo de bytecodes, mas apenas o
mtodo main() da classe com o mesmo nome do arquivo servir de ponto inicial
de execuo. Portanto, em nosso caso, o programa ser executado produzindo a
sada:
Ola, Mundo!
Agora que j cumprimos o ritual de iniciao na linguagem, podemos passar a
descrever os detalhes da linguagem. Grande parte das descries que seguem
abaixo foram baseadas na especificao da linguagem registrada no livro The
Java Language Specification, segunda edio, por J ames Gosling e outros.
Identificadores
Todos os identificadores da linguagem devem iniciar com uma letra, ou o
caractere _`, ou o caractere $`. Deve-se evitar o uso do caractere $`, de modo
que fique reservado para gerao de cdigo automtico. Tratamos por letra todo
caractere reconhecido pelo mtodo Character.isJavaLetter. Isto inclui uma
ampla gama de caracteres do conjunto Unicode
1
, de modo que os programadores
podem usar identificadores adaptados a uma ampla gama de idiomas. Aps o

1
O conjunto de caracteres Unicode foi criado para substituir o conjunto ASCII. Ele usa 16 bits
para representar os caracteres, o que resulta em 65536 caracteres possveis, em oposio aos 7
bits do cdigo ASCII (8 para o ASCII estendido), o que resulta em 128 caracteres possveis (256
para 8 bits).
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
30
primeiro caractere, tambm podem ser usados os caracteres que vo de 0` at
9`. A linguagem J ava distingue as letras maisculas das minsculas, portanto o
identificador Aluno distinto do identificador aluno. A tabela III-1 mostra
alguns identificadores vlidos e invlidos.
Vlido Invlido
Aluno10 Aluno#10
Num_Alunos Num Alunos
_disciplina$ !disciplina
Professor_10 10Professor

&uuu
No No?
Tabela III-1. Identificadores vlidos e invlidos em Java.
Palavras Reservadas
As seguintes sequncias de caracteres so reservadas para o uso como
palavras chave e, portanto, no podem ser usadas como identificadores:
abstract continue goto package synchronized
assert
2
default if private this
boolean do implements protected throw
break double import public throws
byte else instanceof return transient
case extends int short try
catch final interface static void
char finally long strictfp
3
volatile
class float native super while
const for new switch
Tabela III-2. Palavras reservadas da linguagem Java.
As palavras chave const e goto, apesar de serem reservadas, no esto
sendo usadas correntemente na linguagem.

2
Introduzida a partir da verso 1.4 do SDK.
3
Introduzida a partir da verso 1.2 do SDK
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
31
Literais
Literais so elementos do cdigo que representam um valor de tipo
primitivo, tipo String ou null. Os literais podem ser numricos, booleanos,
caracteres ou cadeias de caracteres (Strings). Literais numricos incluem
inteiros, ponto flutuante.
Literais Inteiros
Um literal inteiro do tipo primitivo long (longo) se possui o sufixo L`
ou l`, caso contrrio do tipo primitivo int (inteiro). Um numeral hexadecimal
prefixado pelos caracteres 0x` ou 0X` seguidos de um ou mais dgitos
hexadecimais. Os dgitos hexadecimais com valores entre 10 e 15 so
representados pela letras a` at f` ou A` at F`, nessa ordem. Um numeral
octal consiste de um dgito 0 seguido de um ou mais dgitos de 0 at 7.
O maior literal decimal do tipo int 2147483648. Os literais decimais
de 0 at 2147483647 podem aparecer em qualquer lugar que um literal inteiro
pode aparecer, mas o literal 2147483648 pode aparecer somente como operando
de uma negao unria.
Os maiores literais hexadecimal e octal positivos inteiros so 0x7fffffff e
017777777777, respectivamente, que correspondem ao valor decimal
2147483647. Os maiores literais hexadecimal e octal negativos inteiros so
0x80000000 e 020000000000, respectivamente, que representam o valor
decimal -2147483648 (). Os literais hexadecimal e octal 0xffffffff e
037777777777, representam o valor decimal -1. Abaixo esto listados alguns
exemplos de literais inteiros:
0 -12 0372 0xCafe 1999 0x00FF00FF
O maior literal decimal do tipo longo o 9223372036854775808L. Os
literais decimais de 0L at 9223372036854775807L podem aparecer em
qualquer lugar que um literal inteiro longo pode aparecer, porm o literal
9223372036854775808L pode aparecer somente como operando de uma
negao unria.
Os maiores literais hexadecimal e octal positivos inteiros longos so
0x7fffffffffffffffL e 0777777777777777777777L, respectivamente, que
correspondem ao valor decimal 9223372036854775807L.Os maiores literais
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
32
hexadecimal e octal negativos inteiros longos so 0x8000000000000000L e
01000000000000000000000L, respectivamente, que representam o valor
decimal -9223372036854775808L. Os literais hexadecimal e octal
0xffffffffffffffffL e 01777777777777777777777L, representam o valor decimal -
1. Abaixo esto listados alguns exemplos de literais inteiros longos:
0L 0777L 0xC0B0L 0xCafe 1999 0x100000000L
Literais de Ponto Flutuante
Um literal de ponto flutuante composto por uma parte inteira seguida
de um ponto decimal, uma parte fracionria, um expoente e um sufixo
determinando o tipo. O expoente, se presente, indicado pela letra E ou e,
seguido por um inteiro com sinal um opcional. Pelo menos um dgito na parte
inteira ou fracionria e o ponto decimal ou o expoente ou o sufixo indicando o
tipo so exigidos. Todos os outros componentes so opcionais.
Um tipo ponto flutuante do tipo float se possuir o sufixo F ou f,
caso contrrio do tipo double. O tipo double possuir opcionalmente o sufixo
D ou d.
O tipo float e double de J ava obedecem a especificao IEEE 754 para
binrios de ponto flutuante de preciso simples (32-bit) e dupla (64-bit).
O maior literal positivo do tipo float 3.40282347e+38f. O menor
literal positivo do tipo float diferente de zero 1.40239846e-45f. O maior
literal positivo do tipo double 1.79769313486231570e+308. O menor literal
positivo do tipo double diferente de zero 4.94065645841246544e-324.
Um programa em J ava pode representar quantidades infinitas sem
produzir erros de compilao por meio da utilizao de expresses constantes
tais como 1f/0f e -1d/0d ou pela utilizao das constantes predefinidas
POSITIVE_INFINITY e NEGATIVE_INFINITY das classes Float e Double.
Exemplos de literais do tipo float:
1e1f 2.f .3f 0f 3.14f 6.022137e+23f
Exemplos de literais do tipo double:
1e1 2. .3 0.0 3.14 1e-9d 1e137
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
33
Literais Booleanos
O tipo boolean possui dois valores, representados pelos literais true e
false.
Literais de Caracteres
Um literal do tipo char expresso como um caractere ou uma sequncia
de escape, envolvida por aspas simples. Os caracteres CR e LF nunca so
caracteres de entrada, uma vez que so reconhecidos como terminadores de
linha. Exemplos de literais do tipo char:
Caractere Descrio
'a' o caractere a.
'%' o caractere %
'\n' line feed
'\t' Tab
'\\' o caractere \
'\'' o caractere '.
'\u03a9'
'\uFFFF'
'\177'
Tabela III-3. Exemplo de literais do tipo char.
Literais de Cadeia de Caracteres (Strings)
Um literal do tipo String consiste de zero ou mais caracteres envolvidos
por aspas duplas. Cada caractere pode ser representado por uma sequncia de
escapes. O tipo String no um tipo primitivo e sim uma classe denominada
String. Portanto, um literal na verdade uma instncia da classe String.
Uma String longa pode ser particionada em cadeias menores unidas
pelo operador de concatenao +. Exemplos de literais do tipo String:
Literal Descrio
"" Cadeia vazia.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
34
"\"" Uma cadeia com apenas o caractere ".
"esta uma cadeia" Uma cadeia contendo 17 caracteres.
"esta uma "
+"cadeia "
Uma cadeia formada por dois literais do
tipo String.
Tabela III-4. Exemplo de literais do tipo String.
Sequncias de escape
Sequncias de escape permitem a representao de alguns caracteres no
grficos, assim como as aspas simples e duplas e a barra invertida. Exemplos de
sequncias de escape:
Sequncia Descrio
\b \u0008: backspace BS
\t \u0009: tab horizontal HT
\n \u000a: linefeed LF
\f \u000c: form feed FF
\r \u000d: carriage return CR
\" \u0022: aspas duplas "
\' \u0027: aspas simples '
\\ \u005c: barra invertida \
Tabela III-5. Exemplo sequncias de escape.
O Literal null
O tipo null possui apenas um valor, representado pelo literal null.
Separadores
J ava possui nove separadores (caracteres de pontuao), listados abaixo:
( ) { } [ ] ; , .
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
35
Tipos de dados
Os tipos de dados definem como devem ser interpretados os dados
armazenados. So essenciais a toda linguagem de programao e devem ser
cuidadosamente selecionados para compor a linguagem, de modo a no limitar a
sua rea de atuao. A maioria da linguagens modernas definem um conjunto de
tipos simples, um conjunto de tipos compostos, formados por tipos mais
primitivos e alguma forma de definio de novos tipos, de modo que possa
modelar mais apropriadamente a realidade. A linguagem J ava obedece esta
regra, fornecendo um conjunto de tipos simples e um conjunto de tipos
compostos. O mecanismo para definio de novos tipos utilizado por J ava
simplesmente a definio de classes.
J ava uma linguagem fortemente tipada. Isto significa que toda varivel
e expresso possui um tipo determinado em tempo de compilao. Os tipos
primitivos disponveis em J ava no so classes. Esta uma das razes porque
J ava no uma linguagem 100% orientada a objetos. No entanto, para cada tipo
primitivo existe uma classe correspondente onde so declarados um conjunto de
mtodos para a manipulao dos valores primitivos, focalizando principalmente
na converso de tipos. Estas classes esto agrupadas no pacote java.lang. Por
exemplo, o tipo primitivo int usado para expressar valores inteiros. A classe
correspondente ao tipo int a Integer. Nela esto declaradas variveis
pblicas contendo o valor mximo e mnimo que uma varivel do tipo inteiro
pode armazenar e mtodos para converso para outros tipos.
Tipos de dados simples
Tipos de dados simples so aqueles que no podem ser divididos em
tipos mais primitivos. Os tipos de dados simples de J ava podem ser divididos em
inteiros, ponto flutuante, booleano e caractere. Para se definir uma varivel de
um determinado tipo basta preceder o nome da varivel com o nome do tipo
desejado, como na forma abaixo:
<nome do tipo> <nome da varivel>;
Assim, para se declarar uma varivel var1 do tipo inteiro basta a linha de
cdigo abaixo:
int var1;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
36
Podemos tambm declarar mais de uma varivel em com o mesmo tipo,
usando o caractere , como separador. Portanto, a declarao
int var1, var2;
equivalente s declaraes
int var1;
int var2;
J ava tambm permite que as variveis sejam inicializadas durante a
declarao. Assim, para inicializarmos a varivel var1 com o valor 1 na
declarao basta a linha de cdigo abaixo:
int var1=1;
Segue abaixo as categorias de tipos de dados simples.
Inteiros
Nome Tamanho
byte 8 bits
short 16 bits
int 32 bits
long 64 bits
Tabela III-6. Tipos inteiros.
Ponto Flutuante
Nome Tamanho
float 32 bits
double 64 bits
Tabela III-7. Tipos de ponto flutuante.
booleanos
boolean {true,false}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
37
Caractere
char 16 bits
Tipos de dados compostos
Os tipos de dados compostos so constitudos por tipos mais simples.
Todos os tipos compostos em J ava so Classes. Nesta seo trataremos duas
classes de objetos muito usadas em J ava para criao de tipos compostos: os
arrays (arranjos) e strings. Posteriormente abordaremos a declarao de objetos
no caso geral e no Captulo VI ser apresentado o pacote de classes java.util
que contm vrias classes para agrupamento de objetos.
Arrays
Um array um objeto, e como tal herda todos os mtodos da classe
Object. Um array contm um certo nmero de variveis chamadas de
componentes. Em J ava todo objeto acessado indiretamente, via uma referncia.
Ou seja, no se cria uma varivel do tipo de um objeto e sim uma varivel que
pode referenciar um objeto. Estamos falando de ponteiros, o que pode parecer
contraditrio, uma vez que tnhamos mencionado que J ava no possui ponteiros.
Na verdade J ava acessa as instncias de objeto por meio de ponteiros mas eles
no esto disponveis como tipo da linguagem e nem possvel que o
programador os manipule diretamente.
Pode parecer pouco importante para o programador saber que a varivel
no armazena o objeto diretamente e sim uma referncia a um objeto, uma vez
que ele no pode manipular ponteiros. No entanto, acreditamos que esta
informao importante para que o leitor possa entender as etapas para a criao
de objetos. A primeira etapa a declarao da varivel para referenciar o objeto
e a segunda etapa a criao do objeto propriamente dito. Para se declarar uma
varivel para referenciar objetos do tipo array usada a seguinte sintaxe:
tipo identificador[];
tipo[] identificador;
Exemplos
int numeros[];
char[] letras;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
38
long grade[][];
Note que no definido o nmero de elementos do array. Isto faz parte
do objeto. Note tambm que existem duas formas de declaraes de referncias a
arrays. O nmero de [] indica o nmero de dimenses do array. A criao do
objeto realizada por meio do operador new, seguido pelo tipo do array e pelo
nmero de componentes de cada dimenso, como nos exemplos abaixo:
numeros = new int[10];
char alfabeto[] = new char[26];
grade = new long[10][10];
Alternativamente podemos realizar as duas etapas acima e ainda definir
os elementos do array em uma nica declarao como no exemplo abaixo, onde
criado um array de trs inteiros, referenciados pela varivel primos e onde o
primeiro elemento 7, o segundo 11 e o terceiro 13.
int primos = {7, 11, 13};
De agora em diante no faremos distino entre referncia a objeto do
tipo array e o objeto array, a no ser que seja necessrio explicitar esta distino.
O acesso aos elementos do array realizado por meio do nome da
varivel seguida por um expresso inteira no negativa envolvida pelos
caracteres [ e ]. A expresso inteira chamada de ndice e os valores
admissveis para a expresso vai de 0 a n-1, onde n nmero de elementos do
array. O ndice do primeiro elemento 0. Abaixo seguem alguns exemplos:
alfabeto[0] = a;
grade[0][5] = 10L;
for(int i=0; i<10; i++) numeros[i] = i*2;
possvel descobrir o tamanho de um array em tempo de execuo
acessando a varivel pblica length do objeto, onde est armazenada a
capacidade do array. Por exemplo:
for(int i=0; i< numeros.length; i++) numeros[i] = i*2;
Strings
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
39
O manipulao de cadeias de caracteres (strings) em J ava realizada por
uma classe do pacote java.lang denominada String. Ou seja, no existe um
tipo primitivo para tratar cadeias de caracteres. Para se declarar uma varivel que
faz referencia a um objeto String usa-se a seguinte linha de comando:
String nome;
Para que a varivel faa referncia a um objeto basta criar um objeto por
meio do operador new ou atribuir a referncia de um objeto preexistente.
nome = new String(Pedro);
String x, y;
x= nome;
y = Pedro;
No primeiro caso a varivel nome faz referencia a um objeto recm criado
contendo o valor Pedro. J a varivel x faz referencia ao mesmo objeto
referenciado pela varivel nome. Ou seja, nenhum novo objeto String criado,
ocorrendo um compartilhamento de objetos. J a varivel y faz referncia a um
objeto String contendo o valor Pedro, distinto do objeto referenciado por x e
nome. Podemos tambm inicializar a varivel durante a declarao.
String nome = Pedro;
Os objetos do tipo String possuem um conjunto extenso de mtodos e
construtores para a manipulao e criao de Strings. A tabela abaixo mostra
alguns dos mais utilizados.
Construtor Descrio
String(byte[] bytes, int offset,
int num)
Constri uma nova String convertendo o subarray de
bytes especificado
String(StringBuffer buffer)
Constri uma nova String usando a sequncia de
caracteres contida no StringBuffer.
String(byte[] bytes)
Constri uma nova String convertendo o array de
bytes especificado
String(String valor)
Constri uma nova String com o mesmo contedo
da String passada como argumento.
String()
Constri uma nova String contendo zero caracteres.
String(char[] valor)
Constri uma nova String convertendo o array de
caracteres especificado.
String(char[] valor, int offset,
int num)
Constri uma nova String convertendo o subarray de
caracteres especificado.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
40
Tabela III-8. Principais construtores da classe String.
Mtodo Descrio
charAt(int indice) Retorna o caractere localizado no ndice especificado.
compareTo(String
outraString)
Compara duas Strings lexicograficamente.
equals(Object anObject) Verifica se dois objetos so iguais.
getChars(int srcBegin,
int srcEnd, char[] dst,
int dstBegin)
Copia os caracteres da String em um array de
caracteres.
indexOf(String str) Retorna o ndice da primeira ocorrncia do substring
no string.
indexOf(String str, int
fromIndex)
Retorna o ndice da primeira ocorrncia do substring
no string a partir do ndice especificado.
indexOf(int ch, int
fromIndex)
Retorna o ndice da primeira ocorrncia do caractere
no string a partir do ndice especificado.
indexOf(int ch) Retorna o ndice da primeira ocorrncia do caractere
no string .
length() Retorna o comprimento do string.
replace(char oldChar,
char newChar)
Retorna uma nova String onde todos os caracteres
oldChar foram substitudos pelos caracteres
newChar.
substring(int beginIndex) Retorna uma nova string que substring da atual.
substring(int beginIndex,
int endIndex)
Retorna uma nova string que substring da atual.
toLowerCase() Converte para minsculas.
toUpperCase() Converte para Maisculas.
trim() Remove os espaos em branco do inicio e do fim do
String.
valueOf(Object obj) Retorna a representao em String do argumento
Object.
valueOf(char c) Retorna a representao em String do argumento
char.
valueOf(boolean b) Retorna a representao em String do argumento
booleano.
valueOf(long l) Retorna a representao em String do argumento
long.
valueOf(int i) Retorna a representao em String do argumento int..
valueOf(char[] data) Retorna a representao em String do argumento
array de caracteres
valueOf(float f) Retorna a representao em String do argumento
float.
valueOf(double d) Retorna a representao em String do argumento
double.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
41
Tabela III-9. Principais mtodos da classe String.
Os literais de Strings so tratados como instncias da classe String e
como tal possuem os mtodos de um objeto da classe String. Por exemplo,
aps a execuo da expresso abaixo a varivel x conter o valor 5.
int x = Pedro.length();
Converso de Tipos
De forma geral as converses entre tipos em J ava devem ser
especificadas explicitamente. A forma mais comum de se especificar uma
converso por meio da notao abaixo:
(<tipo destino>) <expresso>
Por exemplo:
int i = 10;
char c = (char) i;
Este tipo de converso chamada de casting. O programador deve ficar
bastante atento no que diz respeito a converses, uma vez que pode acontecer
perda de informao quando convertemos um tipo para outro que ocupa um
espao menor na memria. A tabela abaixo mostra as converses entre tipos
primitivos que podem causar perda de informao:
do tipo para o tipo
byte char
short byte, char
char byte, short
int byte, short, char
long byte, short, char, int
float byte, short, char, int, long
double byte, short, char, int, long, float
Tabela III-10. Converso de tipos que podem causar perda de informao.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
42
Outra forma de converter tipos usando os mtodos fornecidos pelas
classes associadas aos tipos. A tabela abaixo mostra a classe associada a cada
tipo primitivo.
Tipo Classe
int Integer
float Float
double Double
boolean Boolean
byte Byte
short Short
long Long
Tabela III-11. Classes associadas a cada tipo primitivo.
As classes fornecem mtodos para converso mais sofisticados como do
tipo primitivo para String e vice-versa. Por exemplo, a classe Integer
fornece um mtodo para converter String para int:
int i = Integer.parseInt(12);
Para se converter um inteiro para String podemos utilizar o mtodo
toString():
String s = Integer.toString(12);
Existem mtodos semelhantes nas outras classes. Existe tambm um tipo
de converso que somente se aplica aos operandos do operador binrio +
quando um dos operandos um objeto da classe String. Caso o outro operando
no seja um objeto da classe String, ento ele ser convertido para String e o
resultado da operao ser a concatenao das duas cadeias. As Converses
entre objetos de classes distintas sero tratadas no prximo Captulo.
Operadores
Os operadores atuam sobre valores e variveis de modo a gerar novos
valores ou modificar os valores das variveis. Os smbolos abaixo representam
os 37 operadores da linguagem J ava:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
43
= > < ! ~ ? :
== <= >= != && || ++ --
+ - * / & | ^ % << >> >>>
+= -= *= /= &= |= ^= %= <<= >>= >>>=
Os operadores podem ser divididos nas seguintes classes.
Unrios
Descrio Smbolo
Incremento ++
Decremento --
Negativo -
Complemento de bit ~
Tabela III-12. Operadores unrios.
Os operadores de incremento e decremento (++ e --) aumentam e
decrementam variveis de tipo inteiro de uma unidade. Estes operadores podem
ser usados na forma prefixa ou psfixa. Na forma prefixa o operador modifica o
valor da varivel antes que o valor seja usado na expresso onde est a varivel.
Na forma psfixa o operador modifica o valor da varivel depois que o valor
usado na expresso onde est a varivel. Por exemplo, o valor das variveis x,
y e w aps a execuo do trecho de cdigo abaixo
int x = 1, y, w;
y = x++;
w = --x;
1. Isto ocorre porque y recebe o valor de x antes de ser incrementado e w
recebe o valor de x depois de ser decrementado.
O operador de negao unrio (-) usado para mudar o sinal de um valor
inteiro. O operador de Complemento de bit (~) inverte cada bit da representao
binria de um inteiro. O exemplo abaixo mostra efeito da aplicao deste
operador.
byte x = 10; // valor em binrio 00001010
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
44
x = ~x; // valor em binrio 11110101; valor em decimal 245.
O programa abaixo mostra o uso de cada operador unrio.
public class Unarios {
public static void main (String args[]) {
int x = 10, y = 0;
System.out.println("x = " + x);
System.out.println("y = " + y);
System.out.println("++x = " + ++x);
System.out.println("y++ = " + y++);
System.out.println("x = " + x);
System.out.println("y = " + y);
System.out.println("-x = " + -x);
System.out.println("~y = " + ~y);
}
}
Sada:
x = 10
y = 0
++x = 11
y++ = 0
x = 11
y = 1
-x = -11
~y = -2
Exemplo III-2. Uso dos operadores unrios.
Binrios
Descrio Smbolo
Adio e concatenao de strings +
Subtrao -
Multiplicao *
Diviso /
Mdulo %
E de bit &
OU de bit |
OU exclusivo de bit ^
deslocamento de bits a esquerda <<
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
45
deslocamento de bits a direita >>
des. a direita com preenchimento zero >>>
Tabela III-13. Operadores binrios.
Acreditamos que os operadores binrios para adio, subtrao,
multiplicao, diviso e concatenao de Strings no necessitam maiores
explicaes. O operador de mdulo (%) retorna o resto da diviso entre dois
operandos inteiros. Por exemplo, o valor da varivel x aps a execuo do trecho
de cdigo
int x = 7 % 4;
3.
Os operadores &, | e ^implementam operaes orientada para bits, ou
seja, operaes que atuam sobre os bits individuais dos operandos. So teis
quando se usa valores como campos de bits. O operador & realiza a operao
lgica E entre cada bit individual dos operandos. Por exemplo, o valor da
varivel x aps a execuo do trecho de cdigo
byte y = 3;
byte x = Y & 5;
1.
O operador | realiza a operao lgica OU entre cada bit individual dos
operandos. Por exemplo, o valor da varivel x aps a execuo do trecho de
cdigo
byte y = 3;
byte x = Y | 5;
7.
O operador ^realiza a operao lgica XOU (ou exclusivo) entre cada bit
individual dos operandos. Por exemplo, o valor da varivel x aps a execuo do
trecho de cdigo
byte y = 3;
byte x = Y & 5;
6.
y 00000011
4 00000101 &
1 00000001
y 00000011
4 00000101 |
7 00000111
y 00000011
4 00000101 ^
1 00000110
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
46
Os operadores <<, >>e >>>implementam operaes de deslocamento de
bits. Os bits do operando esquerda sero deslocados o nmero de posies
especificadas pelo operando direita. Os bits que saem dos limites do campo so
perdidos e a varivel preenchida com zeros no lado oposto ao deslocamento. O
operador << realiza a operao de deslocamento de bits a esquerda. Por
exemplo, o valor da varivel x aps a execuo do trecho de cdigo
byte x = 7 << 1;
14. Note que o deslocamento de uma unidade para a esquerda tem o mesmo
efeito da multiplicao por 2, desde que nenhum bit seja. Os operadores >>e
>>>realizam a operao de deslocamento de bits a direita. A diferena entre o
operador >>e o >>> que o primeiro no desloca o bit de mais alta ordem
usado para indicar nmeros negativos. O programa abaixo ilustra o uso desses
operadores:
public class Deslocamento {
public static void main (String args[]) {
int x = 7, y =7;
System.out.println("x = " + x);
System.out.println("y = " + y);
System.out.println("x << 1= " + (x<<1));
System.out.println("x >> 2= " + (x>>2));
System.out.println("y >> 2= " + (y>>2));
System.out.println("y >>> 31= " + (y>>>31));
}
}
Sada:
x = 7
y = -7
x <<= 14
x >> 2= 1
y >> 2= -2
y >>>30=3
Exemplo III-3. Uso dos operadores de deslocamento de bits.
Note que no caso do nmero positivo o deslocamento direita teve o
efeito de uma diviso inteira por dois. J quando o nmero negativo este efeito
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
47
no ocorre, devido ao fato da representao de nmeros inteiros ser feita em
complemento a dois.
Relacionais
Descrio Smbolo
Menor que <
Maior que >
Menor igual <=
Maior igual >=
Igual ==
Diferente !=
Tabela III-14. Operadores relacionais.
Os operadores relacionais so usados para comparar valores. O resultado
da aplicao desses operadores um valore boolano, ou seja :true ou false. O
programa abaixo ilustra o uso desses operadores:
public class Relacional {
public static void main (String args[]) {
int x = 7, y = 8;
System.out.println("x = " + x);
System.out.println("y = " + y);
System.out.println("x < y = " + (x < y));
System.out.println("x > 10 = " + (x > 10));
System.out.println("y <= 8 = " + (y <= 8));
System.out.println("y == 5 = " + (y == 5));
System.out.println("x != y = " + (x != y));
}
}
Sada:
x = 7
y = 8
x < y = true
x > 10 = false
y <= 8 = true
y == 5 = false
x != y = true
Exemplo III-4. Uso dos operadores relacionais.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
48
Booleanos
Descrio Smbolo
E &
OU |
OU Exclusivo ^
E Curto circuito &&
OU Curto circuito ||
Negao !
Igualdade ==
Condicional ?:
Tabela III-15. Operadores booleanos.
Os operadores booleanos atuam sobre valores booleanos e retornam um
valor booleano. A tabela abaixo resume o resultado da aplicao dos operadores
booleanos, exceto o operador condicional (?:) e o de negao (!):
Operando 1 Operando 2 & | ^ && || ==
true true true true false true true true
true false false true true false true false
false true false true true false true false
false false false false false false false true
Tabela III-16. Resumo dos operadores booleanos.
O operador de negao muda o valor booleano como mostrado na tabela
abaixo:
Operando !
true false
false true
Tabela III-17. Operador de negao.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
49
O operador condicional atua sobre trs operandos: uma expresso
condicional e duas outras expresses quaisquer. A forma geral do operador
<condio> ? <expresso 1> : <expresso 2>.
Se <condio> for avaliada como true, ento o resultado da aplicao
do operador condicional ser o retorno da avaliao da <expresso 1>. Caso
contrrio o resultado da avaliao da <expresso 2> ser retornado. O
programa abaixo ilustra o uso deste operador:
public class Condicional
{
public static void main (String args[])
{
int x = 5;
boolean par = (x % 2 == 0) ? true : false;
System.out.println("x = " + x);
System.out.println(" par = " + par);
}
}
Sada:
x = 5
par = false
Exemplo III-5. Uso do operador condicional.
Atribuio
Descrio Smbolo
Simples =
Adio +=
Subtrao -=
Multiplicao *=
Diviso /=
Modulo %=
AND &=
OR |=
XOR ^=
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
50
Tabela III-18. Operadores de atribuio.
Os operadores de atribuio simplesmente atribuem um valor a uma
varivel. Exceto o operador de atribuio simples (=), todos os outros operadores
na forma
<varivel> <op>= <expresso>
funcionam como uma maneira abreviada de se escrever
<varivel> = <varivel> <op>(<expresso>)
Por exemplo, a atribuio
x += 2;
tem o mesmo significado da atribuio
x = x +2;
Esta forma de escrever facilita a trabalho de digitao, porm torna o
cdigo fonte menos legvel.
Expresses e Precedncia entre Operadores
Expresses so trechos de cdigos que geram valores. Portanto, o trecho
de cdigo 1+2 uma expresso pois gera o valor 3. Literais tambm so
expresses pois geram o prprio valor que representam. Portanto, o literal 3.14
tambm uma expresso. As variveis que ocorrem em uma expresso so
tambm expresses, pois representam o valor que armazenam.
As expresses so combinadas por meio dos operadores para formar
expresses maiores. Assim, podemos combinar as expresses 3 e 5*6 por meio
de um operador tipo +para formar a expresso
3+5*6
Uma pergunta que pode surgir : como a expresso avaliada? Ou seja,
que operador aplicado primeiro: o + ou o *? Dependendo da ordem de
aplicao dos operadores o resultado da avaliao da expresso pode ser
diferente, como no caso acima. A ordem de aplicao obedece uma prioridade
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
51
definida pela precedncia relativa entre os operadores. A tabela abaixo define a
precedncia entre os operadores. A precedncia decresce de cima para baixo. Em
se tratando de operadores com a mesma precedncia a avaliao em uma
expresso feita da esquerda para a direita.
. [] ()
++ -- ! ~
* / %
+ -
<< >> >>>
< > <= >=
== !=
&
^
&&
||
?:
=
Tabela III-19. Precedncia de operadores.
Comentrios
Comentar o cdigo fonte faz parte das regras que definem um bom estilo
de programao. J ava possui trs diferentes formas de se comentar o cdigo,
ilustradas abaixo:
// comentrio de linha
/* comentrio de bloco */
/** comentrio de bloco c/ propsito de documentao */
As duas primeiras formas de comentrio so familiares para os
programadores de C++. Na primeira forma, todos os caracteres posicionados
aps // e antes do final da linha so ignorados pelo compilador. Na segunda
forma todos os caracteres que ocorrem aps /* so ignorados pelo
compilador, at que seja encontrado a sequncia */. A terceira forma de
comentrio semelhante a segunda, com a diferena de que usada pela
ferramenta de documentao javadoc para gerar uma documentao no formato
HTML (HyperText Markup Language). O uso dessa ferramenta ser tratado no
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
52
final do prximo captulo. O exemplo III-6 repete o cdigo do exemplo III-5
com a adio de alguns comentrios:
public class Condicional
{ // classe para teste do operador ?:
public static void main (String args[])
{
int x = 5; // varivel usada para o teste
/*
Ser impresso true se x for par
*/
boolean par = (x % 2 == 0) ? true : false;
System.out.println("x = " + x);
System.out.println(" par = " + par);
}
}
Exemplo III-6. Uso de comentrios.
Blocos e Escopo
Na linguagem J ava, assim como em C/C++um bloco de comandos
delimitado pelos caracteres { e }. Os blocos so utilizados para agrupar
comandos que so relacionados. Um bloco tambm pode conter blocos,
chamados de blocos internos. Todas as variveis declaradas em um bloco podem
ser referenciadas apenas dentro do bloco e nos blocos internos ao bloco onde foi
definida, desde que no exista nenhuma varivel no bloco mais interno com o
mesmo nome. As sees onde uma determinada varivel pode ser acessada
definem a escopo da varivel. A figura III-1 ilustra a relao entre blocos e
escopo.
public class Visivel {
public static void main (String args[]){
int x = 5;
int y = 2;
...
{
int x =2;
...
}
...
}
}
escopo do x interno
escopo do x externo
escopo de y
{
}
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
53
Figura III-1. Visibilidade de variveis.
Estruturas de Controle
As estruturas de controle definem a sequncia de execuo das
instrues. No possvel implementar um algoritmo que no seja trivial em
uma linguagem de programao que no tenha um conjunto mnimo de
estruturas de controle. As estruturas de controle podem ser divididas em seleo,
repetio e sequncia. A sequncia simplesmente definida pela execuo
sequencial dos comandos, de cima para baixo. Falta abordarmos as estruturas
pertencentes s outras duas classes.
Seleo
Na seleo o fluxo sequencial de execuo desviado segundo uma
condio ou valor. J ava apresenta duas formas seleo: o if e o switch.
if
O comando de seleo de if possui duas formas bsicas:
if (condio)
comando1
if (condio)
comando1
else
comando2
(a) (b)
Na forma (a) o comando1 executado se condio for avaliada como
true. Na forma (b) o comando1 executado se condio for avaliada como
true seno o comando2 executado.
if (x==0)
y = 5;
else
y+=6;
Exemplo III-7. Comando if.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
54
Se o comando a ser executado for na verdade um conjunto de comandos
devemos ento usar os delimitadores de bloco { e } para agrupar os
comandos em um nico bloco.
if (x==0)
y = 5;
else
{
y+=6;
x++;
}
Exemplo III-8. Comando if executando um bloco.
Os comandos if podem combinar em forma aninhada como mostrado no
exemplo III-9.
if (x==0)
if (y == 1)
x= y;
else
y+=6;
Exemplo III-9. ifs aninhados.
O aninhamento como no exemplo III-9 deixa uma dvida com que if o
else est relacionado? Com o mais interno ou o mais externo? A regra para
esses casos : o else se relaciona com o if mais interno. Essa regra pode ser
alterada, utilizando os delimitadores { e } para definir os blocos de
comandos, como mostrado no exemplo III-10.
if (x==0)
{
if (y == 1)
x= y;
}
else
y+=6;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
55
Exemplo III-10. Uso de blocos para definir o par if-else.
switch
O comando switch til quando existem vrias aes distintas que
precisam ser realizadas em funo do resultado da avaliao de uma expresso.
No nada que no poderia ser feito com um conjunto de if-else, no entanto o
uso do switch facilita codificao e a legibilidade do programa. A forma geral
do comando est definida abaixo:
switch(Expr)
{
case const1: com1;
...
case constN: comN;
default: comDef
}
O comando switch avalia a expresso Expr e compara o valor resultante
com todas as constantes colocadas aps a palavra a chave case. A comparao
feita na ordem de cima para baixo e a primeira constante que igualar com o valor
resultante da expresso faz com que os comandos aps o : sejam executados
at o fim ou at que seja encontrado o comando break. A palavra chave
default opcional e ela serve como ponto de entrada para os comandos que
sero executados caso o valor da expresso no seja igual a nenhuma das
constantes. O exemplo III-11 ilustra o uso do comando switch.
switch(letra)
{
case i: System.out.println(inserir);
break;
case a: System.out.println(alterar);
break;
case e: System.out.println(excluir);
break;
default:
System.out.println(
Ao ignorada: +letra);
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
56
Exemplo III-11. Uso do comando switch.
O comando break muito importante na composio do switch. Ele faz
com que a execuo sequencial dos comandos seja interrompida para ser
retomada no primeiro comando aps o comando switch. O exemplo III-12
mostra as sadas de um programa com um comando switch que no faz uso do
comando break. Note que todos os comandos so executados, uma vez que no
existe um comando break para interromper a execuo.
public class Switch {
public static void main (String args[]) {
char letra = i;
switch(letra)
{
case i: System.out.println(inserir);
case a: System.out.println(alterar);
case e: System.out.println(excluir);
default: System.out.println(
Ao ignorada: +letra);
}
}
}
Sada:
inserir
alterar
excluir
Ao ignorada:i
Exemplo III-12. Uso do comando switch sem break.
O leitor pode se estar perguntando porque a sequncia de comandos no
interrompida automaticamente em vez de deixar para o programador a tarefa
de sinalizar isso por meio do comando break. A verdade que a omisso do
comando break pode ser til para poupar digitao naqueles casos onde mais de
uma opo precisa executar a mesma sequncia de comandos. O exemplo III-13
mostra um desses casos.
switch (ms) {
case 1:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
57
case 3:
case 5:
case 7:
case 8:
case 10:
case 12: dias = 31; break;
case 4:
case 6:
case 9:
case 11: dias = 30; break;
case 2: if (((ano % 4==0) && !(ano % 100 == 0))
|| (ano % 400 == 0) )
dias = 29;
else
dias = 28;
break;
}
Exemplo III-13. Uso til da omisso do comando break.
Repetio
Os comandos de repetio, ou de iterao, executam um comando ou um
bloco de comandos vrias vezes. uma das formas para executar repetidamente
um comando. A outra a recurso que a chamada direta ou indireta de um
mtodo durante a execuo do prprio mtodo. Em J ava existem trs formas de
comandos de repetio: o while; o do-while; e o for.
while
A forma geral do comando while :
while(condio)
Comando;
O comando while executa Comando enquanto condio for avaliada
como true. Portanto, para encerrar a iterao necessrio que exista a
possibilidade da execuo de Comando alterar a avaliao de condio. A
condio testada antes da execuo do comando. O exemplo III-14 mostra a
soma dos 100 primeiros nmeros inteiros.
int i = 1;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
58
int x = 0;
while(i<=100)
x +=i++;
Exemplo III-14. Soma dos 100 primeiros nmeros inteiros.
Se for necessrio executar mais de um comando deve-se agrup-los por
meio de delimitadores de bloco, como mostrado no exemplo III-15.
while(i<=100)
{
x *=y;
i++;
}
Exemplo III-15. - Uso de while com bloco.
do-while
A forma geral do comando do-while :
do
Comando;
while(condio)
O comando do-while executa Comando enquanto condio for
avaliada como true. A diferena em relao ao comando while que a
condio testada aps a execuo do comando. O exemplo III-16 mostra a
soma dos 100 primeiros nmeros inteiros. Os comandos tambm podem ser
agrupados em um bloco.
int i = 1;
int x = 0;
do
x +=i++;
while(i<100);
Exemplo III-16. Soma dos 100 primeiros nmeros inteiros com do-while.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
59
for
A forma geral do comando for :
for(Cod.Inicializao;condio; Cod.passo)
Comando;
No comando for o Cod.Inicializao (cdigo de inicializao)
executado uma vez, a condio avaliada antes de cada iterao e o
Comando e o Cod.passo executado a cada iterao. O Cod.passo
executado aps o Comando. Todas as sees do comando for podem ser
omitidas. Enquanto condio for avaliada como true executada mais uma
iterao. Em geral, o Cod.Inicializao utilizado para inicializar a
varivel que ser testada na condio e o Cod.passo utilizado para alterar
o valor da mesma. O exemplo III-17 mostra a soma dos 100 primeiros nmeros
inteiros.
x = 0;
for(int i=1; i<=100; i++)
x +=i;
Exemplo III-17. Soma dos 100 primeiros nmeros inteiros com for.
Tanto o Cod.Inicializao como o Cod.passo podem ser
compostos de vrios comandos. Cada comando separado por ,. O exemplo
III-18 ilustra esta forma de uso do comando for.
for(int i=1, x = 0; i<=100; i++)
x +=i;
Exemplo III-18. Soma dos 100 primeiros nmeros inteiros com for.
Como j foi dito, todas as sees do comando for podem ser omitidas. O
exemplo III-19 mostra uma iterao infinita, definida pela omisso das sees do
comando for.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
60
for(;;)
System.out.println(ola mundo);
Exemplo III-19. Iterao infinita.
break e continue
J vimos o uso do comando break quando discutimos o comando
switch. Ele servia para interromper a sequncia de execuo dos comando e sair
do comando switch. Isto no acontece apenas no comando switch. Toda vez
que um break encontrado, o fluxo de execuo salta para fora do bloco onde
est contido o break, sendo retomado no comando aps o bloco. A figura III-2
ilustra este comportamento.
for (;;)
{
...
break;
...
} fluxo retomado aqui
...
Figura III-2. Uso do comando break.
O uso mais comum do comando break ocorre em uma condio de teste
dentro de uma iterao. O exemplo III-20 equivalente ao exemplo III-18.
for(int i=1, x = 0;; i++)
if (i==101) break;
else x +=i;
Exemplo III-20. Soma dos 100 primeiros nmeros inteiros com for e break.
J o comando continue usado dentro de uma iterao e faz com que
ocorra um desvio para a condio de teste da iterao. Ou seja, o comando
continue fora um salto para prxima iterao. A figura III-3 ilustra este
comportamento.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
61
while (Condio)
{
... fluxo retomado aqui
continue;
...
}
...
Figura III-3. Uso do comando continue.
Como no comando break, o uso mais comum do comando continue
em uma condio de teste dentro de uma iterao.
Argumentos da linha de comando
Os argumentos digitados na linha de comando so passados para o
mtodo main() da classe invocada por meio de um vetor de Strings. Por
exemplo, se executarmos a linha de comando abaixo
java teste um dois trs
o mtodo main() da classe teste receber o seguinte vetor de Strings:
[0] um
[1] dois
[2] trs
Figura III-4. Vetor com os argumentos da linha de comando.
Para quem est acostumado a programar na linguagem C note o primeiro
elemento do vetor no o nome do programa e sim o primeiro argumento da
linha de comando. O espao serve como separador de argumentos. Se
desejarmos tratar uma cadeia de caracteres com espao como um nico
argumento necessrio delimit-la com aspas duplas. Por exemplo, o comando
abaixo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
62
java teste um dois trs
resulta no seguinte vetor:
[0] um
[1] dois trs
Figura III-5. Vetor com os argumentos da linha de comando com aspas.
O classe do exemplo III-21 mostra um programa que imprime os
argumentos recebidos, um em cada linha do dispositivo de sada.
public class ImpLinha
{
public static void main(String args[])
{
int i;
for (i=0;i<args.length;i++)
System.out.println(args[i]);
}
}
Exemplo III-21. Imprimindo a linha de comando.
Todos os argumentos so tratados como Strings. Se houver necessidade
de tratar os argumentos como pertencendo a um tipo diferente ser preciso
realizar as converses necessrias. No exemplo III-22 os argumentos so
convertidos para nmeros inteiros para serem somados.
public class Soma
{
public static void main(String a[]){
int i,soma=0;
for (i=0;i<a.length;i++)
soma += Integer.parseInt(a[i]);
System.out.println(A soma :+soma);
}
}
Exemplo III-22. Imprimindo a soma dos nmeros.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
63
Assert (Assertivas)
Com o surgimento da verso 1.4 do SDK uma nova alterao na
linguagem J ava foi introduzida, envolvendo a incluso de uma nova palavra
reservada: a palavra assert. O objetivo desta alterao incluir na linguagem
recursos que permitam que o programador verifique se uma dada condio,
chamada de assertiva, verdadeira em um local especfico do cdigo. Isto
possibilita o desenvolvimento de cdigos mais confiveis, sendo um recurso
utilizado durante a etapa de desenvolvimento e desabilitado em tempo de
execuo.
Devido a incluso de uma nova palavra chave, cdigos fontes
preexistentes que incluam a palavra assert como identificador geraro erro de
compilao ao serem compilados com a verso 1.4 do SDK. Este problema de
compatibilidade solucionado por meio de flags de compilao.
A linguagem C++possui recurso semelhante, com a diferena de ser
implementado por meio de biblioteca e no a nvel de linguagem. No caso de
J ava, a deciso de no utilizar uma biblioteca para implementao deste recurso
deveu-se ao objetivo de se buscar uma implementao mais transparente, apesar
do inconveniente da perda de compatibilidade.
A incluso de recursos de para verificao de condies estava presente
na especificao original da linguagem, quando ainda era denominada oak, mais
foi retirada da primeira verso por se acreditar que no haveria tempo para se
desenvolver uma implementao adequada.
Sintaxe e semntica
A formato geral de uma assertiva :
assert<expresso booleana1>;
ou
assert<expresso booleana1>:<expresso booleana2>;
A avaliao de uma assertiva funciona da seguinte forma: a primeira
expresso avaliada. Caso o resultado seja false e no exista uma segunda
expresso ento a exceo AssertionError lanada. Caso o resultado seja
false e exista uma segunda expresso ento ela avaliada e o resultado
passado para o construtor da exceo AssertionError antes de ser lanada.
Caso o resultado seja da primeira expresso seja true ento a segunda expresso,
caso exista, no ser avaliada.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
64
O exemplo III-23 mostra um exemplo do uso de assertivas para garantir
que uma determinada condio seja verdadeira.
...
assert b > 0;
int x = a/b;
...
Exemplo III-23. Uso de assertivas.
Habilitando e Desabilitando Assertivas
As assertivas podem ser habilitadas/desabilitadas por flags na linha de
comando e chamadas a mtodos durante a execuo. A habilitao/desabilitao
pode ter uma atuao que varia desde o envolvimento de uma nica classe at
um pacote ou todo o programa. Por default as assertivas esto desabilitadas.
Habilitao por flags
A forma geral para a habilitao de assertivas :
java [-enableassertions | -ea] [:<nome package>... |
:<nome classe>]
O flag sem argumento habilita as assertivas para todas as classes. Se for
seguindo por o nome de um pacote seguido por ... as assertivas sero
habilitadas para o pacote especificado e todos os subpacotes. Se for seguido
apenas de ...as assertivas sero habilitadas para o pacote do diretrio corrente e
todos os subpacotes. Se o argumento no terminar com ..., ento as assertivas
sero habilitadas apenas para a classe especificada. Abaixo segue um exemplo
de habilitao de assertivas:
java ea:br.ufv.dpi.apo... Teste
A desabilitao de assertivas segue a mesma lgica, mudando apenas o
flag que passa ser disableassertions ou da.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
65
Habilitao por mtodos
Os seguintes mtodos da classe ClassLoader podem ser invocados para
habilitar/desabilitar as assertivas em tempo de execuo:
void setDefaultAssertionStatus(boolean status) habilita/desabilita por
default as assertivas.
void setPackageAssertionStatus(String nomepack, boolean status)
habilita/desabilita as assertivas no pacote e subpacotes.
void setClassAssertionStatus(String nomeclasse, boolean status)
habilita/desabilita as assertivas na classe.
void clearAssertionStatus() retorna ao default.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
66
Captulo IV Classes, Pac kages e
Interfaces
A unidade fundamental de programao em J ava a Classe. No
possvel fazer um programa em J ava que no tenha pelo menos uma classe. Isso
no verdade para todas as linguagens Orientadas a Objeto. Em C++, por
exemplo, possvel fazer um programa que no use classe. Em J ava todas as
variveis e mtodos de um programa J ava devem ser definidos dentro de uma
classe. Um programa que no contenha classes no um programa orientado a
objetos. No entanto, o fato de um programa conter classes tambm no o torna
merecedor do ttulo de orientado a objetos. A programao orientada a objetos
mais um estilo de programao do que um conjunto de palavras-chave
colocadas em um programa. Porm, obviamente melhor implementar este
estilo usando uma linguagem que oferece suporte a ele. Neste captulo
estudaremos o suporte oferecido por J ava a este estilo de programao. No s a
implementao de classes ser vista, como tambm conceitos relacionados,
como pacotes e interfaces.
Classes
No Captulo II foram discutidas Classes e Objetos do ponto de vista de
modelagem e de implementao. Nesta seo ser detalhada a implementao de
classes em J ava. A definio de uma classe em J ava obedece a seguinte forma
geral:
[public] class <Identificador>
{
<corpo da classe>
}
A palavra reservada public opcional e indica que a classe pode ser
referenciada por qualquer outra classe alm do prprio pacote (conceito que ser
visto mais adiante). Apenas uma classe por arquivo pode ser precedida pela
palavra reservada public e o nome do arquivo tem que ser idntico ao nome
desta classe. Se a declarao da classe no for precedida de public, ento ela s
poder ser referenciada por outras classes do mesmo pacote. Os modificadores
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
67
de acesso private e protected no podem ser aplicados s classes. O
<Identificador> usado para referenciar a classe. No <corpo da classe>
so definidos os atributos e mtodos da classe. Na comunidade de
programadores J ava existe a conveno de associar s classes identificadores
que iniciem com letra maiscula, enquanto que os identificadores de variveis e
mtodos devem iniciar com letra minscula. No exemplo IV-1 mostrada a
definio da classe de uma classe com o identificador Pessoa. Nele foi definido
um construtor para atribuir valores aos atributos e definido os mtodos para
acesso aos atributos. Note que os mtodos que atribuem valores s variveis da
classe iniciam com a palavra set e os mtodos que retornam os valores
armazenados nas variveis da classe iniciam com a palavra get. Este padro de
nomeao de mtodo foi adotado a partir da verso 1.1 da linguagem e muito
importante segu-lo, principalmente se pretendemos implementar J avaBeans,
como ser visto no Captulo X.
public class Pessoa
{
String nome;
String telefone;
String endereo;
public Pessoa(String n, String t, String e)
{
nome = n; telefone = t; endereo = e;
}
public void setNome(String n) { nome=n; }
public void setTelefone(String t) { telefone = t; }
public void setEndereo(String e) { endereo = e; }
public String getNome() { return nome; }
public String getTelefone() { return telefone; }
public String getEndereo() { return endereo; }
}
Exemplo IV-1. Definio da classe Pessoa.
Unidade de Compilao
Cada arquivo fonte J ava uma unidade de compilao. Ao compilar o arquivo fonte o
compilador ir gerar um arquivo .class para cada classe constante no arquivo. O nome de
cada arquivo ser o nome da cada classe.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
68
Os atributos ou variveis declarados na classe so criados somente
quando os objetos so criados. Ou seja, cada objeto da classe Pessoa ter a sua
varivel nome, telefone e endereo. Portanto, a varivel pertence instncia
da classe e no classe. Variveis que pertencem ao objeto so chamadas
variveis de instncia. Com os mtodos o raciocnio o mesmo, ou seja, para
podermos usar o mtodo getNome() preciso criar um objeto da classe Pessoa
e usar o mtodo getNome() deste objeto. Mtodos que pertencem ao objeto so
chamados de mtodos de instncia. Como veremos mais adiante, podemos usar a
palavra reservada static para declarar variveis e mtodos que pertencem
classe (mtodos e variveis de classe).
Os mtodos definem operaes sobre os atributos. Eles possuem a forma
geral:
<modificador> <tipo> <identificador>(<parmetros>)
{
<corpo do mtodo>
}
onde <modificador> um modificador de acesso, <tipo> o tipo do valor de
retorno do mtodo, <identificador> o identificador do mtodo e
<parmetros> uma lista de parmetros. O corpo do mtodo composto de
comandos, expresses e declaraes de variveis locais ao mtodo. Os mtodos
do exemplo IV.1 so muito simples. Eles apenas retornam um valor ou atribuem
um valor aos atributos do objeto.
Construtores
Podemos observar no exemplo IV-1 que existe um mtodo pblico com o
mesmo nome da classe e que no define um valor de retorno. Mtodos como
esse so denominados de construtores e so chamados pelo operador new. Uma
classe pode no ter construtor ou ter vrios, desde que tenham diferentes tipos de
argumentos. O interpretador decidir qual chamar a partir dos argumentos
passados para o construtor. Se o programador no declarar nenhum construtor
ento o compilador ir criar automaticamente um construtor default para a
classe.
Valor de Retorno
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
69
Com exceo dos construtores todos os outros mtodos precisam retornar
algum valor. Se programador no precisa que o mtodo retorne algum valor,
ento ele deve especificar que o mtodo ir retornar o valor void que o valor
vazio. Se o mtodo no foi definido com valor de retorno void e no um
construtor ento preciso que no corpo do mtodo seja indicado o valor de
retorno. Esta indicao deve ser feita em toda ramificao de cdigo que leve ao
fim da execuo do mtodo e feita com a palavra chave return seguida de
uma expresso:
return <expresso>
A expresso pode ser uma varivel, um literal ou qualquer outra
expresso que gere um valor do tipo especificado para o retorno da funo. O
exemplo IV-2 mostra um mtodo que retorna um inteiro. Note que toda
ramificao de cdigo que leve ao fim da execuo do mtodo necessita de um
comando return.
public class ExemploIV2
{
...
public int calc(int a)
{
if (a==0) return 1;
else return a*a;
}
}
Exemplo IV-2. Mtodo que retorna um inteiro.
Objetos
Para se criar um objeto de uma classe (ou uma instncia da classe)
preciso primeiro declarar uma varivel que ir referenciar o objeto, para depois
criar o objeto. A declarao de um referncia a um objeto feita obedecendo a
seguinte forma geral:
<nome da classe> <identificador>;
Por exemplo, para declarar uma referncia um objeto da classe Pessoa
devemos adicionar a seguinte linha ao cdigo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
70
Pessoa p1;
Pode-se declarar mais de uma referncia a objetos de uma classe em uma
nica declarao, separando os identificadores por vrgula.
Pessoa p1, p2;
Para criar um objeto usa-se o operador new conforme a forma geral
abaixo:
<identificador> = <nome da classe>(<argumentos>);
onde <argumentos> uma lista de argumentos que sero passados para um
mtodo especial da classe, denominado de construtor. Por exemplo, para criar
um objeto do tipo Pessoa podemos usar a declarao abaixo:
P1 = new Pessoa(Ana,432-6969,Rua 17 134);
Podemos tambm combinar a declarao da referncia com a criao do
objeto em uma nica linha de cdigo.
Pessoa P1 = new Pessoa(Ana,432-6969,Rua 17 134);
Uma vez criado o objeto podemos acessar os elementos do objeto por
meio da referncia ao objeto e do operador .. Por exemplo para acessar o
mtodo getNome() do objeto referenciado pela varivel P1 devemos usar o
seguinte cdigo:
P1.getNome();
Para acessar um atributo diretamente a sintaxe mesma. Por exemplo,
para acessar o atributo nome diretamente basta usar a seguinte linha de cdigo.
P1.nome;
O exemplo IV-3 mostra a criao de um objeto do tipo Pessoa e o acesso
a seus membros. Para que a classe seja executvel diretamente pela mquina
virtual preciso que ela possua um mtodo main() que servir como ponto de
entrada para a execuo. Podemos ento, inserir cdigo no mtodo main() para
criar uma instncia da classe para que, a partir de ento, possamos a acessar os
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
71
membros do objeto. O mtodo main() existe antes da criao da instncia, e
portanto pode ser acessado pela mquina virtual, porque foi declarado com o
modificador static. Isto significa que o mtodo pertence classe (mtodo de
classe) e no ao objeto (mtodo de instncia).
public class Pessoa
{
...
// igual ao exemplo IV.1
...
public static void main(String args[])
{
Pessoa p;
p = new Pessoa(Ana,432-6969,Rua 17 134);
// Acessa os dados via mtodos
System.out.println(Nome:+getNome());
System.out.println(Telefone:+ getTelefone());
System.out.println(Endereo:+ getEndereo());
// Altera o endereo
setEndereo(Rua 17 138)
// Acessa os atributos diretamente
System.out.println(Endereo:+ endereo);
}
}
Exemplo IV-3. Definio da classe Pessoa.
As implementaes da classe Pessoa mostradas nos exemplos IV-1 e
IV-3 possuem alguns problemas que iremos abordar gradativamente. O primeiro
problema est relacionado com o acesso direto aos atributos. Em um programa
bem projetado o acesso aos atributos da classe a partir de mtodos definidos em
outras classe restringido de modo a diminuir a dependncia em relao
representao interna de uma classe. Quanto maior for esta independncia maior
a facilidade para manuteno do programa. Para se restringir o acesso aos
membros da classe deve-se preceder a declarao dos membros com palavras
reservadas denominadas de modificadores de acesso que sero descritos a seguir.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
72
Modificadores de acesso
Os modificadores de acesso tem por objetivo definir a visibilidade de um
membro de uma classe (atributo ou mtodo) em relao outras classes. A
tabela IV-1 mostra os modificadores de acesso disponveis em J ava.
Modificador Descrio
default
Somente classes do mesmo package possuem acesso
public
Todos possuem acesso
protected
Apenas os membros da classe e subclasse
private
Apenas os membros da classe
Tabela IV-1. Modificadores de acesso.
Quando no especificado nenhum modificador de acesso assumido o
modificador default, tambm chamado de friend. Ou seja, no existe uma
palavra reservada default. O acesso default determina que todas as classes
dentro do mesmo package (pacote) podem acessar os membros da classe
corrente. O conceito de package ser detalhado mais adiante, no entanto
podemos adiantar que um package um agrupamento de classes e interface
(tambm ser vista mais adiante). Toda classe e interface pertence a um
package, mesmo que o programador no indique o package explicitamente. Se o
programador no indicar o package ento ser assumido que a classe ou
interface pertence ao package default.
O modificador public determina que todas as classes podem acessar o
membro. J o modificador protected limita o acesso ao membro apenas aos
membros da prpria classe e aos membros das subclasses da classe. Finalmente,
o modificador private limita o acesso ao membro apenas aos membros da
prpria classe.
O exemplo IV-4 uma redefinio da classe Pessoa, explicitando os
modificadores de acesso dos atributos com objetivo de limitar a visibilidade dos
mesmos.
public class Pessoa
{
protected String nome;
protected String telefone;
protected String endereo;
...
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
73
// igual ao exemplo IV.1
...
}
Exemplo IV-4. Definio da classe Pessoa com os atributos protegidos.
O modificador de acesso usado para os atributos no exemplo IV-4 foi o
protected. Portanto, se for criada uma subclasse da classe Pessoa, esta poder
acessar diretamente os atributos da classe Pessoa. O exemplo IV-5 mostra a
definio da classe Funcionario como subclasse de Pessoa. Note que o
atributo de instncia salario da classe Funcionario definido com o
modificador de acesso private, impedindo, dessa forma, acessos diretos ao
atributo a no ser por membros da prpria classe. Note tambm que o construtor
da classe Funcionario possui uma chamada a um mtodo super. Esta chamada
representa, na verdade, uma chamada ao construtor da superclasse. Isto ser
visto com maiores detalhes mais adiante.
public class Funcionario extends Pessoa
{
private double salario;
public Funcionario(String n, String t, String e, double s)
{
super(n,t,e);
salario = s;
}
public void setSalario(double s) { salario = s; }
public double getSalario() { return salario; }
}
Exemplo IV-5. Definio da classe Funcionario.
Para utilizar a classe Funcionario pode-se criar uma terceira classe,
como mostra o exemplo IV-6, com o um mtodo main() que serve de ponto de
entrada para o incio da execuo. Foi colocado propositadamente uma tentativa
de acesso ao atributo privado por um mtodo externo classe do atributo, de
modo a ilustrar um acesso no permitido.
public class TesteFun
{
public static void main(String a[])
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
74
Funcionario f;
f = new Funcionario(Carlos,555-7777,
Av Nova 32,3000.0);
System.out.println(Nome:+f.getNome());
// Acesso Ilegal. Use o mtodo.
System.out.println(Salario:+f.salario);
}
}
Exemplo IV-6. Utilizando a classe Funcionario.
Outros Modificadores
Alm dos modificadores de acesso existem outros modificadores que
estabelecem significados distintos da visibilidade. A tabela IV-2 exibe os
modificadores adicionais.
Modificador Descrio
static
A varivel ou mtodo comum a todas as instncias da
classe.
final
O valor da varivel no pode ser modificado.
synchronized
atribui o monitor do objeto ao thread corrente.
native
indica que se trata de um mtodo nativos.
Tabela IV.2 Modificadores de adicionais.
O modificador static
Um atributo declarado com o modificador static significa que um
atributo da classe e no de instncia. Em outras palavras, existir apenas um
atributo, ocupando uma nica posio de memria, em vez de um atributo para
cada instncia, cada um com sua prpria posio de memria. Como resultado, o
atributo existir antes mesmo que qualquer objeto seja criado e, se for pblico,
poder ser acessado prefixando-o com o nome da classe e o operador .. O
exemplo V-7 mostra uma classe com um atributo static. Note que o no
preciso declarar uma instncia da classe X para que o atributo exista e para
acess-lo basta prefix-lo como nome da classe.
class X
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
75
static public int tot =0;
}
public class Main
{
public static void main(String a[])
{
X.tot = 2;
System.out.println(Valor de tot:+X.tot);
}
}
Exemplo IV-7. Classe com atributo static.
Outro efeito que o atributo ser compartilhado por todas as instncias
da classe. Desta forma, se um objeto alterar o contedo do atributo, a alterao
afetar todos os outros objetos da classe. O exemplo V-8 mostra a declarao de
dois objetos da classe X. Um dos objetos altera o valor do atributo static e o
outro imprime o valor do atributo. Isto mostra que as alteraes feitas por um
objeto no atributo percebida por todos os outros objetos da classe.
class X
{
static public int tot =0;
public void inc() {tot++;}
}
public class Main
{
public static void main(String a[])
{
X x1, x2;
x1 = new X();
x2 = new X();
// x1 modifica o valor
x1.inc();
System.out.println(Valor de tot:+x2.tot);
}
}
Sada:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
76
Valor de tot:1
Exemplo IV-8. Objetos com atributo static.
O modificador static tambm pode ser usado na declarao de
mtodos. Neste caso o mtodo fica ligado classe e no instncia, sendo
denominado de mtodo de classe. Como consequncia o mtodo pode ser
acessado antes de existir um objeto da classe. Vrios exemplos mostrados neste
livro tem pelo menos um mtodo static: o mtodo main(). Ele serve como
ponto de entrada para a execuo da aplicao J ava, uma vez que inicialmente
no existem objetos. Os mtodos static no podem acessar atributos e outros
mtodos no estticos da classe, a no ser que exista uma declarao de um
objeto da classe no corpo do mtodo. Os mtodos estticos so muito usados em
classes utilitrias. Classes utilitrias so classes que servem para agrupar
mtodos que prestam algum tipo de servio a outras classes. Por exemplo, o
mtodo exit() um mtodo esttico da classe System. Ele serve para encerrar
a execuo da mquina virtual corrente. Sendo um mtodo esttico no preciso
criar um objeto da classe System para acess-lo. A classe System uma classe
utilitria, contendo vrios mtodos e atributos estticos teis para outras classes.
O Modificador final
O modificador final pode ser usado em atributos, mtodos e classes. O
modificador final impede se modifique o que est sendo prefixado. Um atributo
prefixado com final indica que uma vez definido seu valor ele no ser
alterado. Ou seja, uma constante. A definio do valor do atributo pode ser
feito tanto na declarao como durante a execuo do programa, sendo que esta
ltima possibilidade no era permitida na verso 1.0 da linguagem J ava. O
exemplo IV-9 mostra o uso do modificador final em atributos.
class X
{
public int k =0;
}
public class Main1
{
public final int i = 1;
public final int j;
public final X x = new X();
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
77
public Main1(){j = 2;}
public static void main(String a[])
{
Main1 m = new Main1();
m.x.k= 3;
// Erro : o atriuto no pode ser modificado
// m.j = 4;
System.out.println("Valor de k:"+ m.x.k);
System.out.println("Valor de j:"+ m.j);
System.out.println("Valor de i:"+ m.i);
}
}
Exemplo IV-9. Uso do modificador final em atributos.
Note que no exemplo IV-9 o atributo j inicializado no construtor e no
na declarao. No exemplo o atributo k do objeto referenciado pelo atributo x
modificado, mesmo sendo x um atributo final. Isto ocorre porque x uma
referencia a um objeto e no o prprio objeto, portanto, no caso de referencias a
objeto, o modificador final implica que o atributo no pode referenciar outro
objeto, mas no significa que o objeto referenciado no possa ser modificado.
Um mtodo declarado com o modificador com final no pode ser
sobrescrito em uma subclasse. Alguns compiladores podem aproveitar isso e
verificar se possvel definir as chamadas a esses mtodos como inline. Nas
chamadas inline o compilador substitui a chamada ao mtodo pelo o cdigo do
mtodo, tornando mais eficiente a execuo do programa. O exemplo IV-10
mostra o uso do modificador final em um mtodo.
class X
{
public int k =0;
public final void mostra()
{
System.out.println("Valor de k:"+ k);
}
}
class SX extends X
{
// Erro: Sobrescrita ilegal
public void mostra()
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
78
System.out.println("k:"+ k);
}
}
Exemplo IV-10. Uso do modificador final em mtodos.
Uma classe declarada com o modificador com final impede que sejam
criadas subclasses desta classe. O programador pode decidir fazer isso por
razes de projeto ou de segurana, j que neste caso ele ter certeza que a
funcionalidade da classe no ser alterada. Outra razo pode ser eficincia, uma
vez que os mtodos de uma classe final tambm so final, e portanto podem
ser otimizados para serem tratados como inline.
Os Modificadores synchronized e native
O modificador synchronized para controlar o acesso a reas crticas
no processamento concorrente em J ava. usado em mtodos e blocos de
comandos, e seu uso ser discutido em detalhes no Captulo XI.
O modificador native usado em mtodos para indicar que o mtodo
foi implementado em outra linguagem de programao. O programador deve
apenas indicar a assinatura do mtodo, como mostrado abaixo:
native int meuMetodo(int a);
O uso de chamadas nativas restringe a portabilidade do programa. No
momento a linguagem J ava s suporta chamadas nativas implementadas na
linguagem C/C++.
Referncias Compartilhadas
Um outro problema das implementaes da classe Pessoa mostradas nos
exemplos IV-1 e IV-3 est relacionado com o compartilhamento de referncias.
No construtor, assim como nos mtodos setXXX, o argumento atribudo
diretamente s variveis de instncia. Como toda varivel de objeto em J ava na
verdade uma referncia para o objeto ento as variveis de instncia da classe
Pessoa e os argumentos do construtor e dos mtodos setXXX so referncias a
objetos do tipo String. Portanto, ao atribuir diretamente o argumento s
variveis de instncia geramos um compartilhamento de referncias. Essa
situao melhor ilustrada graficamente, como pode ser visto na figura IV-1,
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
79
onde mostrado o compartilhamento entre o argumento n e a varivel de
instncia nome aps a atribuio.
O problema do compartilhamento de referncias, que ele permite
acesso aos objetos referenciados internamente pelos objetos. Com isso possvel
modificar, com mtodos externos ao objeto, o objeto referenciado. No entanto,
no caso particular dos objetos da classe String, isso no chega a ser um
problema. Strings so constantes, ou seja, seus valores no podem ser alterados
aps a sua criao e, portanto, objetos Strings podem ser compartilhados sem
riscos. Toda alterao em um objeto do tipo String retorna um novo objeto
String, deixando a original inalterada.
Antes da atribuio
n
nome null
Aps a atribuio
n
nome
Figura IV-1.Compartilhamento de referencias.
Se o programador desejar alterar o valor de uma cadeia de caracteres sem
criar um novo objeto, ento ele deve optar por utilizar a classe StringBuffer
que implementa uma sequncia mutvel de caracteres. No entanto, preciso
estar alerta para o problema de compartilhamento de referncias. O trecho de
cdigo do exemplo IV-11 mostra uma ocorrncia de compartilhamento de
referncia. No exemplo a classe Pessoa definida usando a classe
StringBuffer para armazenar as sequncias de caracteres. Os objetos da classe
X possuem uma referncia a um objeto do tipo Pessoa. Na construo do objeto
Pessoa so passados como parmetros as referncias dos objetos StringBuffer
do objeto da classe X, gerando um compartilhamento de referencias. Quando
invocado o mtodo m1() do objeto da classe X, este concatena a sequncia fim
ao StringBuffer referenciado por n. Como n compartilha o mesmo objeto com
a varivel de instncia nome do objeto Pessoa, ento a alterao tambm afeta o
objeto Pessoa, ocasionando um efeito colateral, provavelmente indesejvel.
Objeto
Objeto
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
80
Para se evitar esta situao necessrio que o objeto crie uma cpia do
objeto que est recebendo e retorne uma cpia do objeto que referencia. No caso
de objetos do tipo StringBuffer basta construir um novo objeto, passando
como parmetro a String correspondente ao StringBuffer anterior, como
mostrado abaixo:
nome = new StringBuffer(n.toString());
No entanto, no caso de objetos mais complexos mais complicado criar
uma cpia por meio do construtor. Neste caso necessrio criar uma cpia
usando o mtodo clone(). Este mtodo ser visto na prxima seo.
class Pessoa
{
StringBuffer nome;
StringBuffer telefone;
StringBuffer endereo;
public Pessoa(StringBuffer n, StringBuffer t,
StringBuffer e)
{
nome = n; telefone = t; endereo = e;
}
// O restante da da classe semelhante ao exemplo VI.1
// ...
}
public class X
{
StringBuffer n = new StringBuffer("Pedro");
StringBuffer t = new StringBuffer("324-6789");
StringBuffer e = new StringBuffer("Rua 17/148 Natal");
Pessoa p;
public X() {p = new Pessoa(n,t,e);}
public void m1() { n.append("fim");}
public static void main(String a[])
{
X x = new X();
x.m1();
System.out.println(x.p.nome);
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
81
Exemplo IV-11. Exemplo de compartilhamento de referncia.
Copiando Objetos
Como visto na seo anterior, a atribuio envolvendo duas referencias a
objetos acarreta um compartilhamento do objeto e no uma cpia do objeto
original. No entanto, em algumas situaes no queremos compartilhar um
objeto e sim criar uma cpia de um objeto que j existe, ou seja um clone.
Existem dois tipos de modos de se clonar um objeto:
1- Cpia rasa (shallow copy) - neste caso os atributos do objeto resultante
recebem os valores dos atributos correspondentes no objeto original. Os
objetos referenciados pelo objeto original sero compartilhados pelo
objeto resultante. A figura IV-2 ilustra este tipo de cpia. Note o
compartilhamento das referencias.
Figura IV-2.Cpia rasa entre os objetos A e D.
2- Cpia profunda (deep copy) - neste caso no s o objeto original
copiado como tambm todos os objetos por ele referenciados. Este tipo
de cpia pode ser bastante ineficiente. A figura IV-3 ilustra este tipo de
cpia.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
82
Figura IV-3.Cpia profunda entre os objetos A e D.
J ava oferece suporte para a cpia rasa. Para que a classe esteja apta a ser
clonada preciso que ela implemente a interface Cloneable (interfaces sero
discutidas mais adiante).
O objeto this
Em algumas situaes necessrio referenciar o prprio objeto corrente.
Por essa razo todo objeto possui uma varivel especial identificada por this
que contm uma referncia para o prprio objeto. O exemplo IV.xx mostra um
uso tpico do atributo this. Ele mostra um mtodo cujo parmetro formal possui
o mesmo nome de um atributo de instncia. Para distingu-los necessrio
qualificar o atributo da instncia com o atributo this.
public class objetoGeo
{
protected Color cor;
protected int x, y;
public objetoGeo(Color cor, int x, int y)
{
this.cor = cor; this.x=x; this.y = y;
}
public Color retCor() {return cor};
}
Exemplo IV-12. Exemplo de uso do atributo this.
Outro uso tpico e quando queremos passar a instncia corrente como
argumento de um mtodo. Como mostra o exemplo IV.xx.
class X
{
...
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
83
public void mx(Y y)
{
...;
}
}
class Y
{
X x;
public void my()
{
x.mx(this);
...
}
}
Exemplo IV-13. Exemplo de uso do atributo this como argumento.
No exemplo IV.xx o objeto da classe Y passa ele prprio como
argumento do mtodo mx() do objeto da classe X.
Packages
Pacotes (Packages) a soluo proposta por J ava para agrupar Classes e
Interfaces relacionadas para compor bibliotecas. As Interfaces sero vistas mais
adiante. Organizando as classes em pacotes evita a coliso entre os nomes das
classes. No caso dos mtodos isso no necessrio, pois mtodos como o
mesmo nome em classes diferentes so facilmente distinguidos uma vez que so
qualificados pelos objetos das classes. No entanto como distinguir classes com o
mesmo nome? Esse problema muito comum, principalmente quando se
trabalha em equipe. Como impedir que um programador trabalhando no mesmo
projeto crie uma classe com o mesmo nome que outra criada por outro
programador? Na hora de unir as classes os sistema no ir compilar devido ao
problema de redeclarao de classes. Sendo J ava uma linguagem para atuar na
Internet o problema ainda mais grave: como impedir que uma classe que foi
baixada de outra mquina no possua o mesmo nome de uma classe. Para
contornar todos estes problemas foi criado os Pacotes.
Usando Packages
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
84
Toda classe pertence a um pacote. No caso de o programador no indicar
a que pacote pertence a classe, o compilador ir assumir que a classe pertence ao
pacote default. Para se usar uma classe definida em outro package preciso usar
a palavra chave import seguida do nome da classe qualificada pelo nome do
pacote como mostra a forma geral abaixo:
import nome_Package.nomeClasse;
Por exemplo para importar a classe Color do pacote java.awt o
programador dever usar a diretiva abaixo:
import java.awt.Color;
Se o programador quiser importar todas as classes do pacote java.awt
basta usar o caractere *` no lugar do nome da classe:
import java.awt.*;
possvel usar uma classe declarada em outro pacote sem usar a palavra
chave import. Nesse caso necessrio qualificar o nome da classe com o
nome do pacote toda vez que a classe for referenciada. Por exemplo, no caso da
classe Color seria necessrio qualific-la da seguinte forma:
java.awt.Color
Existem dois pacotes que no precisam ser importados para que possam
ser usadas as suas classes sem a qualificao: o pacote default e o pacote
java.lang. O pacote default agrupa todas a classes que esto no diretrio
corrente e o pacote java.lang agrupa as classes do ncleo bsico da
linguagem.
Criando Packages
Para incluir uma unidade compilao em um pacote basta que o
programador inclua a seguinte declarao no arquivo.
package nomepacote;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
85
Importante: a declarao acima precisa ser a primeira declarao no
arquivo.
O nome do pacote pode ser composto por vrios nomes separados pelo
caractere ., como no caso do pacote java.awt.
As classes de um determinado pacote devem ser colocadas em um
diretrio obedecendo a mesma estrutura do nome do pacote, a partir de algum
diretrio constando na varivel de ambiente classpath. A varivel de
ambiente classpath indica os diretrios que servem como pontos de entrada
para procura de classes pela mquina virtual.
Por exemplo, suponha que eu resolva colocar as classes sobre objetos
geomtricos em um determinado pacote, digamos br.com.alcione.geo.
Para indicar que unidade de compilao pertence a esse pacote devemos colocar
a diretiva adequada no incio do arquivo fonte, como mostrado no exemplo
IV.xx.
package br.com.alcione.geo;
public class objetoGeo
{
protected Color cor;
protected int x, y;
public objetoGeo(Color cor, int x, int y)
{
this.cor = cor; this.x=x; this.y = y;
};
public Color retCor() {return cor};
}
Exemplo IV-14. Indicando que uma classe pertence ao pacote
br.com.alcione.geo.
Para que a mquina virtual consiga achar o pacote devemos coloc-lo em
diretrio com a mesma estrutura do nome do pacote e que tenha como raiz
algum diretrio constante na varivel de ambiente classpath. Por exemplo,
suponha que a varivel classpath contenha os seguintes diretrios:
CLASSPATH=.;C:\JAVA\LIB;C:\meujavalib
ento o arquivo objetoGeo.class resultante da compilao do arquivo
objetoGeo.java pode ser colocado no diretrio:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
86
C:\meujavalib\br\com\alcione\geo
Note que a estrutura do diretrio combina com a estrutura do nome do
pacote. Para usar a classe em outra unidade de compilao basta incluir a
seguinte diretiva no arquivo fonte:
import br.com.alcione.geo.*;
O formato do nome do pacote no foi escolhido por acaso. Se existe a
pretenso de us-lo na Internet ento deve-se adotar um nome que seja nico na
rede. Para garantir esta unicidade utiliza-se o nome do domnio do criador do
pacote com a ordem dos campos invertida, evitando assim a coliso de nome na
Internet. Por exemplo, nome do pacote br.com.alcione.geo origina-se da
inverso do nome do meu domnio (alcione.dpi.ufv.br) concatenado com o
nome geo.
Por simplicidade. na maioria dos exemplos adotados neste livro,
adotaremos o pacote default.
O Mecanismo de Extenso
A partir da verso 1.2 a linguagem J ava apresentou um mecanismo para
adicionar classes ao ncleo bsico da linguagem, dispensando deste modo o uso
da varivel de ambiente classpath. Este mecanismo chamado de
Mecanismo de Extenso. O mecanismo de extenso tambm oferece suporte
para envio de classes pela rede para uso em Applets. As extenses so agrupadas
em arquivos J AR que so abordados no captulo que trata dos Applets. Uma vez
feito isso, pode-se transformar as classes em extenses utilizando uma das duas
formas:
1. Extenso Instalada colocando o arquivo J AR em um local
predeterminado na estrutura de diretrios do ambiente de tempo de
execuo de J ava(Java Runtime Environment ou J RE).
2. Extenso de download Extenso referenciando o arquivo J AR de uma
forma especfica, a partir do manifesto de outro arquivo J AR.
Extenso Instalada
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
87
Para incluir uma nova classe ou pacote no ncleo bsico da linguagem
basta colocar o arquivo J AR onde que contm a classe no diretrio /lib/ext
do ambiente de tempo de execuo. O diagrama mostrado na figura IV.xx
mostra a localizao deste diretrio dentro da estrutura de diretrios do ambiente
J ava.
Figura IV.xx- localizao do diretrio ext dentro da estrutura de diretrios
Java.
Por exemplo, suponha que desejamos acrescentar o pacote do exemplo
IX. s extenses da linguagem J ava no ambiente local. Para isso devemos criar
primeiro o arquivo J AR. No ambiente DOS o comando seria o abaixo, executado
no diretrio acima do diretrio /br:
jar cvf geo.jar br\com\alcione\geo\objetoGeo.class
Aps isso colocaramos o arquivo geo.jar dentro do diretrio /ext.
Para usar a classe o procedimento idntico ao uso no caso do classpath, ou
seja basta colocar a seguinte diretiva no arquivo fonte:
import br.com.alcione.geo.*;
Extenso de Download
As extenses de download ocorrem quando arquivos J AR ou classes so
indicados como extenses de outros arquivos J AR. Por exemplo, suponha que
J ava 1.3
lib include bin jre
bin
bin
lib
audio cmm fonts ext images security
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
88
existem dois arquivos J AR, x.jar e y.jar, localizados no mesmo diretrio.
Para tornar o arquivo y.jar uma extenso do arquivo y.jar basta colocar a
seguinte informao no manifesto do arquivo x.jar:
Class-Path: y.jar
Deste modo toda classe no arquivo x.jar pode referenciar as classes do
pacote y.jar. Se os arquivos no estiverem no mesmo diretrio ser
necessrio indicar o caminho relativo at o arquivo da extenso. possvel
indicar vrias extenses, separando-as por espao ou usando vrias diretivas
Class-Path. Para indicar um diretrio como extenso basta adicionar o
sufixo / no ao nome do diretrio. Por exemplo:
Class-Path: meudir/
Derivando classes
O reuso de componentes de programas tem sido uma das principais metas
dos projetistas de linguagens de programao. A razo desta busca que a
reutilizao de componentes economiza esforos e acelera o processo de
desenvolvimento de sistemas de computadores. Essa meta pode ser atingida em
parte por meio da criao de classes que so extenses de classes predefinidas.
As extenses herdam todos os atributos da classe base ou superclasse. Por
exemplo, suponha que algum tenha definido uma classe para representar os
dados de uma conta bancria:
Figura IV.2- Classe Conta.
Suponha tambm que alm da conta corrente bsica mais dois tipos de
conta devam ser criadas: poupana e conta especial. A poupana possui todos os
Conta
-nmero:num
-Saldo: float
-CPF:Num
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
89
atributos de uma corrente e mais um atributo contendo a data de abertura da
conta que ser usada para clculo do valor dos juros e correo monetria que
ser acrescentado ao saldo da conta. A conta especial possui todos os atributos
de uma corrente e mais um atributo contendo o valor de limite de crdito.
No exemplo descrito acima seria um desperdcio de tempo e cdigo se
precisssemos codificar todos os atributos e mtodos relacionados da classe
Conta nessas duas novas classes. Para evitar esta duplicao de esforo basta
declaramos essas duas novas classes como subclasses da classe Conta. Desta
forma apenas os atributos que no esto declarados na superclasse e mtodos
associados precisam ser codificados, uma vez que os membros da superclasse
so herdados pelas subclasses. A figura IV.3 mostra o diagrama de classe
contendo o relacionamento entre as classes e o exemplo IV.13 mostra o cdigo
J ava correspondente.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
90
Figura IV.3- Relao entre as classes.
public class Conta
{
long numero;
long cpf;
double saldo;
public Conta(long n, long c, double s)
{
numero = n; cpf = c; saldo = s;
}
public long getNumero(){return numero;}
public long getCpf(){return cpf;}
public double getSaldo(){return saldo;}
public void setSaldo(double s){saldo = s;}
public void somaSaldo(double v){saldo += v;}
}
import java.util.*;
public class CPoupanca extends Conta
{
Date dataAber;
public CPoupanca(long n, long c, double s, String d)
{
super(n,c,s);
dataAber = new Date(d);
Conta
-nmero:num
-Saldo: float
-CPF:Num
CPoupana
-DataAber:Data
CEspecial
-Limite: float
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
91
}
public String getData(){return dataAber.toString();}
}
public class CEspecial extends Conta
{
double limite;
public CEspecial(long n, long c, double s, double l)
{
super(n,c,s);
limite = l;
}
public double getLimite(){return limite;}
public double getSaldo(){return saldo+limite;}
public void setLimite(double l){ limite = l;}
}
Exemplo IV-15. Implementao das Classes.
Podemos notar que para declarar uma classe como subclasse de outra
basta colocarmos a palavra-chave extends aps o nome da classe e o nome da
superclasse aps a palavra-chave. Apenas o nome de uma superclasse
permitido, portanto J ava no permite que uma classe seja subclasse de mais de
uma classe (herana mltipla).
Herana Mltipla
A capacidade de possuir mais de uma superclasse chamada de herana mltipla. A
linguagem C++suporta a herana mltipla. No entanto, a implementao desta facilidade
complexa e sua utilizao tende a gerar erro. Alm disso poucos so os casos que demandam o
uso desta soluo, e mesmo nestes casos possvel utilizar outras solues. Por essas razes a
linguagem J ava no implementou a herana mltipla. Nos casos onde necessrio que um objeto
adote o comportamento de mais de uma classe devemos utilizar as interfaces, como ser visto
mais adiante.
Todos os membros declarados com os modificadores public e
protected podem ser acessados diretamente na subclasse. O membros
declarados com o modificador private no so visveis dentro da subclasse.
super
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
92
Podemos notar tambm que no construtor das subclasses do exemplo
IV.12 existe uma chamada a um mtodo super(). Este mtodo representa a
chamada ao construtor da superclasse. Se no for chamado explicitamente o
compilador ir gerar cdigo para chamar o construtor default da superclasse. No
entanto, se desejamos chamar explicitamente um construtor com argumentos
devemos usar o mtodo super().
A classe Object
importante salientar que toda classe em J ava, com exceo da classe
Object subclasse de alguma classe. Se o programador no declarar a classe
base ento a classe base ser a classe Object. Desta forma a classe Object
a raiz da hierarquia de classes da linguagem J ava. Sendo assim, todo objeto na
linguagem J ava herda os seguintes mtodos pblicos e protegidos da classe
Object.
Mtodos Pblicos Descrio
public boolean equals(Object
obj)
Verifica se dois objetos so iguais. A
verificao feita sobre o endereo do objeto .
public final native Class
getClass()
Retorna a classe do objeto em tempo de
execuo.
public native int hashCode() Retorna o valor do objeto.
public final native void
notify()
Notifica um thread que est esperando sobre
um objeto.
public final void notifyAll() Notifica todos os threads que est esperando
sobre um objeto.
public String toString()
Retorna uma representao em String do
objeto.
public final void wait() Espera para ser notificado por outro thread.
public final void wait(long
timeout)
Espera para ser notificado por outro thread.
public final void wait(long
timeout, int nanos)
Espera para ser notificado por outro thread.
Mtodos Protegidos Descrio
protected native Object clone() Cria uma cpia do objeto corrente.
protected void finalize() Chamado pelo coletor de lixo antes de liberar a
rea de memria.
Tabela IV.xx- Mtodos pblico e protegidos da classe Object.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
93
Sobrescrita e Polimorfismo
Outro ponto interessante que podemos observar no exemplo IV.12 que
a classe CEspecial possui um mtodo com a mesma assinatura que um
mtodo da superclasse. o mtodo getSaldo() que no caso da classe
CEspecial deve incluir o limite de crdito como parte do saldo.
Neste caso o mtodo da subclasse est sobrescrevendo ou ocultando o
mtodo da superclasse. Toda vez que o mtodo getSaldo() for invocado
dentro de algum mtodo da classe CEspecial ou for chamado por meio de
um objeto da classe CEspecial o mtodo chamado ser uma instncia do
declarado na classe e no do declarado na superclasse. No entanto, possvel
invocar uma instncia do mtodo declarado na superclasse de dentro de algum
mtodo da subclasse, bastando qualificar o mtodo com a palavra chave super
como mostrado abaixo:
super.getSaldo();
Por exemplo, o mtodo getSaldo() da classe CEspecial poderia
ser rescrito da seguinte forma:
public double getSaldo()
{
return super.getSaldo()+limite;
}
Suponha agora uma classe como mostrado no exemplo IV.13. O mtodo
imprimeSaldo() espera um objeto da classe Conta mas recebe um objeto da
classe CEspecial. Isto no causa nenhum problema porque todo objeto da classe
CEspecial tambm um objeto da classe Conta. No entanto fica a pergunta:
que mtodo getSaldo() invocado dentro o mtodo imprimeSaldo()? O da
classe Conta ou o da classe CEspecial?
public class TestaConta
{
public void imprimeSaldo(Conta c)
{
System.out.println(O Saldo e:+c.getSaldo());
}
public static void main(String a[])
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
94
{
TestaConta testa = new TestaConta();
CEspecial c= new CEspecial(1, 123456, 500.0, 100.0);
testa.imprimeSaldo(c);
}
}
Exemplo IV-16. Teste de polimorfismo.
A resposta : o mtodo chamado pertence a instncia da classe
Cespecial. Portanto a regra a seguinte: sempre chamado o mtodo da
declarado na classe a que o objeto pertence e no da classe superclasse. Para
que essa regra seja implementada necessrio que a associao da chamada do
mtodo com o cdigo do mtodo em casos como no exemplo IV.13 seja feito em
tempo de execuo. Isso ocorre porque somente em tempo de execuo ser
possvel saber a classe do objeto que est sendo recebido como parmetro.
O momento em que ocorre a associao de um identificador com a objeto
que identifica chamado tempo de amarrao. Se este momento ocorre em
tempo de compilao a amarrao dita esttica (static binding). Se associao
ocorre em tempo de execuo a amarrao dita dinmica (dynamic binding).
Assim, na linguagem J ava, em se tratando da associao da chamada do mtodo
ao cdigo do mtodo a amarrao dinmica. A nica exceo se o mtodo for
declarado como final. Neste caso a amarrao esttica porque no possvel
sobrescrever o mtodo.
A implementao da amarrao dinmica claramente mais ineficiente
que a esttica, uma vez que o compilador precisa gerar cdigo para determinar a
classe do objeto em tempo de execuo. No entanto, existem vantagens
considerveis na adoo da amarrao dinmica. Ela facilita o reuso e a
extenso de programas. Por exemplo, se criarmos uma nova subclasse da classe
Conta que tambm sobrescrevesse o mtodo imprimeSaldo(), nenhuma
modificao precisaria ser feita em mtodos como o imprimeSaldo() da
classe TestaConta, uma vez que o mtodo correto sempre chamado.
Portanto, podemos ampliar a hierarquia de um conjunto de classes sem precisar
alterar, na maioria das vezes, os mtodos que fazem uso dessa hierarquia.
A amarrao dinmica de mtodos tambm acarreta um comportamento
polimrfico. Por exemplo, o objeto que passado para o mtodo
imprimeSaldo() pode exibir comportamento diversos, dependendo da classe
a qual realmente o objeto pertence.
Amarrao Dinmica em C++
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
95
Apesar da amarrao dinmica entre os identificadores dos mtodos e o corpo dos
mtodos ser considerada uma caracterstica importante para linguagens orientadas a objetos, nem
todas a linguagens deste estilo de programao adotam este comportamento como padro. Por
exemplo, a linguagem C++adota a amarrao esttica como padro. Se o programador desejar
que os mtodos possuam amarrao dinmica ento o deve instruir o compilador explicitamente
prefixando os mtodos com a palavra-chave virtual. A razo para esta deciso dos projetistas da
linguagem est na eficincia. A amarrao dinmica bem mais ineficiente que a amarrao
esttica e a linguagem C++se prope a ser uma linguagem que capaz de gerar cdigo que
executa eficientemente.
O exemplo IV.14 procura esclarecer melhor a amarrao dinmica dos
mtodos na linguagem J ava.
public class Animal
{
public void fala(){}
}
public class Cachorro extends Animal
{
public void fala(){System.out.println(Au au!);}
}
public class Gato extends Animal
{
public void fala(){System.out.println(Miau!);}
}
public class UsaAnimal
{
public void falaAnimal(Animal a){a.fala();}
}
Exemplo IV-17. Classes de vozes dos animais.
No exemplo IV.14 o mtodo falaAnimal() da classe UsaAnimal
recebe qualquer subclasse da classe Animal invoca o mtodo fala() da
subclasse. Para incluir mais um animal na hierarquia basta declarar mais uma
subclasse:
public class Pato extends Animal
{
public void fala(){System.out.println(Qu Qu!);}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
96
Exemplo IV-18. Classe com a voz do pato.
Nada precisa ser alterado nas outras classes. A nova classe pode ser
inclusive subclasse de outra subclasse que no haver problema:
public class GatoRonronando extends Gato
{
public void fala(){System.out.println(Purr!);}
}
Exemplo IV-19. Classe com a voz do pato.
Podemos observar que a classe Animal propriamente dita no faz nada
a no ser servir de cabide para as outras classes. pouco provvel que ela seja
instanciada, j que o seu nico mtodo no faz nada. Classes como essa
funcionam como um esquema para as subclasses e deveriam ser tratadas
adequadamente pelo compilador. Este tpico tratado adequadamente na
prxima seo.
Classes e Mtodos Abstratos
Classes abstratas so esquemas ou esqueletos de classes cujo nico
propsito e servir de cabides para pendurar classes. Uma classe abstrata no
pode ser instanciada e possui um ou mais mtodos abstratos. Um mtodo
abstrato um mtodo sem corpo cuja a assinatura precedida da palavra-chave
abstract. Na verdade o programador no obrigado a declarar mtodos
abstratos em classes abstratos, porm raramente surgira uma situao em que
no isso no faa sentido. As subclasses precisam sobrescrever os mtodos
abstratos, caso contrrio tambm no podero ser instanciadas.
A classe Animal do exemplo IV.14 uma tima candidata classe
abstrata. Para torn-la uma classe abstrata basta preceder a declarao da classe
com a palavra chave abstract e declarar um ou mais de seus mtodos como
abstratos, como mostra o exemplo IV.17.
abstract public class Animal
{
abstract public void fala();
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
97
Exemplo IV-20. Classe abstrata Animal.
Alm de no poder ser instanciada a classe abstrata possui outras
limitaes. Uma classe abstrata no pode possuir mtodos estticos e
construtores. Outra limitao que os mtodos abstratos no podem ser
privados, uma vez que as subclasses precisam sobrescrever os mtodos
abstratos.
Interfaces
As Interfaces podem ser encaradas como classes abstratas completamente
no implementadas. Ou seja, todos os mtodos so abstratos e os atributos s
podem ser do tipo static final (constantes). A forma geral de uma Interface
obedece o seguinte esquema:
interface identificador
{
corpo da interface
}
A classe que implementa uma interface precisa fornecer uma
implementao para todas os mtodos definidos na Interface. Para que uma
determinada classe seja vista como uma implementao de uma interface
preciso indicar isto colocando a palavra chave implements na declarao da
classe e aps a palavra chave a lista com o nome de todas as interfaces que se
deseja implementar, separados por vrgula. O esquema abaixo mostra a forma
geral do uso de Interfaces.
class Identificador implements Interface1, Interface2,...
{
corpo da classe
}
O leitor deve estar se perguntando: se a interface apenas uma classe
abstrata completamente no implementada ento porque no criar simplesmente
uma classe abstrata? A resposta est relacionada com o tipo de herana que
ocorre entre as classes de J ava. Como j mencionamos a linguagem J ava no
permite a herana mltipla, ou seja, uma classe s pode ser subclasse de apenas
uma classe. No entanto, existem situaes em que necessrio definir uma
classe que possa ser vista de modos distintos. ai que entram as Interfaces. A
interface define uma forma de ver uma classe, restando para a classe a
implementao desta viso e a linguagem J ava permite que uma classe
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
98
implemente tantas Interfaces quantas se desejar. Desta forma J ava evita os
principais problemas da herana mltipla (herdando mltiplas definies e no
mltiplas implementaes), sem abrir mo de criar classes que podem ser vistas
de formas diferentes.
Por exemplo, suponha que um mtodo receba um objeto que representa a
interface de sada de um determinado programa. O objetivo deste mtodo usar
um mtodo do objeto de interface para escrever uma mensagem na tela. O
exemplo IV.xx mostra o cdigo da classe que contm o mtodo.
public class EscreveMem
{
public static void escreve(InterUsuario inter)
{
inter.exibeMensagem(ola mundo!);
}
}
Exemplo IV-21. Classe que recebe um objeto de interface.
Suponha tambm que desejamos que o programa tenha tanto uma
interface com o usurio em modo grfico e em modo texto. Usaremos de agora
em diante as iniciais IU para significar interface com o usurio para evitar a
confuso com o conceito de Interfaces que estamos introduzindo. Se desejamos
que o mtodo escreve() possa receber instncias dos dois tipos de IU
necessrio que ambas sejam do tipo InterUsuario. No entanto, como veremos
mais adiante, as classes que implementam IU grficas devem ser subclasses de
classes predefinidas como por exemplo da classe java.awt.Frame. Portanto,
temos agora um problema de herana mltipla. A classe que implementa a IU
grfica de herdar de uma classe como a Frame e da classe InterUsuario. A
soluo simples. Basta definir InterUsuario como uma interface como
mostra o exemplo IV.xx.
interface InterUsuario
{
abstract public void exibeMensagem(String men);
}
Exemplo IV-22. Definio de como InterUsuario interface.
Agora basta que cada classe que representa um tipo de IU implemente a
interface InterUsuario. O exemplo IV.xx mostra a implementao de uma
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
99
IU grfica simples e o exemplo IV.xx mostra a implementao de uma IU em
modo texto simples.
import java.awt.*;
import java.awt.event.*;
public class Janela extends Frame implements InterUsuario
{
private Label label1;
public Janela() {
addWindowListener (new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
}
);
setLayout (new BorderLayout());
label1 = new Label();
label1.setText ("Mensagem");
add (label1, "South");
setSize(200,100);
}
public void exibeMensagem(String men)
{
label1.setText(men);
}
}
Exemplo IV-23. IU grfica.
public class Console implements InterUsuario
{
public void exibeMensagem(String men)
{
System.out.println(men);
}
}
Exemplo IV-24. IU em modo texto.
O exemplo IV.xx mostra uma forma de uso das classes definidas nos
exemplos de IV.xx a IV.xx.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
100
public class UsaIUs
{
public static void main(String args[])
{
Console c = new Console();
Janela j = new Janela();
j.setVisible(true);
EscreveMem. escreve(c);
EscreveMem. escreve(j);
}
}
Exemplo IV-25. Uso das IUs.
As Interfaces tambm so teis sob o aspecto de projeto. Em C++os
programadores esto acostumados separar a interface de uma classe de sua
implementao. Geralmente dentro das classes so declaradas apenas as
interfaces dos mtodos sendo que a implementao dos mesmos pode ser feita
posteriormente. Isto permite que se possa dividir a etapa da especificao do uso
de uma classe (o que ela faz) de sua implementao (como ela faz). Isto reduz a
complexidade da tarefa de implementao e permite melhor diviso de tarefas.
No entanto, na linguagem J ava os mtodos de uma classe so geralmente
implementados dentro da classe. As Interfaces e Classes podem ser utilizadas
para permitir a separao entre a interface e a implementao a exemplo de
como e feito em C++.
Classes Internas
A partir da verso 1.1 da linguagem J ava foi includa a permisso para
declarar uma classe dentro da declarao de outra classe. As classes declaradas
dentro de outra classe so denominadas de Classes Internas. A figura IV.xx
mostra um esquema contendo o posicionamento relativo de uma classe interna.
public class Externa
{
...
class Interna
{
...
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
101
}
Figura IV.xx- Posicionamento relativo das classes Interna e Externa.
Os atributos e mtodos declarados na classe externa so visveis pela classe
interna, mesmo os declarados como protected ou private. No entanto, o
contrrio no verdadeiro, ou seja, os atributos e mtodos da instncia da classe
interna s so visveis pela classe interna se forem declarados como pblicos.
Como j foi dito as classes mais externas (nvel topo) s podem ser
declaradas como pblicas ou friendly (default). No entanto, as classes internas
podem tambm receber os qualificadores private e protected. O efeito destes
qualificadores sobre a visibilidade da instncia da classe o mesmo obtido sobre
um atributo qualquer. O exemplo IV.xx mostra o caso de uma classe contendo
uma classe interna privada. O exemplo tem por objetivo apenas ilustrar o uso de
classes internas.
public class Calc
{
Incrementa inc1, inc5;
public Calc ()
{
inc1=new Incrementa(1);
inc5=new Incrementa(5);
}
private class Incrementa
{
int i;
public Incrementa(int ai){i=ai;}
public int inc(int num){return i+num;}
}
public int calcula(int x){return inc1(x)+inc5(x);}
}
Exemplo IV-26. Uso de classes internas.
A incluso de classes internas foi uma modificao a nvel de linguagem em
J ava e o leitor deve estar se perguntando o que motivou a uma modificao to
profunda em J ava. A reposta est no novo modelo de eventos proposto pela
verso 1.1. No novo modelo, como poder ser constatado no captulo que trata
sobre a AWT, as classes internas se adequam perfeitamente. Aliado a esta
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
102
motivao existe o fato de que esta alterao na linguagem no acarretou
nenhuma modificao na mquina virtual, tratada pelo compilador. Desta modo
esta facilidade no gerou qualquer impacto em termos desempenho dos
programas. O exemplo IV.xx mostra o exemplo de uso de uma classe interna
para capturar eventos. Este tipo de uso ser tratada com maiores detalhes no
captulo que trata sobre AWT.
public class Janela extends Frame {
public Janela (String Titulo){
super(Titulo);
addWindowListener(new JanelaListener());
setSize(100,50);
}
private class JanelaListener implements WindowListener
{
public void windowOpened(WindowEvent we){}
public void windowClosed(WindowEvent we){}
public void windowIconified(WindowEvent we){}
public void windowDeiconified (WindowEvent we){}
public void windowActivated(WindowEvent we){}
public void windowDeactivated(WindowEvent we){}
public void windowClosing(WindowEvent we){
setVisible(false);
dispose();
System.exit(0);
}
};
};
Exemplo IV-27. Uso de classes internas para receber eventos.
Classes Internas Annimas
J ava permite que se crie um objeto de uma classe sem nome. As classes so
declaradas no momento do retorno de um mtodo ou durante a passagem de
parmetros e o objeto criado quando o argumento ou a expresso de retorno
avaliada. O exemplo IV.xx mostra o retorno de um objeto de uma classe
annima.
public class TesteAnonima
{
public Object retAnon()
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
103
{
return new Object()
{ // Definio da classe annima
private int i=10;
public int value(){return i;}
};
}
};
Exemplo IV-28. Retorno de um objeto de uma classe annima.
Pode parecer pelo exemplo IV.xx que o objeto retornado uma instncia
da classe Object, no entanto na verdade uma instncia de uma classe
annima que subclasse da classe Object. A classe annima possui atributos e
mtodos prprios que a diferenciam da classe Object e esto definidos na
declarao da classe. Usamos a classe Object apenas para exemplificar com
uma classe conhecida. Qualquer classe pode fazer o papel de superclasse. O
exemplo IV.xx mostra o uso de uma classe annima na criao de um objeto
para lidar com eventos sobre um boto.
class BT
{
Button bt;
public BT()
{
bt = new Button(OK);
bt.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dispose();
}
});
}
}
Exemplo IV-29. Uso de uma classe annima para tratamento de eventos.
As classes annimas so adequadas para situaes onde necessitamos em um
local especfico de um objeto de uma classe ligeiramente diferente de outra
classe j declarada. Com a classe annima evitamos ter que declarar uma nova
classe para atender apenas uma necessidade local.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
104
Converso
Uma varivel declarada como referencia para objetos de uma
determinada classe pode receber referencias de objetos de subclasses sem a
necessidade de se usar qualquer operador de converso. A converso feita
automaticamente, uma vez que toda instncia de uma subclasse tambm uma
instncia da superclasse. Por exemplo:
Object o;
String s = teste;
o = s;
A atribuio acima possvel porque a classe Object uma superclasse
de String (Na verdade superclasse de todas as classes). J a converso
inversa s possvel se o objeto for realmente do tipo da subclasse, e mesmo
assim preciso utilizar um operador de converso forada (casting):
Object o;
String s = teste;
String t = teste;
o = s;
t = (String) o;
Excees
Quanto maior o nmero de situaes de exceo que um determinado
programa consegue lidar, mais robusto este programa. Para construir um
programa robusto o programador deve prever, alm das situaes onde os dados
de entrada e os recursos se apresentam de forma adequada, as situaes onde
algo pode impedir a computao normal. Existem trs abordagens tpicas para
esses casos:
1) Ignorar neste caso a ao ser a padro do sistema, provavelmente
a interrupo do programa, ou no mnimo do comando onde ocorreu
o erro, e a exibio de uma mensagem ininteligvel na sada padro,
gerada pelo sistema. Esta abordagem mais simples, mas certamente
no a mais interessante, principalmente do ponto de vista do usurio
final.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
105
2) Retornar o cdigo de erro. No caso da linguagem J ava este retorno
s pode ser feito via valor de retorno da funo. No entanto algumas
vezes no existem valores disponveis para indicar o erro. Por
exemplo, quando um mtodo retorna um valor inteiro costuma-se
usar os valores 0 ou 1 para sinalizar uma condio de erro, mas
como agir no caso desses e todos os outros valores de inteiros serem
valores vlidos em uma execuo normal? Existe ainda o problema
de que esta abordagem no resolve o problema de erros que ocorrem
nos construtores. Como os construtores no retornam valores no
possvel sinalizar erros dessa forma. Esta uma abordagem muito
comum entre os programadores de C e Pascal, e ainda usada pelos
programadores de C++. No entanto, as linguagens mais modernas
como C++e J ava disponibilizam recursos que permitem um melhor
tratamento de excees, como veremos na terceira abordagem.
3) Declarar um ou mais tratadores de excees. Um tratador de
exceo uma parte do cdigo que tem por objetivo recuperar a
execuo do programa aps a ocorrncia da exceo, permitindo que
o sistema se comporte suavemente, mesmo sob condies adversas.
A sintaxe e semntica dos tratadores de exceo variam muito de
linguagem para linguagem, mas tem tendido a uma certa
uniformizao nas linguagens mais modernas. A linguagem J ava, por
ter como objetivo ser uma linguagem segura, obriga que os
programador capture todas as excees, menos as derivadas da classe
RuntimeException.
Na linguagem J ava a amarrao do tratador exceo definida em
tempo de compilao. Nela, o programador envolve os comandos passveis de
gerar excees em blocos try/catch com o formato geral mostrado abaixo:
try
{
cdigo que pode gerar excees
} catch(classe de exceo1 objeto) {
tratamento da exceo1
} catch(classe de exceo2 objeto) {
...
} catch(classe de exceoN objeto) {
tratamento da exceoN
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
106
As excees so representadas como objetos A poro catch do bloco
possui um bloco com comandos para tratamento da exceo. O bloco que trata
das excees no tem acesso s variveis declaradas dentro do bloco try{},
uma vez que o escopo destas variveis est delimitado pelo bloco. Por exemplo,
o mtodo esttico parseInt() da classe Integer lana como exceo um
objeto da classe NumberFormatException se receber como argumento um
String que no pode traduzido para uma representao inteira. O cdigo para
capturar este tipo de exceo poderia ser semelhante ao apresentado no exemplo
XX.XX.
public class Excecao1
{
public static void main(String a[])
{
try
{
int i = Integer.parseInt(a[0]);
System.out.println("A cadeia passada pode ser +
tranformada para nmero :+i);
} catch(NumberFormatException e)
{ System.out.println("A cadeia passada no pode ser +
tranformada para nmero :+a[0]);
}
}
}
Exemplo IV.XX- Capturando a exceo NumberFormatException.
Se o bloco catch no possuir nenhum comando de return ou alguma
chamada funo exit(), ento o programa reassumido aps o ltimo bloco
catch.
A hierarquia de Excees
As excees so objetos que pertencem a classes que esto organizadas
em uma hierarquia e cuja classe que se encontra no topo da hierarquia a classe
Throwable. A classe Throwable possui duas subclasses: Exception e
Error. Exception e suas subclasses so usadas para indicar condies que
podem ser recuperadas. Error e suas subclasses indicam condies que em geral
no podem ser recuperadas, causando a terminao do programa.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
107
Todos os objetos da classes Exception devem ser capturados ou
explicitamente relanados para um nvel acima na pilha de chamadas. Isto s no
vlido para os objetos da classes RuntimeException. A RuntimeException
suas subclasses fazem definem as excees que podem ser lanadas durante a
execuo normal da mquina virtual, como diviso por zero ou indexao fora
dos limites do array. A exceo NumberFormatException mostrada no exemplo
uma subclasse da RuntimeException. Como essas excees podem ser
lanadas por um nmero muito grande de mtodos, seria trabalhoso para o
programador se ele fosse obrigado a incluir cdigo para capturar todas essas
excees. Portanto, instncias da classe RuntimeException e suas subclasses
no precisam ser capturadas. A figura IV.XX mostra uma parte da hierarquia
Throwable at o nvel 3. O nmero de classes nesta hierarquia muito grande
como o leitor pode verificar no apndice XX. O programador pode tambm
adicionar classes a esta hierarquia como veremos mais adiante.
Figura IV.XX- Hierarquia de excees.
Capturando mais de uma exceo
Um determinado mtodo pode lanar mais de uma exceo, assim como
pode existir mais de um mtodo dentro de um bloco try/catch com potencial
de lanar excees. Portanto, muitas vezes preciso definir um bloco
try/catch com capacidade de tratar mais de uma exceo. Isto feito por meio
da definio de mais de uma clusula catch. Cada clusula catch trata uma
exceo. Como a busca pela clusula catch que deve tratar uma determinada
exceo feita de cima para baixo preciso tomar o cuidado de posicionar as o
tratamento das excees mais genricas mais abaixo do que o tratamento das
excees mais especficas. Caso contrrio o tratamento das excees mais
Throwable
Exception
RuntimeException
Error
ThreadDeathError VirtualMachineError LinkageError
.
.
.
.
.
.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
108
especificas nunca ser executado. O exemplo IV.xx mostra um trecho de cdigo
cujo bloco try/catch capaz de capturar as excees IOException,
NumberFormatException e Exception. Note que por ser uma exceo mais
genrica que as outras duas o tratamento da exceo Exception posicionado
aps os outros. Como as excees NumberFormatException e IOException
no se encontram na mesma linha de herana, a posio de uma relativa a outra
no tem significado.
import java.io.*;
class Excecao2
{
public static void main(String a[])
{
try
{
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("Entre um nmero:");
int i = Integer.parseInt(in.readLine());
}catch(IOException e)
{System.out.println(Erro de leitura!);}
catch(NumberFormatException e)
{System.out.println(No um nmero!);}
catch(Exception e)
{System.out.println(ocorreu algum erro);}
}
}
Exemplo IV.XX- Capturando a vrias excees.
Lanando excees
At agora temos visto apenas como capturar as excees lanadas. Est
na hora de olharmos o outro lado da moeda, ou seja, como lanar as excees.
As excees so lanadas utilizando-se o operador throw. A forma geral do
comando a seguinte:
throw <objeto>
Pode-se tambm criar o objeto no instante do lanamento, invocando o
construtor. Neste caso a forma geral do comando seria a seguinte:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
109
throw new <classe>(<parmetros>)
Note que pode-se passar parmetros para o construtor que podem ajudar
na recuperao do problema pelo tratador de excees. O mtodo onde a
exceo lanada deve tratar a exceo ou pass-la para mtodo que o invocou.
Para passar a exceo para o mtodo que o invocou a assinatura do mtodo
corrente deve conter uma clusula throws aps a lista de argumentos, como
mostrado abaixo:
<modificador><tipo retorno> <identificador>(<argumentos>)
throws <exceo
1
>,<exceo
2
>,...,<exceo
n
>
{
}
Note que possvel indicar na assinatura do mtodo o repasse de vrias
excees. O exemplo IV.xx mostra tanto o lanamento de um objeto da classe
Exception caso os parmetros para o construtor da classe no sejam corretos.
import java.io.*;
class NumPos{
private int num;
public NumPos(int aNum) throws Exception {
if (aNum < 1)
throw new Exception(Nmero no positivo);
num = aNum;
}
}
public class Excecao3 {
public static void main(String a[]) {
try
{
NumPos np = new NumPos(Integer.parseInt(a[0]));
}catch(Exception e)
{System.out.println(e.getMessage());}
}
}
Exemplo IV.XX- Lanando excees.
Na verdade o pode-se usar a clusula throws na assinatura do mtodo
para repassar qualquer exceo que se desejar. O exemplo IV.xx , mostra o
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
110
mtodo m1 que repassa qualquer objeto da classe Exception que for lanado em
seu corpo, mesmo os que no forem explicitamente lanado por meio do
comando throw:
public class Excecao4
{
public void m1(int i) throws Exception
{
if (i == 0 ) throw new NumberFormatException();
System.out.println(2/i);
}
}
Exemplo IV.XX- Repassando todas as excees.
Comportamento do Sistema diante das Excees
Agora que j vimos como tratar e como lanar excees podemos discutir
como o comportamento global do sistema diante das excees. Ou seja, como
a sequncia de busca por um tratador aps a ocorrncia de uma exceo?
Quando ocorre uma exceo em um mtodo o sistema verifica se o comando
onde ocorreu a exceo est incluso em bloco try/catch com uma clusula
catch associada exceo. Neste caso o controle transferido para o bloco de
tratamento da clusula catch. Caso contrrio, o sistema desempilha um nvel na
pilha de chamada de mtodos e verifica se a chamada ao mtodo anterior est
inclusa em bloco try/catch com uma clusula catch associada exceo. O
sistema prossegue desta forma at que um bloco tratador seja encontrado. Caso
encontre o bloco tratador e este no possua nenhum comando de sada (return
ou System.exit()), ento o controle ser retomado no nvel de chamada onde
foi tratado aps o ltimo bloco catch. e no onde ocorreu a exceo. Caso no
encontre nenhum bloco tratador, ao atingir o nvel mais alto da pilha de
chamadas o programa abortado.
A figura IV.xx procura ilustrar o comportamento do sistema diante de
uma exceo, tratada em um nvel da pilha de chamada diferente de onde
ocorreu.
Pilha de chamadas Cdigo fonte
m1
m2
m3
public class Excecao5
{
public void m1(int i)
{
try {
m2(i)
}catch (Exception e){...};
...
}
public void m2(int i) throws Exception
{
m3(i);
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
111
Figura IV.XX- Propagao das excees.
Criando suas prprias excees
Se o programador concluir que nenhuma exceo pr-existente se
encaixa no tipo de erro que pretende sinalizar, ento criar uma classe nova para
representar essa exceo. A nica condio que a nova classe seja uma
extenso da subclasse Throwable ou de uma de suas subclasses. Procure
estender a classe Exception ou uma de suas subclasses, exceto o ramo da
RuntimeException, uma vez que, como j foi dito, esta ramificao da
hierarquia de excees utilizada para excees do sistema. Por exemplo,
podemos rescrever o exemplo IV.xx de modo que o mtodo lance uma exceo
definida pelo programador.
import java.io.*;
class NumPosException extends Exception
{
public NumPosException(String m){super(m);}
}
class NumPos
{
private int num;
public NumPos(int aNum) throws NumPosException {
if (aNum < 1)
ocorrncia
da exceo
tratamento
da exceo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
112
throw new NumPosException (Nmero no positivo);
num = aNum;
}
}
public class Excecao6 {
public static void main(String a[]) {
try
{
NumPos np = new NumPos(Integer.parseInt(a[0]));
}catch(NumPosException e)
{System.out.println(e.getMessage());}
}
}
Exemplo IV.XX- Lanando excees.
A clusula finally
Existe mais uma clusula opcional do bloco try/catch. Esta a clusula
finally. A clusula finally abriga uma trecho de cdigo que deve ser
executado independente se ocorreu ou no uma exceo no bloco try/catch.
Pode ser usada para realizar operaes de finalizaes, como por exemplo
fechamento de arquivos e canais de comunicao. O exemplo IV.xx ilustra o uso
da clusula finally.
import java.io.*;
class Excecao7
public static void main(String a[])
{
try
{
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("Entre um nmero:");
int i = Integer.parseInt(in.readLine());
}catch(IOException e)
{System.out.println(Erro de leitura!);}
catch(NumberFormatException e)
{System.out.println(No um nmero!);}
finally()
{System.out.println(Terminou.);}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
113
}
}
Exemplo IV.XX- Usando a clusula finally.
No exemplo IV.xx se no ocorrer nenhuma exceo a clusula finally
executada e a execuo reassumida aps a clusula finally. Caso ocorra
alguma exceo no bloco try/catch e exista alguma clusula catch associada
exceo ento a clusula finally executada aps o tratamento da exceo e a
execuo reassumida aps a clusula finally. Caso ocorra alguma exceo no
bloco try/catch e no exista alguma clusula catch associada exceo ento
a clusula finally executa antes da transferncia do controle para o mtodo
chamador.
Documentando o cdigo
Uma das maiores dificuldades no desenvolvimento de software
conseguir que os programadores produzam uma documentao relacionada com
os programas que esto desenvolvendo. Eles no gostam de interromper o
desenvolvimento para escrever paralelamente a documentao e aps o trmino
da implementao no se animam a passar um grande perodo de tempo
documentando todo o cdigo escrito. Pensando nisso os projetistas de J ava
desenvolveram um meio do programador embutir a documentao no prprio
cdigo, de modo que, no precisasse interromper a implementao.
A documentao inserida como um comentrio e usa uma sintaxe
especial que pode ser interpretada pelo programa javadoc para gerar um
documento HTML. Todo comentrio que deve ser interpretado pelo javadoc
deve ser iniciado por /** e terminado por */. O programador pode inserir
a documentao de duas formas:
1. rtulos (tags) iniciados pelo caractere @ e que denotam comandos
de documentao; ou
2. por meio de cdigo HTML embutido.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
114
Rtulos
O javadoc relaciona os comentrios com a estrutura codificada aps o
comentrio. As estruturas relacionadas com os comentrios so as classes,
variveis e mtodos. A exceo do rtulo @see todos os rtulos esto
relacionados com a documentao de classes ou mtodos.
Rtulo @see
O rtulo @see usado para gerar links para documentao de outras
classes. Os links no sero verificados pelo javadoc. Os formatos possveis
so os seguintes:
@see <nome da classe>
@see <nome da classe>#<nome do mtodo>
Rtulos para documentao de classes
Os seguintes rtulos so usados na documentao de classes:
Rtulo Descrio
@version <verso> Usado para incluir informao sobre a verso.
@author <autor> Usado para incluir informao sobre o autor.
Tabela IV.xx- Rtulos para documentao de classes.
Rtulos para documentao de mtodos
Os seguintes rtulos so usados na documentao de mtodos:
Rtulo Descrio
@param <nome> <descrio>
Usado para incluir informao sobre o
parmetro do mtodo.
@return <descrio>
Usado para incluir informao sobre o
valor de retorno do mtodo.
@exception <nome da classe>
<descrio>
Usado para incluir informao sobre a
exceo que pode ser lanada pelo
mtodo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
115
@deprecated
Includo a partir da verso 1.1. Indica
que o mtodo pode no ser mantido
nas prximas verses da linguagem.
Tabela IV.xx- Rtulos para documentao de mtodos.
Exemplo de Documentao
O exemplo IV.xx ilustra o uso dos rtulos para documentao do cdigo.
/**
Pessoa
Mantem os dados pessoais de uma pessoa.
@author Alcione de Paiva Oliveira
@author alcione@dpi.ufv.br
@version 1.0
*/
public class Pessoa
{
private String Nome;
private String Tel;
private String End;
// Construtor
/**
@param n String contendo o nome
@param t String contendo o telefone
@param e String contendo o endereo
@return no retorna valor
*/
public Pessoa(String n, String t, String e)
{
Nome = n; Tel = t; End = e;
}
/**
Retorna o nome da pessoa
@return uma String contendo o nome
*/
public String getNome(){return Nome;}
/**
Retorna o telefone da pessoa
@return uma String contendo o telefone
*/
public String getTel(){return Tel;}
/**
Retorna o endereo da pessoa
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
116
@return uma String contendo o endereo
*/
public String getEnd(){return End;}
}
Exemplo IV.XX- Exemplo de documentao.
HTML embutida
O programador pode incluir cdigo HTML dentro dos comentrios para
documentao da mesma forma que faria em um documento da Web, como
mostra o exemplo IV.xx.
/**
* <b>Pessoa<\b>
* Possui os seguintes objetivos
* <ol>
* <li> Objetivo1
* <li> Objetivo2
* </ol>
*/
public class Pessoa
{
...
}
Exemplo IV.XX- Uso de HTML embutida para documentar cdigo.
O javadoc ir ignorar os caracteres * no incio de cada linha ao gerar
a documentao. No use rtulos de ttulos como <h1> ou <hr>, uma vez que
o javadoc ir inserir rtulos de ttulos automaticamente.
Agenda Eletrnica verso Console 1.0
Iniciaremos agora a primeira verso de um programa que implementa
uma agenda eletrnica de endereos e telefones. Este programa evoluir ao
longo do livro, de acordo com os conhecimentos que sero apresentados. Em sua
primeira verso a agenda eletrnica ter uma interface baseada em linha de
comando e no armazenar o seu contedo em algum dispositivo de memria
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
117
permanente, o que no a torna muito til em termos prticos. Nas verses
posteriores a agenda eletrnica armazenar o seu contedo em arquivos e Banco
de Dados, ganhar interface grfica, poder ser utilizada em navegadores de
Web, ter uma arquitetura Cliente/Servidor, e outras facilidades. Esperamos com
isso mostrar os vrios aspectos da linguagem durante a evoluo do programa.
Outros exemplos sero apresentados de acordo com a necessidade, porm a
agenda eletrnica permanecer como exemplo principal.
O diagrama de classes da figura III.xx mostra os objetos que compe a
verso console da agenda.
Figura III. Diagrama de classes da verso console da agenda eletrnica.
Os objetos da classe Pessoa armazenam os dados de uma pessoa. Ela
fornece os mtodos para o acesso a esses dados.
O objeto da classe Agenda composto por vrios dados de pessoa. Este
fato est representado no diagrama pela associao de agregao. A classe
Agenda possui os mtodos necessrios para insero e recuperao dos dados. O
mtodo inserir(), trata de inserir uma pessoa na lista de pessoas, o mtodo
getPessoas(), retorna uma lista contendo todos os objetos da classe Pessoa e
o mtodo getPessoa() retorna um objeto da classe Pessoa com o nome
especificado.
AgendaInt
+obterPessoa()
+exibirLista()
+exibirPessoa()
Agenda
+inserir(pessoa p)
+pessoas getPessoas()
+Pessoa getPessoa(String Nome)
Pessoa
-String Nome
-String Tel
-String End
+getNome()
+getTel()
+getEnd()
0..*
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
118
A Classe AgendaInt responsvel por fornecer os mtodos que
implementam a interface com o usurio. Ela foi criada por questes de projeto,
uma vez que importante manter separado o cdigo das interfaces do sistema.
Primeiramente apresentaremos o cdigo da classe Pessoa.
/**
Pessoa
*/
public class Pessoa
{
private String Nome;
private String Tel;
private String End;
// Construtor
public Pessoa(String n, String t, String e)
{
Nome = n; Tel = t; End = e;
}
// Metodos
public String getNome(){return Nome;}
public String getTel(){return Tel;}
public String getEnd(){return End;}
}
Por questes de simplicidade a classe pessoa possui apenas um
construtor. As variveis de instncia so declaradas private para prevenir
acessos que no sejam por meio dos mtodos da classe. Segue abaixo o cdigo
da classe Agenda:
/**
AGENDA Verso Console 1.0.
*/
public class Agenda
{
Pessoa pessoas[];
// Construtor
public Agenda() {pessoas = null;}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
119
// Metodos
/**
inserir
*/
public void inserir(Pessoa p)
{
if (pessoas == null) pessoas = new Pessoa[1];
else AumentaCapacidade();
pessoas[pessoas.length-1] = p;
}
/**
Consultar
*/
public Pessoa getPessoa(String nome)
{
Pessoa aux = null;
for (int i=0; i< pessoas.length; i++)
if (pessoas[i].getNome().equals(nome))
aux = pessoas[i];
return aux;
}
/**
listar
*/
public Pessoa[] getPessoas(){return pessoas;}
/**
AumentaCapacidade
*/
private void AumentaCapacidade ()
{
Pessoa aux[] = new Pessoa[pessoas.length+1];
for (int i=0;i< pessoas.length;i++)
aux[i] = pessoas[i];
pessoas = aux;
}
}
De modo a manter o programa com poucas linhas no inserimos cdigo
para tratar erros para testar os valores que so passados para os mtodos ou
retornados por eles. O leitor deve ter isto em mente se por acaso pretende utilizar
trechos deste programa para aplicaes profissionais.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
120
Existem vrias formas de representar a associao entre duas classes.
Escolhemos representar a agregao por meio de um array de objetos da classe
Pessoa. Um outra forma, mais fcil de se trabalhar, ser apresentada na seo xx.
A varivel que referencia o array inicializada com null. Toda vez que
inserido um novo objeto o array precisa ser redimensionado. Isto feito pelo
mtodo privado AumentaCapacidade(). Na verdade o mtodo cria um
novo array maior em uma unidade que o anterior. Esta no uma soluo muito
eficiente. O melhor seria incrementar o array em vrias unidades, de modo que o
redimensionamento seria necessrio em intervalos menores. Contudo, o cdigo
necessrio para gerenciar a insero seria bem mais complexo.
O mtodo getPessoa() retorna um objeto com o dado nome igual ao
passado ao mtodo. Se no existir tal objeto retornado null. J o mtodo
getPessoas() retorna uma referencia para array de objetos do tipo Pessoa.
/**
AgendaInt
Interface console da agenda.
*/
import java.io.*;
public class AgendaInt
{
Agenda ag;
BufferedReader in;
// Construtor
public AgendaInt()
{
ag = new Agenda();
in = new BufferedReader(new
InputStreamReader(System.in));
}
// Metodos
/**
Exibirlista
*/
public void Exibirlista()
{
Pessoa p[]=ag.getPessoas();
for (int i= 0; i<p.length; i++)
System.out.println("\nNome:"+p[i].getNome()+"\nTelef
one:"
+p[i].getTel()+"\nEndereo:"+p[i].getEnd()+"\n");
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
121
}
/**
exibirPessoa
*/
public void exibirPessoa()
{
String nome=null;
try {
System.out.println("Entre com o nome:");
nome = in.readLine();
if (nome.length()<1) System.exit(-1);
} catch(IOException e)
{System.out.println(e.getMessage());System.exit(-1);}
Pessoa p = ag.getPessoa(nome);
if (p!=null)
{
System.out.println("\nNome:"+p.getNome()+"\nTelefone:"
+p.getTel()+"\nEndereo:"+p.getEnd());
}
}
/**
obterPessoa
*/
public void obterPessoa()
{
String nome;
String tel;
String end;
try {
System.out.println("Entre com o nome:");
nome = in.readLine();
if (nome.length()<1) System.exit(-1);
System.out.println("\nEntre com o Telefone:");
tel = in.readLine();
System.out.println("\nEntre com o Endereo:");
end = in.readLine();
ag.inserir(new Pessoa(nome ,tel,end));
} catch(IOException e)
{System.out.println(e.getMessage());System.exit(-1);}
}
// main
public static void main(String args[])
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
122
AgendaInt agInt = new AgendaInt();
String opcao="";
for(;;)
{
System.out.println(
"\nAgenda Tabajara\n***********************\n");
System.out.print(
"Opcoes:\n(i)nserir\n(c)onsultar\n(l)istar\n(f)im=>"
);
try {
opcao = agInt.in.readLine();
if (opcao.length()==0) continue;
} catch(IOException e)
{System.out.println(e.getMessage());System.exit(-
1);}
switch(opcao.charAt(0))
{
case 'f': System.exit(0); break;
case 'i': agInt.obterPessoa(); break;
case 'c': agInt.exibirPessoa(); break;
case 'l': agInt.Exibirlista(); break;
}
}
}
}
O mtodo main da classe AgendaInt cria um objeto da prpria classe,
que por sua vez possui um objeto da classe Agenda. A partir de ento o
programa entra em um lao, que aguarda e atende s solicitaes do usurio.
Todos os mtodos da classe recebem e exibem dados por meio dos dispositivos
de E/S padro. Para ler os dados do dispositivo de entrada padro, uma linha por
vez, foi necessrio encapsular o objeto System.in em objetos das classes
BufferedReader e InputStreamReader . No detalharemos aqui o
uso destas classes, que ser abordado no prximo captulo. No momento basta
observarmos que a entrada de dados ser realizada por meio do mtodo
readLine(), que retorna a linha digitada pelo usurio.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
123
Captulo V Entrada e Sada
(java.io)
Acesso Sequencial
As funes de entrada e sada so suportadas por classes agrupadas no
pacote java.io. Todas se baseiam no conceito de stream de bytes (corrente ou
sequncia), onde a entrada/sada um duto onde se retira/coloca cada byte
como em uma fila do tipo First in-first out. A figura V.1 ilustra este tipo de
enfoque.
Figura V.1 Stream de bytes.
O produtor e o consumidor podem se selecionados de uma ampla
variedade que vai desde arquivos e portas de protocolos TCP/IP at arranjos
(arrays) de bytes e Strings. De modo a pode lidar com essa ampla variedade de
fontes/consumidores de dados e prover todo o tipo de facilidade de leitura o
pacote java.io possui um conjunto razoavelmente grande classes. Essas
classes so combinadas, formando camadas, onde as classes das camadas
inferiores fornecem servios bsicos como leitura/escrita de um byte, enquanto
que as classes superiores fornecem servios de leitura/escrita mais sofisticados,
como leitura de linha, leitura de um tipo float, etc. A figura V.2 mostra este tipo
de combinao.
C Ca am ma ad da a n n
C Ca am ma ad da a 1
C Cl l a as ss se e I I/ /O O
B B s si i c ca a
N N v ve el l
d do os s
s se er rv vi i o os s
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
124
Figura V.2 Organizao das classes de I/O.
Para complicar um pouco mais a situao, a linguagem J ava Possui dois
conjuntos distintos de classes para I/O. Um originado da verso 1.0 e outro
introduzido na verso 1.1. A razo para isso que as classes projetadas na
verso 1.0 so orientadas para bytes e portanto no so adequadas para lidar
cdigos Unicodes que utilizam dois bytes. A verso 1.2 no introduziu grandes
modificaes, realizando apenas um aperfeioamento na java.io.File e
algumas mudanas na assinatura de alguns mtodos . O leitor deve ento estar
pensando que basta ento utilizar o novo conjunto de classes e esquecer do
antigo, porm a coisa no to simples assim. Primeiramente, importante
conhecer o conjunto antigo de classes uma vez que existe um grande nmero de
programas escrito na verso 1.0 e o leitor pode se ver obrigado a ler ou dar
manuteno no cdigo destes programas. Em segundo lugar, algumas vezes ser
preciso combinar as funes antigas com as novas para obter algum tipo de
funcionalidade. E em terceiro lugar a Sun adicionou novas facilidades ao
conjunto antigo na verso 1.1, dando sinais que no pretende simplesmente
abandon-lo. Tudo isto faz com que o tratamento de entrada e sada em J ava no
seja algo muito simples de se dominar. As figuras V.3 e V.4 apresentam
diagramas que mostram algumas das camadas dos dois conjuntos de classes, de
modo que o leitor possa ter uma idia da sua equivalncia, embora nem sempre
uma classe de um conjunto possua uma classe correspondente em outro
conjunto.
Figura V.3 Comparao entre as classes de entrada.
S St tr ri in ng gB Bu uf ff fe er rI In np pu ut tS St tr re ea am m
B By yt te eA Ar rr ra ay yI In np pu ut tS St tr re ea am m
P Pi ip pe ed dI In np pu ut tS St tr re ea am m
F Fi il le eI In np pu ut tS St tr re ea am m
I In np pu ut tS St tr re ea am m
i in nt ts s
f fl lo oa at ts s
S St tr ri in ng g
e et tc c. .
b by yt te es s
F Fi il lt te er rI In np pu ut tS St tr re ea am m
D Da at ta aI In np pu ut tS St tr re ea am m
B Bu uf ff fe er re ed dI In np pu ut tS St tr re ea am m
L Li in ne eN Nu um mb be er rI In np pu ut tS St tr re ea am m
i in nt ts s
f fl lo oa at ts s
S St tr ri in ng g
e et tc c. .
c ca ar ra ac ct te er re e
P Pi ip pe ed dR Re ea ad de er r
C Ch ha ar rA Ar rr ra ay yR Re ea ad de er r
S St tr ri in ng gR Re ea ad de er r
F Fi il le eR Re ea ad de er r
R Re ea ad de er r
F Fi il lt te er rR Re ea ad de er r
B Bu uf ff fe er re ed dR Re ea ad de er r
L Li in ne eN Nu um mb be er rR Re ea ad de er r
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
125
Figura V.4 Comparao entre as classes de sada.
Note que no existe uma equivalncia perfeita entre os dois conjuntos,
nem entre o par entrada/sada em um mesmo conjunto. Por exemplo, a classe
StringBufferedInputStream no possui uma classe equivalente
StringBufferedOutputStream nem a DataInputStream possui uma
equivalente DataWriter. Esta uma das razes para o uso combinado dos dois
conjuntos. Para realizar a converso entre os dois conjuntos so fornecidas as
classes InputStreamReader e OutputStreamWriter.
As funes bsicas so tratadas pelas classes abstratas bsicas
InputStream e OutputStream. Para as funes de entrada e sada com Buffers
so utilizadas as classes BufferedInputStream, BufferedOutputStream,
BufferedReader e BufferedWriter. O tamanho padro do buffer de 2048
bytes. A traduo entre InputStream, OutputStream e BufferedReader,
BufferedWriter feita por InputStreamReader e OutputStreamWriter. Para
IO em arquivos podem ser utilizadas classes de baixo nvel: FileInputStream,
FileOutputStream, FileReader e FileWriter.
De modo a possibilitar a comparao e o entendimento do uso dos dois
conjuntos os exemplos abaixo mostram a mesma funo implementada com
cada grupo de classes.
a) Streams b) I/O 1.1
import java.io.*;
class TesteIO101
import java.io.*;
class TesteIO111
B By yt te eA Ar rr ra ay yO Ou ut tp pu ut tS St tr re ea am m
P Pi ip pe ed dO Ou ut tp pu ut tS St tr re ea am m
F Fi il le eO Ou ut tp pu ut tS St tr re ea am m
O Ou ut tp pu ut tS St tr re ea am m
i in nt ts s
f fl lo oa at ts s
S St tr ri in ng gs s
e et tc c. .
b by yt te es s
F Fi il lt te er rO Ou ut tp pu ut tS St tr re ea am m
P Pr ri in nt tS St tr re ea am m
D Da at ta aI In np pu ut tS St tr re ea am m
B Bu uf ff fe er re ed dO Ou ut tp pu ut tS St tr re ea am m
i in nt ts s
f fl lo oa at ts s
S St tr ri in ng gs s
e et tc c. .
c ca ar ra ac ct te er re e
P Pi ip pe ed dW Wr ri it te er r
C Ch ha ar rA Ar rr ra ay yW Wr ri it te er r
S St tr ri in ng gW Wr ri it te er r
F Fi il le eW Wr ri it te er r
W Wr ri it te er r
F Fi il lt te er rW Wr ri it te er r
B Bu uf ff fe er re ed dW Wr ri it te er r
P Pr ri in nt tW Wr ri it te er r
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
126
{
public static void main(String a[])
{
try
{
DataInputStream in =
new DataInputStream(
new BufferedInputStream(
new FileInputStream(a[0])));
String str;
while((str = in.readLine())!= null)
System.out.println(str);
} catch(IOException e)
{ System.out.println(e.getMessage());}
}
}
{
public static void main(String a[])
{
try
{
BufferedReader in =
new BufferedReader(
new FileReader(a[0]));
String str;
while((str = in.readLine())!= null)
System.out.println(str);
} catch(IOException e)
{System.out.println(e.getMessage());}
}
}
Exemplo V.1 Leitura no formatada de arquivos.
O exemplo V.1 mostra a leitura de um arquivo passado pela linha de
comando feita (a) por meio de stream e (b) por meio de reader. Em ambos os
casos a leitura utiliza buffers, de modo a otimizar os acessos a disco. No caso
(b) basta utilizar um objeto da classe BufferedReader, uma vez que a leitura
no formatada, com o uso do mtodo readLine(). J no caso (a), preciso
envolver o objeto da classe BufferedInputStream em um objeto da
classe DataInputStream, apesar de no ser uma leitura formatada, uma vez
que o mtodo readLine() pertence classe DataInputStream. Mesmo
assim o programa receber a mensagem
The method java.lang.String readLine() in class
java.io.DataInputStream has been deprecated.
significando que o mtodo readLine() est sendo descontinuado para a classe
DataInputStream, tendendo a desaparecer nas prximas verses.
a) Streams b) I/O 1.1
import java.io.*;
class TesteIO102
{
public static void main(String a[])
{
try
{
PrintStream out = new PrintStream(
new BufferedOutputStream(
new FileOutputStream("saida.out")));
out.println("Linha de teste 1");
import java.io.*;
class TesteIO112
{
public static void main(String a[])
{
try
{
PrintWriter out = new PrintWriter(
new BufferedWriter(
new FileWriter("saida.out")));
out.println("Linha de teste 1");
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
127
out.println("Linha de teste 2");
out.close();
}catch(IOException e) {
System.out.println(e.getMessage());}
}
}
out.println("Linha de teste 2");
out.close();
}catch(IOException e) {
System.out.println(e.getMessage());}
}
}
Exemplo V.2 Escrita no formatada em arquivos.
a) Streams
import java.io.*;
class TesteIO103
{
public static void main(String a[])
{
try
{
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("a.out")));
out.writeBytes("O valor de pi: \n");
out.writeDouble(3.14159);
out.close();
DataInputStream in = new DataInputStream(
new FileInputStream("a.out"));
System.out.println(in.readLine());
System.out.println(in.readDouble());
}catch(IOException e) {System.out.println(e.getMessage());}
}
}
Exemplo V.3 Escrita e leitura formatada em arquivos..
A leitura/escrita formatada utiliza as classes DataInputStream e
DataOutputStream. Como no existem as correspondentes DataReader
e DataWriter, somos obrigados a usar o conjunto antigo de classes para
realizar a leitura e escrita formatada.
Os dispositivos de entrada e sada padres (equivalentes na linguagem
C++a cin, cout e cerr), so mantidos pela por variveis estticas da classe
System, referenciadas por System.in, System.out e System.error.
Como essas variveis referenciam a objetos das classes InputStream e
OutputStream, se desejarmos manipular os dispositivos de E/S padres com
o conjunto de classes novos devemos utilizar as classes tradutoras
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
128
InputStreamReader e OutputStreamWriter, como mostrado no
exemplo V.4.
import java.io.*;
class TesteIO114
{
public static void main(String a[])
{
try
{
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("Entre uma linha:");
System.out.println(in.readLine());
}catch(IOException e)
{System.out.println(e.getMessage());}
}
}
Exemplo V.4 Leitura e Escrita nos dispositivos de sada e entrada padres.
Acesso Direto
At agora lidamos com dispositivos de entrada e sada que tratam
sequncia de bytes ou caracteres (streams). No entanto, alguns dispositivos
como disco rgido e CDs permitem o acesso direto um byte sem a necessidade
de ler todos os outros bytes posicionados antes. Este tipo de acesso chamado
de acesso direto e J ava permite este tipo acesso a arquivos armazenados em
dispositivos que suportam o acesso direto por meio da classe
RandomAccessFile. Esta classes no pertence a nenhuma das hierarquias
apresentadas anteriormente uma vez que no acessa os dados na forma de
sequncia. A nica semelhana com as outras hierarquias o fato de
implementar as interfaces InputStream e OutputStream. De fato, a classe
RandomAccessFile torna muito conveniente o acesso a arquivos por
implementar simultaneamente as duas interfaces, permitindo desta forma tanto a
leitura quanto a escrita no arquivo. Os construtores da classe so os seguintes:
public RandomAccessFile(File file, String mode)
throws IOException
public RandomAccessFile(String name, String mode)
throws IOException
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
129
O primeiro construtor recebe um objeto da classe File e um objeto da
classe String especificando o modo de acesso do arquivo. O acesso direto ser
feito sobre o objeto da classe Files. Os modos acesso possveis so: modo de
leitura, especificado pela String r e modo de leitura e escrita, especificado
pela String rw. O segundo construtor recebe um objeto da classe String
contendo o nome do arquivo e outro objeto da classe String especificando o
modo de acesso do arquivo. Ambos os construtores lanam a exceo
IOException.
A maioria dos mtodos implementados por RandomAccessFile so
implementados pela classe FileInputStream ou pela classe
FileOutputStream, uma vez que ela lida tanto com leitura como sada,
porm, a classe RandomAccessFile possui alguns mtodos adicionais que
permitem definir a posio corrente no arquivo e estabelecer onde ser
lido/escrito o prximo dado. A tabela V.1 mostra os mtodos da classe
RandomAccessFile.
Mtodo Descrio
close()
Fecha o arquivo.
getFD()
Retorna o descritor arquivo objeto associado com
este stream.
getFilePointer()
Retorna a posio corrente neste arquivo.
length()
Retorna o tamanho deste arquivo.
read(byte[] b, int
off, int len)
L at len bytes em um array de bytes.
read()
L um byte.
read(byte[] b)
L at to b.length bytes em um array de bytes.
readBoolean()
L um boolean.
readByte()
L um um byte.
readChar()
L um caracter Unicode.
readDouble()
L um double.
readFloat()
L um float.
readFully(byte[] b,
int off, int len)
L exatamente len bytes no array byte.
readFully(byte[] b)
L b.length bytes no array byte.
readInt()
L um inteiro de 32-bit com sinal.
readLine()
L a prxima linha de texto.
readLong()
L um inteiro com sinal de 64-bits.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
130
readShort()
L um inteiro com sinal de 16-bits.
readUnsignedByte()
L um inteiro sem sinal de 8-bits.
readUnsignedShort()
L um inteiro sem sinal de 16-bits.
readUTF()
L um String usando a codificao UTF-8.
seek(long pos)
Define pos como a posio em bytes no arquivo
onde ser feita a prxima leitura/escrita.
skipBytes(int n)
Salta exatamente n bytes.
write(int b)
Escreve um byte.
write(byte[] b, int
off, int len)
Escreve len bytes do array iniciando em off.
write(byte[] b)
Escreve b.length bytes do array.
writeBoolean(boolean
v)
Escreve um boolean como um valor 1-byte.
writeByte(int v)
Escreve um byte como um valor 1-byte.
writeBytes(String s)
Escreve uma String como uma sequncia de
bytes.
writeChar(int v)
Escreve um caractere como um valor 2-byte, byte
alto primeiro.
writeChars(String s)
Escreve uma String como uma sequncia de
caracteres.
writeDouble(double
v)
Escreve um double como um valor de 8-bytes.
writeFloat(float v)
Escreve um float como um valor de 4-bytes.
writeInt(int v)
Escreve um inteiro como quatro bytes.
writeLong(long v)
Escreve um long como oito bytes.
writeShort(int v)
Escreve um short como dois bytes.
writeUTF(String str)
Escreve uma String usando a codificao UTF-8.
Tabela V.1 Mtodos pblicos da classe RandomAccessFile.
O Exemplo V.5 mostra o uso da classe RandomAccessFile para
acessar o byte no meio do arquivo.
import java.io.*;
class RandomTeste
{
public static void main (String args[])
{
if (args.length ==0)
{
System.err.println("Fornea o nome do arquivo!");
System.exit(0);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
131
}
try
{
RandomAccessFile f = new RandomAccessFile(args[0], "r");
long tam = f.length();
if (tam==0)
{
System.out.println("Arquivo vazio!");
}
else
{
f.seek(tam>>1);
System.out.println("O byte no meio : "+f.read());
}
} catch (Exception e) {
System.out.println("Erro: " + e.toString());
}
}
Exemplo V.1 Uso da classe RandomAccessFile.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
132
Captulo VI java.util
O pacote java.util rene um conjunto interessante de classes e
interfaces teis ao desenvolvimento de aplicaes. Contm recursos para lidar
com colees, data e hora, internacionalizao, arrays de bits, tokenizao de
cadeias de caracteres e etc. Nesta seo abordaremos as classes e interfaces mais
utilizadas.
Lidando com Colees
Antigamente, era muito comum que, durante o desenvolvimento de um
sistema, os programadores tivessem a necessidade de implementar uma estrutura
de dados como uma lista, pilha ou tabela hash para agrupar e gerenciar um
conjunto de elementos. Como as primeiras linguagens de programao no
possuam recursos para que se implementasse estas estruturas de forma genrica,
de modo que pudessem ser usadas independentemente do tipo dos elementos, o
programador era obrigado a implementar deste o incio toda a estrutura para
cada novo tipo de elemento.
Com as linguagens de programao mais recentes este quadro mudou. As
novas linguagens permitem que o programador implemente estruturas de dados
genricas, independentes de tipos. Alm disso, a maioria delas j implementam,
embutidas na linguagem ou na forma de bibliotecas, as estruturas de dados mais
comuns. Este o caso da linguagem J ava que possui, dentro do pacote
java.util classes e interfaces que implementam estruturas de dados como
listas (List), arrays crescentes (Vector), pilhas (Stack), tabela hash
(Hashtable) e etc. O pacote possui tambm interfaces para percorrer os
elementos das estruturas (Iterator e Enumeration). Apresentaremos aqui
apenas as classes e interfaces mais usadas.
As Interfaces Iterator e Enumeration
As interfaces Iterator e Enumeration so usadas na criao de
objetos que tem por objetivo percorrer sequencialmente os elementos de uma
coleo. Como ambas as interfaces possuem o mesmo objetivo o leitor deve
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
133
estar se perguntando sobre necessidade de existirem duas interfaces. O fato que
at a verso 1.1 da linguagem J ava existia apenas a interface Enumeration.
No entanto, como o nome deste tipo de objeto na comunidade de Engenharia de
Software iterator a Sun aproveitou para incluir uma interface com este nome
na verso 1.2 e fazer algumas pequenas modificaes.
O mtodos que devem ser implementados em cada interface so
semelhantes e esto descritos nas tabelas VI.1 e VI.2.
Mtodo Descrio
boolean hasMoreElements()
Testa se Enumeration possui mais elementos.
Object nextElement()
Retorna o prximo elemento da Enumeration.
Tabela VI.1 Mtodos da interface Enumeration.
Mtodo Descrio
boolean hasNext()
Testa se Iterator possui um prximo elemento.
Object next()
Retorna o prximo elemento do Iterator.
void remove() Remove da coleo associada o ltimo elemento
retornado pelo Iterator.
Tabela VI.2 Mtodos da interface Iterator.
Um objeto que implementa a interface Enumeration retornado por
alguma classe que implementa uma estrutura de dados sempre que invocamos o
mtodo elements() da classe. Por exemplo, suponha que desejamos imprimir
os elementos reunidos por um objeto v da classe Vector. O trecho de cdigo
para cumprir essa tarefa poderia ter a seguinte forma:
for (Enumeration e = v.elements() ; e.hasMoreElements() ;)
{
System.out.println(e.nextElement());
}
J no caso da interface preciso usar o mtodo iterator() herdado
por toda subclasse da interface Collection. Neste caso o trecho de cdigo
para cumprir essa tarefa poderia ter a seguinte forma:
for (Iterator it = v.iterator() ; it.hasNext() ;)
{
System.out.println(it.next());
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
134
}
Vector
public class Vector
extends AbstractList
implements List, Cloneable, Serializable
A classe Vector implementa um array dinmico. Ou seja, um array que
cresce ou diminui a medida da necessidade. O uso de objetos classe Vector
indicado para situaes onde o programador precisa manter uma lista de
elementos mas no sabe, a priori, o nmero de elementos que pertencero lista
ou o nmero de elementos da lista ir variar durante o processamento.
Hierarquia
java.lang.Object
|
+--java.util.AbstractCollection
|
+--java.util.AbstractList
|
+--java.util.Vector
Construtores
Construtor Descrio
public Vector()
Constri um Vector vazio com espao inicial
para 10 elementos e incremento 0.
public Vector(Collection c)
Constri um Vector contendo os elementos do
objeto do tipo Collection.
public Vector(int iniCapac)
Constri um Vector vazio com espao inicial
para iniCapac elementos e incremento 0.
public Vector(int iniCapac,
int inc)
Constri um Vector vazio com espao inicial
para iniCapac elementos e incremento inc.
Tabela VI.3 Construtores da classe Vector.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
135
Atributos
Atributo Descrio
protected int capacityIncrement Quantidade que incrementada
capacidade do Vector toda vez que o
tamanho se torna maior que a capacidade.
protected int elementCount Nmero de elementos referenciados
protected Object[] elementData Array onde so armazenadas as referencias
aos elementos.
Tabela VI.4 Atributos pblicos da classe Vector.
Mtodos
Devido ao grande nmero de mtodos da classe Vector mostraremos
apenas os mais usados.
Mtodo Descrio
void add(int i, Object o)
Adiciona um elemento na posio indicada por i.
public boolean add(Object
o)
Adiciona um elemento no final do Vector.
public boolean
addAll (Collection c)
Adiciona todos os elementos da coleo especificada
no final do Vector.
public void
addElement(Object o)
Adiciona um elemento no final do Vector.
public int capacity() Retorna a capacidade atual.
public void clear()
Remove todos os elementos do Vector.
public Object clone()
Retorna um clone do Vector.
public boolean
contains(Object o)
Testa se o objeto um elemento do Vector.
public boolean
containsAll(Collection c)
Retorna true se o Vector contm todos os
elementos referenciados por c.
public void
copyInto (Object[] a)
Copia os elementos do Vector no array.
public Object
elementAt(int i)
Retorna o elemento na posio i.
public Enumeration
elements()
Retorna um objeto do tipo Enumeration que
permite percorrer os elementos do Vector.
public void
ensureCapacity(int min)
Aumenta a capacidade do Vector para o valor min.
public boolean
equals(Object o)
Compara se o igual ao Vector. Retorna true
somente se o objeto tambm do tipo List, possui o
mesmo tamanho e referencia os mesmos elementos na
mesma ordem.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
136
public Object
firstElement()
Retorna o primeiro elemento.
public Object get(int i)
Retorna o elemento da posio i.
public int
indexOf(Object o)
Retorna a posio da primeira ocorrncia de o. O
mtodo equals() do objeto usado para o teste de
igualdade.
public int indexOf(Object
o,int i)
Retorna a posio da primeira ocorrncia de o a partir
de i. O mtodo equals() do objeto usado para o
teste de igualdade.
public void
insertElementAt(Object o,
int i)
Insere o objeto o na posio i.
public boolean isEmpty()
Testa se o Vector est vazio.
public Object
lastElement()
Retorna o ltimo elemento.
public int
lastIndexOf(Object o)
Retorna a posio da ltima ocorrncia de o. O
mtodo equals() do objeto usado para o teste de
igualdade.
public Object remove(int
i)
Remove o elemento da posio i.
public boolean
removeAll(Collection c)
Remove todos os elementos que tambm pertencem
Collection.
public void
removeAllElements()
Remove todos os elementos.
public void
removeElementAt(int i)
Remove o elemento da posio i.
public boolean
retainAll(Collection c)
Mantm apenas os elementos que tambm pertencem
Collection.
public Object set(int i,
Object o)
Substitui o objeto na posio i pelo objeto o.
public void setSize(int
s)
Define o tamanho do Vector.
public int size()
Retorna o tamanho do Vector.
public List subList(int
i, int f)
Retorna uma parte dos elementos do Vector entre
fromIndex, inclusive, e toIndex, exclusive.
public Object[] toArray() Retorna um array contendo todos os elementos no
Vector na ordem correta.
public String toString() Retorna uma representao na forma de String do
Vector.
Tabela VI.5 Mtodos da classe Vector.
Exemplo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
137
O exemplo a seguir mostra a insero das strings passadas pela linha de
comando em um objeto da classe Vector. Os elementos do objeto Vector
podem ser exibidos na tela invocando o mtodo print().
import java.util.*;
public class TesteVector
{
Vector v;
public TesteVector(String a[])
{
v = new Vector(a.length);
v.copyInto(a);
}
public void print()
{
for (Iterator it = v.iterator(); it.hasNext() ;)
{
System.out.println((String)it.next());
}
}
public static void main(String args[])
{
TesteVector teste = new TesteVector(args);
teste.print();
}
}
Exemplo VI.xx Uso do Vector.
Stack
public class Stack
extends Vector
A classe Stack implementa a estrutura de dados pilha. Ou seja, uma
estrutura de dados que segue a regra LIFO (last-in-first-out ltimo a entrar,
primeiro a sair). Esta regra impe define uma lista que acessada apenas por
uma extremidade, de modo que o ltimo elemento a ser inserido na pilha tenha
que ser o primeiro elemento a sair.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
138
Hierarquia
java.lang.Object
|
+--java.util.AbstractCollection
|
+--java.util.AbstractList
|
+--java.util.Vector
|
+--java.util.Stack
Construtor
Construtor Descrio
public Stack()
Constri um Stack vazio.
Tabela VI.6 Construtor da classe Stack.
Mtodos
Mtodo Descrio
public boolean empty()
Testa se a Stack est vazia.
public Object peek() Retorna uma referncia para o elemento no topo da
Stack sem retir-lo.
public Object pop() Retorna uma referncia para o elemento no topo da
Stack e o retira.
public Object
push(Object o)
Insere o objeto o no topo da Stack.
public int
search(Object o)
Retorna a distncia do topo da pilha da primeira
ocorrncia de o. O elemento no topo da pilha possui a
distncia 1. O mtodo equals() do objeto usado
para o teste de igualdade.
Tabela VI.5 Mtodos da classe Stack.
Exemplo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
139
O exemplo a seguir mostra a insero das strings passadas pela linha de
comando em um objeto da classe Stack. Os elementos do objeto Stack
podem ser exibidos na tela invocando o mtodo print().
import java.util.*;
public class TesteStack
{
Stack s;
public TesteStack(String a[])
{
s = new Stack();
for (int i=0; i<a.length; i++)
s.push(a);
}
public void desempilha ()
{
String aux = (String)s.pop();
while (aux !=null)
{
System.out.println(aux);
}
}
public static void main(String args[])
{
TesteStack teste = new TesteStack(args);
teste.desempilha();
}
}
Exemplo VI.xx Uso do Stack.
Hashtable
public class Hashtable
extends Dictionary
implements Map, Cloneable, Serializable
A classe Hashtable implementa uma estrutura de dados conhecida
como tabela hash. Neste tipo de estrutura todo elemento armazenado possui uma
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
140
chave que permite recuperar diretamente o elemento, sem a necessidade de ir
examinando cada elemento armazenado at encontrar o elemento desejado,
como seria o caso em uma lista. Cada chave identifica apenas um elemento.
Existem vrios bons livros sobre estruturas de dados nas livrarias que o leitor
pode consultar para se aprofundar no tema.
Hierarquia
java.lang.Object
|
+--java.util.Dictionary
|
+--java.util.Hashtable
Construtores
Construtor Descrio
public Hashtable()
Constri um Hashtable vazio com fator de
carga 0,75.
public Hashtable(int capac)
Constri um Hashtable com capacidade
inicial capac e com fator de carga 0,75.
public Hashtable(int capac,
float fatCarga)
Constri um Hashtable com capacidade
inicial capac e com fator de carga fatCarga.
public Hashtable(Map m)
Constri um Hashtable com os elementos de
m.
Tabela VI.xx Construtores da classe Hashtable.
Mtodos
Devido ao grande nmero de mtodos da classe Hashtable mostraremos
apenas os mais usados.
Mtodo Descrio
public void clear()
Remove todos os elementos do Hashtable.
public Object clone()
Retorna um clone raso do Hashtable.
public boolean
contains(Object o)
Testa se o objeto acessado por alguma chave do
Hashtable.
public boolean
containsKey(Object o)
Testa se o objeto chave no Hashtable.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
141
public boolean
containsValue(Object o)
Testa se o objeto acessado por alguma chave do
Hashtable.
public Enumeration
elements()
Retorna um objeto do tipo Enumeration que
permite percorrer os elementos do Hashtable.
public Set entrySet()
Retorna um Set contendo os elementos do
Hashtable.
public boolean
equals(Object o)
Compara se o igual ao Hashtable. Retorna true
somente se o objeto tambm do tipo Map e faz o
mesmo mapeamento.
public Object get(Object
key)
Retorna o elemento da posio mapeado pela chave
key.
public boolean isEmpty()
Testa se o Hashtable est vazio.
public Enumeration keys()
Retorna um objeto do tipo Enumeration que
permite percorrer as chaves do Hashtable.
public Set keySet()
Retorna um Set contendo as chaves do Hashtable.
public Object put(Object
key,Object o)
Insere o objeto o no Hashtable tendo como chave
key.
protected void rehash()
Reorganiza internamente o Hashtable para acessar
e acomodar os elementos mais eficientemente.
public Object
remove(Object key)
Remove o elemento que tem como chave key.
public int size()
Retorna o nmero de chaves do Hashtable.
public String toString() Retorna uma representao na forma de String do
Hashtable.
public Collection
values()
Retorna um Collection contendo os elementos do
Hashtable.
Tabela VI.xx Mtodos da classe Hashtable.
Exemplos
O exemplo a seguir mostra a insero das objetos da classe Integer em
um objeto Hashtable. A chave usada para cada objeto o nmero por
extenso.
Hashtable numbers = new Hashtable();
numbers.put("one", new Integer(1));
numbers.put("two", new Integer(2));
numbers.put("three", new Integer(3));
...
Integer n = (Integer)numbers.get("two");
if (n != null) {
System.out.println("two = " + n);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
142
}
...
for (Enumeration e = numbers.elements();e.hasMoreElements();){
Integer i = (Integer)e.nextElement()
System.out.println( i.toString());
}
Exemplo VI.xx Uso do Hashtable.
O exemplo a seguir mostra a insero das objetos da classe Pessoa em
um objeto Hashtable. A chave usada para cada objeto o nome da pessoa.
class pessoa {
String nome;
String tel;
public pessoa(String nome, String tel)
{this.nome = nome; this.tel = tel;}
public String getNome(){return nome;}
public String getTel(){return tel;}
}
...
Hashtable pessoas = new Hashtable();
...
pessoa P1 = new pessoa("Pedro", "899-1313");
pessoas.put(P1.getNome(), P1);
...
pessoa P2 =(pessoa) pessoas.get("Pedro");
if (P2!=null) System.out.println
("Nome:"+P2.getNome(), "\nTel:"+P2.getTel());
Exemplo VI.xx Uso do Hashtable.
Miscelnea de Classes do pacote java.util
Arrays
public class Arrays
extends Object
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
143
Esta classe foi inserida no pacote java.util a partir da verso 1.2 do
SDK. uma classe utilitria, fornecendo mtodos de ordenao e busca em
arrays.
Hierarquia
java.lang.Object
|
+--java.util.Arrays
Mtodos
Mtodo Descrio
public static List asList(Object[] a)
Retorna uma List criada a partir do array.
public static int
binarySearch(byte[] a, byte key)
public static int
binarySearch(char[] a, char key)
public static int
binarySearch(double[] a, double key)
public static int
binarySearch(float[] a, float key)
public static int
binarySearch(int[] a, int key)
public static int
binarySearch(long[] a, long key)
public static int
binarySearch(Object[] a, Object key)
public static int
binarySearch(short[] a, short key)
Realiza uma pesquisa binria retornando a
posio de key no array.
public static int
binarySearch(Object[] a, Object key,
Comparator c)
Realiza uma pesquisa binria retornando a
posio de key no array. O array tem que
estar ordenado ascendentemente de acordo
com o Comparator.
public static boolean
equals(boolean[] a, boolean[] a2)
public static boolean
equals(byte[] a, byte[] a2)
public static boolean
equals(char[] a, char[] a2)
public static boolean
equals(double[] a, double[] a2)
public static boolean
equals(float[] a, float[] a2)
public static boolean
equals(int[] a, int[] a2)
public static boolean
equals(long[] a, long[] a2)
public static boolean
equals(Object[] a, Object[] a2)
Retorna true se os dois arrays so iguais.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
144
public static boolean
equals(short[] a, short[] a2)
public static void
fill(boolean[] a, boolean val)
public static void
fill(byte[] a, byte val)
public static void
fill(double[] a, double val)
public static void
fill(float[] a, float val)
public static void
fill(int[] a, int val)
public static void
fill(long[] a, long val)
public static void
fill(Object[] a, Object val)
public static void
fill(short[] a, short val)
Preenche o array com o valor especificado.
public static void fill(boolean[] a,
int ini, int fim, boolean val)
public static void fill(byte[] a,
int ini, int fim, byte val)
public static void fill(double[] a,
int ini, int fim, double val)
public static void fill(float[] a,
int ini, int fim, float val)
public static void fill(int[] a,
int ini, int fim, int val)
public static void fill(long[] a,
int ini, int fim, long val)
public static void fill(Object[] a,
int ini, int fim, Object val)
public static void fill(short[] a,
int ini, int fim, short val)
Preenche o array com o valor especificado a
partir do elemento de ndice ini inclusive
at o elemento de ndice fim exclusive.
public static void sort(byte[] a)
public static void sort(double[] a)
public static void sort(float[] a)
public static void sort(int[] a)
public static void sort(long[] a)
public static void sort(Object[] a)
public static void sort(short[] a)
Ordena o array em ordem ascendente.
public static void
sort(byte[] a, int ini, int fim)
public static void
sort(double[] a, int ini, int fim)
public static void
sort(float[] a, int ini, int fim)
public static void
sort(int[] a, int ini, int fim)
public static void
sort(long[] a, int ini, int fim)
public static void
sort(Object[] a, int ini, int fim)
public static void
sort(short[] a, int ini, int fim)
Ordena o array em ordem ascendente a
partir do elemento de ndice ini inclusive
at o elemento de ndice fim exclusive.
public static void sort(Object[] a,
Comparator c)
Ordena o array em ordem ascendente
definida pelo objeto Comparator.
public static void sort(Object[] a,
int ini, int fim, Comparator c)
Ordena o array em ordem ascendente
definida pelo objeto Comparator a
partir do elemento de ndice ini inclusive
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
145
at o elemento de ndice fim exclusive.
Tabela VI.5 Mtodos da classe Arrays.
O algoritmo de ordenao
O algoritmo de ordenao uma variao quicksort apresentado por J on L. Bentley e
M. Douglas McIlroy's "Engineering a Sort Function", Software-Practice and Experience, Vol.
23(11) P. 1249-1265 (November 1993). Este algoritmo possui complexidade n*log(n) em
conjunto de dados que causariam a degradao de outros algoritmos de quicksort para um
desempenho de ordem quadrtica.
Exemplo
O exemplo a seguir mostra a impresso ordenada das strings passadas
pela linha de comando.
import java.util.arrays;
class TestArrays
{
public static void main(String a[])
{
if(a.length>0)
{
Arrays.sort(a);
for(int i=0;i<a.length; i++) System.out.println(a[i]);
}
}
}
Exemplo VI.xx Uso do Arrays.
Date
public class Date
extends Object
implements Serializable, Cloneable, Comparable
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
146
Esta classe responsvel pela representao da data com preciso de
milisegundos. Antes da verso 1.1 do SDK a classe Date tambm tinha as
funes de formatao e anlise de datas no tipo String assim como de
interpretar as datas em anos, meses, dias, horas, minutos e segundos. Devido
complexidade da internacionalizao estas funes foram transferidas para as
classes DateFormat e Calendar. O mtodos da classe Date que realizavam
essas funes tornaram-se deprecated. A data base padro, a partir da qual so
contados os milisegundos 01/01/1970, 00:00:00 GMT.
Hierarquia
java.lang.Object
|
+--java.util.Date
Construtores
Os construtores deprecated no esto listados.
Construtor Descrio
public Date()
Constri um Date representando a data do momento de
sua alocao.
public Date(long data)
Constri um Date contendo a data calculada a partir
nmero de millisegundos representados por data tendo
como base a data 01/01/1970, 00:00:00 GMT.
Tabela VI.xx Construtores da classe Date.
Mtodos
Os mtodos deprecated no esto listados.
Mtodo Descrio
public boolean after(Date d) Testa se a data anterior data passada como
argumento.
public boolean before(Date d) Testa se a data posterior data passada
como argumento.
public Object clone() Cria um clone do objeto.
public int compareTo(Date d) Compara duas datas. Retorna 0 se as duas
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
147
datas so iguais. Retorna um valor maior que
0 se a data passada como argumento menor
e um valor menor que 0 se data passada como
argumento e maior.
public boolean equals(Object o)
Retorna true se duas datas so iguais.
public long getTime() Retorna o nmero de milisegundos desde
01/01/1970, 00:00:00 GMT at a data
representada pelo objeto corrente.
public void setTime(long time) Define a data desde objeto usando o nmero
de milisegundos desde 01/01/1970, 00:00:00
GMT passado como argumento.
Tabela VI.5 Mtodos da classe Date.
Exemplo
O exemplo a seguir exibe a representao da data corrente em
milisegundos.
import java.util.Date;
class TestDate
{
public static void main(String a[])
{
System.out.println(new Date().getTime());
}
}
Exemplo VI.xx Uso da classe Date.
Observable
public class Observable
extends Object
A classe Observable permite criar objetos observveis. Objeto
observvel um objeto que, quando sofre alguma alterao, notifica outros
objetos, chamados de observadores. Os objetos observveis e observadores
fazem parte do padro de projeto conhecido como MVC (ModeloViso
Controle) introduzido na linguagem Smalltalk. A utilizao deste padro de
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
148
projeto facilita a implementao programas onde um modelo possui vrias
vises que devem ser atualizadas toda vez que o modelo muda. O controle atua
sobre o modelo, ocasionando alteraes. Por exemplo, suponha que modelo que
armazene os valores de aes da bolsa. Podemos exibir vrias vises desses
dados, como grficos de barras e em forma de pizza. Os controladores
modificariam o modelo que em seguida notificaria as vises para refletirem o
estado atual do modelo. As figuras VI.XX e VI.XX ilustram esquematicamente
o padro MVC. Na linguagem J ava, para um objeto ser um observador preciso
implementar a interface Observer.
Figura VI.XX Esquema do padro MVC.
Observvel
Figura VI.XX Duas formas de visualizao de um modelo.
Viso
Viso
Modelo
Controle
Controle
a b
x 30 45
window X window X
a b
a=30;
b=45;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
149
Hierarquia
java.lang.Object
|
+--java.util.Observable
Construtor
Construtor Descrio
public Observable()
Constri um Observable possuindo zero
observadores.
Tabela VI.XX Construtor da classe Observable.
Mtodos
Mtodo Descrio
public void
addObserver(Observer o)
Adiciona um observador ao conjunto de
observadores do objeto.
protected void clearChanged() Limpa a indicao de que o objeto mudou.
public int countObservers() Retorna o nmero de objetos observadores
deste objeto.
public void
deleteObserver(Observer o)
Remove o objeto passado como argumento
do conjunto de objetos observadores.
public void deleteObservers() Remove todos os objetos observadores do
conjunto de objetos observadores.
public boolean hasChanged() Retorna true se o objeto sofreu uma mudana.
public void notifyObservers()
Se o mtodo hasChanged() retornar
true notifica todos os objetos observadores
e chama o mtodo clearChanged().
public void
notifyObservers(Object arg)
Se o mtodo hasChanged() retornar
true notifica todos os objetos observadores
e chama o mtodo clearChanged(). O
objeto arg passado como argumento para o
mtodo update() do observador.
protected void setChanged() Marca este objeto como tendo sofrido uma
mudana.
Tabela VI.XX Mtodos da classe Observable.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
150
Exemplo
O exemplo VI.xx mostra uma classe Observavel que muda de valor
aleatoriamente. A classe implementa a interface Runnable, uma vez que ser
executada concorrentemente. A concorrncia ser abordada detalhadamente no
Captulo XI.
import java.util.*;
public class Observavel extends Observable implements Runnable
{
int valor =0;
public void notifyObservers()
{
setChanged();
super.notifyObservers();
}
public int getValue(){return valor;}
public void run()
{
for(;;)
{
if (Math.random()>0.5)
{
valor =(new Double(Math.random()*200)).intValue();
this.notifyObservers();
}
try {Thread.sleep(300);} catch(Exception e){};
}
}
}
Exemplo VI.xx Uma classe Observable.
O exemplo a seguir mostra uma classe que define um observador. Para
isso necessrio implementar a interface Observer, cujo nico mtodo a ser
codificado o mtodo update(). Este mtodo chamado quando o objeto
observado notifica alguma alterao. No exemplo o objeto observador simula
uma barra de progresso que movimenta de acordo com a mudana do valor do
objeto observado.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
151
import java.awt.*;
import java.util.*;
public class FrameOb extends Frame implements Observer
{
Observavel ob = new Observavel();
Thread t = new Thread(ob);
Canvas progress = new Canvas();
public FrameOb()
{
setLayout(null);
setSize(300,60);
add(progress);
progress.setBackground(Color.blue);
progress.setBounds(0,0,0,30);
setTitle("Exemplo de Observvel");
SymWindow aSymWindow = new SymWindow();
this.addWindowListener(aSymWindow);
ob.addObserver(this);
t.start();
}
static public void main(String args[])
{
(new FrameOb()).setVisible(true);
}
class SymWindow extends java.awt.event.WindowAdapter
{
public void windowClosing(java.awt.event.WindowEvent event)
{
System.exit(0);
}
}
public void update(Observable o, Object arg)
{
progress.setSize(ob.getValue(), 100);
}
}
Exemplo VI.xx Uso da classe Observable.
StringTokenizer
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
152
public class StringTokenizer
extends Object
implements Enumeration
A StringTokenizer uma classe que permite quebrar uma cadeia de
caracteres em subcadeias denominadas de tokens. um token uma subcadeia
cercada por caracteres denominados delimitadores. Portanto, o que um token
depender da especificao dos delimitadores. Por exemplo, dada cadeia de
caracteres ola mundo,ola vida teremos os tokens ola mundo e
ola vida caso o delimitador seja o caractere , e os tokens ola,
mundo,ola e vida caso o delimitador seja o caractere
Hierarquia
java.lang.Object
|
+--java.util.StringTokenizer
Construtores
Construtor Descrio
public
StringTokenizer(String s)
Constri um StringTokenizer para s.
public
StringTokenizer(String s,
String del)
Constri um StringTokenizer para s,
usando como delimitadores os caracteres
contidos em del.
public StringTokenizer
(String s, String del,
boolean voltaTokens)
Constri um StringTokenizer para s,
usando como delimitadores os caracteres
contidos em del. Se voltaTokens possui o
valor true, ento os caracteres contidos em
del tambm so retornados.
Tabela VI.XX Construtores da classe StringTokenizer.
Mtodos
Mtodo Descrio
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
153
public int countTokens() Retorna o nmero de tokens.
public boolean
hasMoreElements()
Mesmo efeito que hasMoreTokens().
public boolean hasMoreTokens()
Retorna true se existir mais tokens.
public Object nextElement() Retorna o prximo token como uma instncia
de Object.
public String nextToken() Retorna o prximo token como uma instncia
de String.
public String nextToken(String
del)
Retorna o prximo token como uma instncia
de String usando como delimitadores os
caracteres contidos em del.
Tabela VI.XX Mtodos da classe StringTokenizer.
Exemplo
import java.util.*;
public class TestToken
{
static public void main(String args[])
{
StringTokenizer st =
new StringTokenizer("ola mundo louco");
while (st.hasMoreTokens())
println(st.nextToken());
}
}
Sada:
ola
mundo
louco
Exemplo VI.XX Uso da classe StringTokenizer.
Agenda Eletrnica verso Console 2.0
Neste ponto j estamos preparados para fazer alguns aperfeioamentos na
nossa agenda eletrnica de endereos. As alteraes sero de dois tipos:
passaremos a utilizar um objeto da classe Hashtable para agrupar as pessoas
da agenda, e acrescentaremos mtodos para gravar e recuperar os dados da
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
154
agenda em um arquivo. Estas modificaes acarretaro mudanas apenas nos
cdigos das classes Agenda e AgendaInt. O diagrama de classes da figura
IV.XX mostra as adies dos mtodos gravarAgenda() e
recuperarAgenda(), responsveis pela gravao e recuperao dos dados
em arquivo.
Figura VI.xx Diagrama de classes da verso console 2.0 da agenda
eletrnica.
Como a classe Pessoa no sofrer nenhuma modificao. Ela
apresentada abaixo apenas por questes de comodidade.
/**
Pessoa
*/
public class Pessoa
{
private String Nome;
private String Tel;
private String End;
// Construtor
public Pessoa(String n, String t, String e)
{
Nome = n; Tel = t; End = e;
}
/**
getNome
*/
public String getNome(){return Nome;}
/**
getNome
AgendaInt
+obterPessoa()
+exibirLista()
+exibirPessoa()
+gravarAgenda()
+recuperarAgenda()
Agenda
+inserir(pessoa p)
+getPessoas()
+getPessoa(String Nome)
Pessoa
-String Nome
-String Tel
-String End
+getNome()
+getTel()
+getEnd()
0..*
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
155
*/
public String getTel(){return Tel;}
/**
getEnd
*/
public String getEnd(){return End;}
}
A classe Agenda ser alterada de modo que o a associao de
agrupamento com a classe Pessoa seja implementada por meio de um objeto da
classe Hashtable e no por um array.
/**
AGENDA Verso Console 2.0.
*/
import java.util.*;
public class Agenda
{
Hashtable pessoas;
// Construtor
public Agenda() {pessoas = new Hashtable();}
/**
inserir
*/
public void inserir(Pessoa p) {pessoas.put(p.getNome(),p);}
/**
Consultar
*/
public Pessoa getPessoa(String nome)
{return (Pessoa) pessoas.get(nome);}
/**
listar
*/
public Enumeration getPessoas(){return pessoas.elements();}
}
Podemos notar que o cdigo fica bem mais simples com a adoo da
instncia da classe Hashtable. Foi alterada a assinatura do mtodo
getPessoas(), de modo que no mais retorna um array e sim um objeto da
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
156
classe Enumeration. A classe AgendaInt ser alterada para tratar o retorno
do mtodo getPessoas() e receber mais dois novos mtodos. O mtodo
main() tambm ser alterado para receber solicitaes para a execuo das
novas funes.
/**
AgendaInt
Interface console da agenda.
*/
import java.io.*;
import java.util.*;
public class AgendaInt
{
Agenda ag;
BufferedReader in;
// Construtor
public AgendaInt()
{
ag = new Agenda();
in = new BufferedReader(new InputStreamReader(System.in));
}
/**
Exibirlista
*/
public void Exibirlista()
{
Pessoa p;
for(Enumeration e = ag.getPessoas(); e.hasMoreElements();)
{
p = (Pessoa) e.nextElement();
System.out.println("\nNome:"+p.getNome()+"\nTelefone:"
+p.getTel()+"\nEndereo:"+p.getEnd()+"\n");
}
}
/**
exibirPessoa
*/
public void exibirPessoa()
{
String nome=null;
try {
System.out.println("Entre com o nome:");
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
157
nome = in.readLine();
if (nome.length()<1) System.exit(-1);
} catch(IOException e)
{System.out.println(e.getMessage());System.exit(-1);}
Pessoa p = ag.getPessoa(nome);
if (p!=null)
{
System.out.println("\nNome:"+p.getNome()+"\nTelefone:"
+p.getTel()+"\nEndereo:"+p.getEnd());
}
}
/**
obterPessoa
*/
public void obterPessoa()
{
String nome;
String tel;
String end;
try {
System.out.println("Entre com o nome:");
System.out.flush();
nome = in.readLine();
if (nome.length()<1) System.exit(-1);
System.out.println("\nEntre com o Telefone:");
System.out.flush();
tel = in.readLine();
System.out.println("\nEntre com o Endereo:");
System.out.flush();
end = in.readLine();
ag.inserir(new Pessoa(nome ,tel,end));
} catch(IOException e)
{System.out.println(e.getMessage());System.exit(-1);}
}
/**
gravar
*/
public void gravar()
{
try
{
Pessoa p;
BufferedWriter fout = new BufferedWriter(
new FileWriter("agenda.dat"));
for (Enumeration e = ag.getPessoas();
e.hasMoreElements();)
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
158
{
p = (Pessoa) e.nextElement();
fout.write(p.getNome()+"\n"+p.getTel()+"\n"
+p.getEnd()+"\n");
}
fout.flush();
fout.close();
} catch(FileNotFoundException e)
{ System.out.println("Arq. No encontrado");}
catch(IOException e)
{System.out.println("Erro na gravao!");}
}
/**
carregar
*/
public void carregar()
{
try
{
String nome;
String tel;
String end;
BufferedReader fin = new BufferedReader(
new FileReader("agenda.dat"));
while ((nome = fin.readLine()) != null)
{
tel = fin.readLine();
end = fin.readLine();
ag.inserir(new Pessoa(nome,tel,end));
}
fin.close();
} catch(FileNotFoundException e)
{System.out.println("Arq. No encontrado");}
catch(IOException e)
{System.out.println("Erro na leitura!"); }
}
// main
public static void main(String args[])
{
AgendaInt agInt = new AgendaInt();
String opcao="";
for(;;)
{
System.out.println(
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
159
"\nAgenda Tabajara\n***********************\n");
System.out.print("Opcoes:\n(i)nserir\n(c)onsultar"+
"\n(l)istar\n(g)ravar\n(r)ecuperar\n(f)im=>");
System.out.flush();
try
{
opcao = agInt.in.readLine();
if (opcao.length()==0) continue;
} catch(IOException e)
{System.out.println(e.getMessage());System.exit(-1);}
switch(opcao.charAt(0))
{
case 'f': System.exit(0); break;
case 'i': agInt.obterPessoa(); break;
case 'c': agInt.exibirPessoa(); break;
case 'l': agInt.Exibirlista(); break;
case 'g': agInt.gravar(); break;
case 'r': agInt.carregar(); break;
}
}
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
160
Captulo VII - Serializao e
Persistncia
Um objeto serializvel se podemos transform-lo em uma sequncia de
bytes de modo que seja possvel o seu armazenamento em arquivo ou envio
atravs de um stream. Desta forma o estado do objeto pode ser preservado em
memria no voltil. Neste caso dizemos que o objeto possui persistncia, ou
seja o estado do objeto persiste enter as execues do programa. A persistncia
implementada pela serializao chamada de persistncia leve, uma vez que o
programador deve providenciar o armazenamento. Em uma persistncia
completa o programador apenas informa ao sistema que o objeto persistente,
ficando a cargo do ambiente o armazenamento e recuperao do objeto de forma
transparente.
A serializao de objetos foi adicionada linguagem J ava a partir da
verso 1.1 com o intuito de possibilitar a transmisso de objetos entre mquinas
executando diferentes plataformas operacionais, viabilizando dessa forma o RMI
(Remote Method Invocation) e permitir a utilizao JavaBeans, que so
componentes configurveis em tempo de execuo, e que mantm a
configurao entre ativaes.
Para que os objetos de uma classe sejam serializveis basta que a classe
implemente a interface Serializable. A partir de ento possvel
armazenar e recuperar os objetos da classe por meio de instncias das classes
ObjectOutputStream e ObjectInputStream, respectivamente. O
exemplo VII.1 mostra como armazenar e recuperar um objeto da classe Pessoa
em um arquivo p.dat.
class pessoa implements Serializable
{
String Nome;
String Tel;
public pessoa(String Nome, String Tel)
{this.Nome = Nome; this.Tel = Tel;}
}
...
Pessoa p = new pessoa(Ana,234-6757);
FileOutputStream fout = null;
ObjectOutputStream out;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
161
try {
fout = new FileOutputStream(p.dat");
out = new ObjectOutputStream(fout);
out.writeObject(p);
out.close();
} catch(Exception e) {System.out.println(Erro:");return;}
FileInputStream fin = null;
ObjectInputStream in;
try {
fin = new FileInputStream(p.dat");
in = new ObjectInputStream(fin);
p = (pessoa) in.readObject();
in.close();
} catch(Exception e)
{ System.out.println(Erro:+e); return;}
Exemplo VII.1 Armazenamento e recuperao de um objeto da classe
Pessoa.
Uma questo interessante : o que acontece com os objetos que so
referenciados pelo objeto que est sendo armazenado? Devem ser armazenados
tambm ou no? Se os objetos referenciados no forem armazenados juntos com
o objeto corrente, a recuperao do mesmo posteriormente poder resultar em
uma instncia incompleta. Por exemplo, um objeto do tipo Pessoa como
mostrado no exemplo VII.1, referencia dois objetos do tipo String que
armazenam o nome e o telefone da pessoa representada pelo objeto. Se estes
objetos no forem armazenados junto com a instncia de Pessoa, qual o
sentido da posterior recuperao do objeto? Portanto, quando um objeto
armazenado todos os objetos referenciados por ele tambm so armazenados,
desde que os objetos implementem a interface Serializable. Caso o objeto
referenciado tambm referencie outro objeto, este ltimo tambm ser
armazenado, e assim por diante, at que toda os objetos da cadeia de referencias
sejam armazenados. Isto pode fazer com que o objeto armazenado ocupe muito
mais espao do que o imaginado inicialmente pelo programador. Outra pergunta
seria: o que acontece ento quando um objeto referenciado mais de uma vez
ou quando acontece um ciclo no grafo de referncias? Neste caso, o objeto
armazenado apenas uma vez.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
162
Agenda Eletrnica verso Console 2.1
Com o objetivo de exemplificar o que foi discutido neste captulo,
modificamos a agenda eletrnica para que a gravao e a carga do arquivo seja
feita atravs da serializao do objeto Agenda. Primeiramente, foi modificada
as classes Pessoa e Agenda de modo que implementassem a interface
Serializable. Para isto basta importar a interface do pacote java.io e
modificar a declarao das classes, como mostrado abaixo. Como o restante do
cdigo dessas duas classes permanece inalterado, no o repetimos aqui. O leitor
deve se reportar s verses anteriores caso deseje recordar sobre o cdigo
omitido.
/**
Pessoa
*/
import java.io.*;
public class Pessoa implements Serializable
{
...
Sem alterao
...
}
/**
AGENDA Verso Console 2.1.
*/
import java.util.*;
import java.io.*;
public class Agenda implements Serializable
{
...
Sem alterao
...
}
A classe AgendaInt sofre modificaes nos mtodos gravar() e
carregar(), que os tornam bem mais simples, uma vez que o trabalho de
seguir as referncias do objeto da classe Agenda para serializ-los e armazen-
los feito implicitamente. Segue abaixo apenas o cdigo dos mtodos
modificados classe AgendaInt. Note que foi preciso usar a hierarquia stream
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
163
para gravar e recuperar os objetos, uma vez que no existem classes do tipo
ObjectReader e ObjectWriter no novo conjunto de classes de E/S.
/**
AgendaInt
Interface console da agenda.
*/
import java.io.*;
import java.util.*;
public class AgendaInt
{
...
Sem alterao
...
/**
gravar
*/
public void gravar()
{
try
{
ObjectOutputStream fout = new ObjectOutputStream(
new FileOutputStream("agenda.dat"));
fout.writeObject(ag);
fout.close();
} catch(FileNotFoundException e)
{ System.out.println("Arq. No encontrado");}
catch(IOException e)
{System.out.println("Erro na gravao!");}
}
/**
carregar
*/
public void carregar()
{
try
{
ObjectInputStream fin = new ObjectInputStream(
new FileInputStream("agenda.dat"));
ag = (Agenda) fin.readObject();
fin.close();
} catch(FileNotFoundException e)
{System.out.println("Arq. No encontrado");}
catch(Exception e)
{System.out.println("Erro na leitura!"); }
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
164
...
Sem alterao
...
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
165
Captulo VIII AWT (Abstract
Window Toolkit)
At este ponto, todos o exemplos apresentados neste livro foram de
aplicaes em modo texto, tambm chamadas de aplicaes no grficas ou de
console. Hoje em dia, no possvel lanar no mercado uma linguagem de
ampla aplicao que no possua ferramentas para construo de interfaces
grficas sofisticadas. A linguagem J ava alm de ter a necessidade de atender este
requisito possui a condio adicional de prover recursos grficos que permitam o
desenvolvimento de interfaces independentes de plataforma. Talvez, devido a
esta forte exigncia, a primeira verso do pacote que implementa o suporte
grfico acabou sendo conhecido como um excelente exemplo de como no se
deve realizar um projeto. O pacote conhecido como AWT 1.0 (Abstract Window
Toolkit), no era muito harmnico, tinha um conjunto muito pobre de
componentes grficos e possua um modelo para tratamento de eventos muito
ineficiente. A verso AWT 1.1 solucionou vrios deste problemas, com o
oferecimento de um novo modelo para tratamento dos eventos e com a
introduo de um modelo para programao de componentes, denominados de
JavaBeans. Na verso 1.2 da linguagem novas facilidades foram incorporadas
com a adio de um conjuntos de componentes leves, denominados de Swing, ou
J FC (J ava Foundation Classes). A denominao de componentes leves para a
J FC se deve ao fato dos componentes no utilizarem os componentes nativos da
GUI (Graphical User Interface) do ambiente. Eles utilizam primitivas de baixo
nvel para sua construo na tela, obtendo assim um alto nvel de portabilidade.
J a AWT utiliza os componentes da GUI (widgets), para sua exibio e por isso
so chamados de componentes pesados. Por isso, para atingir uma portabilidade
razovel, apenas componentes bsicos esto presentes na AWT. Mesmo assim a
portabilidade da AWT no to grande quanto a J FC, apresentando, em alguns
casos, grandes diferenas de visualizao entre ambientes operacionais.
Neste captulo, abordaremos a verso 1.1 do AWT. Os componentes da
J FC/Swing sero tratados isoladamente no captulo XX.
A Hierarquia de componentes
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
166
O AWT um pacote contendo classes e interfaces para a criao de objetos
para interao em janelas grficas. Com essas classes possvel criar e manter
objetos tais como:
Botes (Classe Button)
Caixa de Escolha (Classe Choice)
Dilogos (Classe Dialog)
J anelas (Classe Window)
Menus (Classe Menu)
Barra de Rolamento (Classe Scrollbar)
Etc.
As classes se organizam em uma hierarquia. A figura VI.XX mostra a
organizao hierrquica das classes.
! Color
! Component
" Button
" Canvas
" Checkbox
" Choice
" Container
# Panel
# ScrollPane
# Window
Dialog
FileDialog
Frame
" Label
" List
" Scrollbar
" TextComponent
# TextArea
# TextField
! MenuComponent
" MenuBar
" MenuItem
# Menu
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
167
Figura VI.1 Hierarquia das classes no pacote AWT.
Ol Mundo AWT
Para usar classes definidas na AWT preciso import-las:
import java.awt.*;
Algumas classes so usadas para criar objetos que serviro para conter outros
objetos. Estas classes so descendentes da classe Container. Cada classe
possui um conjunto de atributos que podem ser acessados por meio de mtodos.
Como de praxe, apresentaremos primeiramente a verso AWT do ol mundo
para ilustrar os principais componentes de uma aplicao
import java.awt.*;
class OlaFrame extends Frame
{
public OlaFrame()
{
super(Ola);
setSize(100,50);
add(new Label("ola mundo"));
}
public stati c void main(String args[]){
new OlaFrame().setVisible(true);
}
}
Exemplo XX.XX Verso AWT do Ol mundo.
Para criarmos uma aplicao grfica precisaremos de algum tipo de
janela para colocarmos os componentes. Por isso a classe OlaFrame do
exemplo XX.XX uma subclasse da classe Frame que, por sua vez, e
subclasse da classe Window. A classe Frame implementa uma janela grfica
com ttulo e margem, sendo que a rea do Frame inclui a margem. No exemplo
construtor da classe invoca o construtor da superclasse, passando como
argumento o ttulo da janela.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
168
A classe Frame cria uma janela com 0 x 0 pixels e invisvel. Para
dimension-la e torn-la visvel necessrio usar os mtodos setSize() e
setVisible(). A classe Label usada para criar um objeto de texto que
adicionado ao Frame. O objeto posicionado dentro do Frame de acordo com
um esquema de posicionamento, denominado de layout. Se voc executou este
programa deve ter notado que no foi possvel finalizar o programa a no ser por
meio de um Ctrl-C na console ou algum outro mtodo indireto como o kill da
shell Unix. Isto acontece porque os objetos grficos na linguagem J ava no
possuem tratadores implcitos de eventos. Ou seja, se voc quer que algum
evento seja tratado, ento fornea o cdigo para isto.
Existem dois modelos para tratamento dos eventos que incidem sobre a
interface. O primeiro foi introduzido na verso 1.0 do AWT e o segundo foi
introduzido na verso 1.1 do AWT com o objetivo de substituir o primeiro, uma
vez que ele sofre de deficincias de projeto e desempenho. Neste livro
abordaremos apenas o modelo de eventos 1.1.
Tratamento de Eventos
O estilo de programao relacionado com interfaces grficas a
programao voltada para eventos. Ou seja, o usurio define a interface e um
conjunto de procedimentos para lidar com os eventos que incidiro sobre a
interface. A construo de uma aplicao grfica exige a criao de pelo menos
um objeto que defina uma rea no vdeo para exibir os componentes da
aplicao. Para isso pode-se utilizar um objeto da classe Window ou Frame. O
exemplo XX.XX contm o cdigo de um programa que exibe uma mensagem na
tela. Posteriormente necessrio definir quem deve receber os eventos gerados
pela interao com a interface. Cada linguagem apresenta uma soluo distinta
para o tratamento de eventos. A soluo J ava implementada no modelo de
eventos 1.1 explicada a seguir.
Modelo de Eventos 1.1
O Modelo de eventos do AWT1.1 um grande avano sobre o modelo
1.0. Ele no s mais flexvel e orientado a objetos, como permitiu o
desenvolvimento da interface de aplicao JavaBeans, que viabiliza a descrio
de componentes visuais.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
169
A idia por trs do novo modelo que uma fonte de eventos possa enviar
os eventos para um ou mais objetos cadastrados para o recebimento do evento,
denominados de event listeners. Geralmente, a fonte de evento um
componente, ou seja, um objeto da classe Component. Um listener um objeto
que implementa a interface EventListener ou alguma de suas sub-
interfaces. A figura IV.XX ilustra a estratgia adotada.
Figura VI.XX Esquema de delegao de eventos AWT1.1.
Note que um Listener pode estar registrado em mais de um
componente. Um componente pode ter mais de uma lista de Listener,
dependendo dos tipos de eventos que ele pode gerar. Uma ao sobre um
componente pode gerar mais de um evento. Para ilustrar o tratamento de
eventos, o exemplo XX.XX mostra como criar uma janela da classe Frame que
trata o evento para fechar a janela, gerado quando o usurio clica o cone ,
situado no canto superior direito do Frame.
class FrameX extends Frame implements WindowListener
{
public FrameX() {this("FrameX");}
public FrameX(String Titulo){
super(Titulo);
addWindowListener(this);
setSize(100,50);
}
Componente
1
A
Componente
2
B
Listener
Listener
Listener
Listener
Listener
evento
evento
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
170
public void windowOpened(WindowEvent we){}
public void windowClosed(WindowEvent we){}
public void windowIconified(WindowEvent we){}
public void windowDeiconified (WindowEvent we){}
public void windowActivated(WindowEvent we){}
public void windowDeactivated(WindowEvent we){}
public void windowClosing(WindowEvent we){
setVisible(false);
dispose();
System.exit(0);
}
};
Exemplo XX.XX Cdigo para tratar o evento para fechar a janela.
Para simplificar o exemplo o prprio componente (do tipo Frame) se
registrou como um Listener para os eventos gerados por ele. De modo a se
habilitar a receber os eventos gerados por um componente do tipo Window a
classe deve implementar a interface WindowListener que uma sub-
interface da EventListener.
class FrameX extends Frame implements WindowListener
preciso tambm se registrar junto ao componente para receber os
eventos. Como no exemplo VI.XX o componente uma instncia da prpria
classe que implementa a interface, basta ento adicionar a linha
addWindowListener(this) no construtor da classe. Como a classe
implementa a interface necessrio incluir cdigo para implementar todos os
mtodos da interface. Cada mtodo da interface trata um tipo de evento. No caso
do exemplo VI.XX, estamos interessados em tratar eventos que solicitam o
fechamento da janela. Portanto, necessrio incluir o cdigo para tratamento do
evento neste mtodo. Os outros mtodos so implementados sem linhas de
cdigo, para cumprir a exigncia do compilador. Note que todos os mtodos da
classe FrameX recebem um tipo de evento: WindowEvent. No modelo de
eventos 1.1, na verso SDK1.3, existem 14 classes para os eventos, definidas no
pacote java.awt.event, todas subclasses da classe
java.awt.event.AwtEvent e cada uma representando um conjunto de
eventos relacionados, como mostrado na tabela VI.XX.
Evento Descrio
ComponentEvent Indica que um componente moveu, foi escondido, exibido ou mudou
de tamanho.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
171
FocusEvent Indica que um componente recebeu ou perdeu o foco.
KeyEvent Indica que um componente recebeu uma entrada pelo teclado.
MouseEvent Indica que um componente recebeu uma entrada pelo mouse.
ActionEvent Indica que um componente foi ativado.
AdjustmentEvent Indica que uma barra de rolamento ou componente similar foi
movido.
HierarchyEvent indica uma mudana na hierarquia de componentes a qual o
componente pertence.
InputEvent o evento raiz de todos os eventos de entrada
de componentes.
InputMethodEvent Contm informao sobre o texto que est sendo editado. Sempre que
o texto for alterado este evento ser enviado.
InvocationEvent
O evento que executa o mtodo run() em um tipo Runnable
quando disparado pelo thread despachador de eventos da AWT.
ItemEvent Indica que um item de um componente como lista, checkbox, ou
similar foi selecionado.
ContainerEvent Indica que um componente foi adicionado ou removido de um
container.
WindowEvent Indica que a janela mudou de estado.
TextEvent Indica que uma mudana ocorreu em um campo de texto.
Tabela VI.XX Classes de Eventos.
O exemplo XX.XX mostra o cdigo de uma janela contendo um boto. A
classe que implementa a janela se cadastra junto ao componente Button para
receber o eventos sobre os componente. Para diminuir a complexidade do cdigo
a classe FrameBotao subclasse da FrameX definida anteriormente. Toda
vez que o componente Button acionado, gerando um evento
ActionEvent, o mtodo actionPerformed() da instncia
FrameBotao invocado. O mtodo alterna o texto exibido pelo boto a cada
chamada entre os textos Aperte aqui e Valeu.
import java.awt.*;
import java.awt.event.*;
public class FrameBotao extends FrameX
implements ActionListener
{
Button b;
public FrameBotao()
{
setLayout(null);
setSize(100,80);
b = new Button("Aperte aqui");
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
172
add(b);
b.setBounds(10,40,80,30);
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if (b.getLabel().equals("Aperte Aqui"))
b.setLabel(Valeu);
else b.setLabel("Aperte Aqui");
}
public static void main(String args[]){
(new FrameBotao()).setVisible(true);
}
}
Exemplo XX.XX Cdigo para tratar um evento gerado em boto.
Tratamento de Eventos com classes Internas
Agora vamos supor que uma determinada classe necessitasse receber
vrios eventos de vrios componentes. O cdigo da classe poderia ficar um
pouco confuso, alm da lista enorme de interfaces que necessitariam de ser
declarada aps a palavra implements. Uma forma mais elegante de se lidar
com estes casos por meio de classes internas, ou inner classes. Desta forma, o
cdigo para tratar cada grupo de eventos fica localizado em uma nica classe, e
como as classes internas possuem acesso classe externa, os atributos e mtodos
da classe externa podem ser diretamente referenciados. O exemplo XX.XX
mostra o exemplo XX.XX alterado de forma que o evento ActionEvent
gerado acionamento do componente Button seja tratado por uma classe
interna.
import java.awt.*;
import java.awt.event.*;
public class FrameBotao extends FrameX
{
Button b;
Public FrameBotao()
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
173
{
setLayout(null);
setSize(100,80);
b = new Button("Aperte Aqui");
add(b);
b.setBounds(10,40,80,30);
b.addActionListener(new Bl());
}
class Bl implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (b.getLabel().equals("Aperte Aqui"))
b.setLabel(Valeu);
else b.setLabel("Aperte Aqui");
}
}
public static void main(String args[]){
(new FrameBotao()).setVisible(true);
}
}
Exemplo XX.XX Cdigo para tratar um evento gerado em boto.
Cada componente pode receber um determinado conjunto de listener para
receber eventos. A Figura VI.XX mostra a relao entre alguns componentes e
os eventos que podem ser gerados por eles.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
174
Figura XX.XX Relao entre os componentes e os eventos.
FocusEvent
ActionEvent
AdjustmentEvent
ItemEvent
ContainerEvent
TextEvent
WindowEvent
TextField
MouseEvent
Scrollbar
Component
Label
Dialog
Panel
MenuItem
Button
Frame
Choice
Menu
ComponentEvent
KeyEvent
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
175
As instncias das classes de eventos mantm as informaes relativas ao
evento. Por exemplo, a classe MouseEvent possui os seguintes mtodos para
recuperao de informao sobre o evento:
Mtodo Descrio
int getId() tipo do evento. Por exemplo:
MouseEvent.MOUSE_CLICKED,
MouseEvent.MOUSE_PRESSED
int getX() coordenada x do evento.
int getY() coordenada y do evento.
Point getPoint() coordenada x e y do evento.
int getClickCount() retorna o nmero de mouse clicks.
boolean isPopupTrigger() indica se o evento um disparo para menu pop-up.
void translatePoint(int x,
int y)
move a posio do evento por x e y.
Tabela VI.XX Mtodos da classe MouseEvent.
Basicamente, para se codificar um tratador para um determinado evento
basta seguir os seguintes passos:
1. Determine o grupo de eventos deseja tratar.
2. No nome do grupo de eventos substitua o termo trecho Event por
Listener. Este o nome da interface que voc deve implementar. Crie
uma classe interna que implementa a interface.
3. Codifique os mtodos que tratam os eventos que voc deseja tratar. Todos os
mtodos da interface tem que ser implementados, mas o corpo dos mtodos
que no interessam podem ser deixados vazios.
4. Registre um objeto da classe interna junto ao componente, por meio do
mtodo addXXX, onde XXX o nome da interface implementada.
Por exemplo, no exemplo VI.XX, para tratar o grupo de eventos
ActionEvent foi criada uma classe interna que implementa a interface
ActionListener, e um objeto da classe interna registrado no componente
por meio do mtodo addActionListener. Portanto, tendo o nome do grupo
de eventos fcil obter o nome da interface e do mtodo de registro no
componente. Segue abaixo uma lista com alguns mtodos para registro de
listeners.
Button.addActionListener(ActionListener l)
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
176
Frame.addWindowListener(WindowListener l)
Choice.addItemListener(ItemListener l)
TextField.addTextListener(TextListener l)
Scrollbar.addAdjustamentListener(AdjustamentListene
r l)
Component.addComponentListener(ComponentListener l)
Component.addFocusListener(FocusListener l)
Component.addKeyListener(KeyListener l)
Algumas interfaces exigem a implementao de um grande nmero de
mtodos, como por exemplo a interface WindowListener, como foi visto no
exemplo VI.XX. Isto pode tornar a implementao das interfaces uma tarefa um
tanto tediosa. Com o objetivo de auxiliar esta tarefa, foi includo no pacote
java.awt.event seis classes abstratas, denominadas adapters que facilitam
a implementao de Listener. O programador s precisa criar uma subclasse da
classe adapter escolhida e sobrescrever o mtodo desejado. Para determinar o
nome da classe adapter basta substituir no nome da interface a subcadeia
Listener por adapter. A tabela VI.XX apresenta os nomes das classes adapters.
ComponentAdapter
ContainerAdapter
FocusAdapter
KeyAdapter
MouseAdapter
MouseMotionAdapter
WindowAdapter
Tabela VI.XX Classes adapters.
O exemplo XX.XX mostra o exemplo XX.XX alterado de forma que o
evento ActionEvent gerado acionamento do componente Button seja
tratado por uma classe interna que subclasse da classe MouseAdapter.
import java.awt.*;
import java.awt.event.*;
public class Botao extends FrameX {
Button b;
public Botao() {
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
177
setLayout(null);
setSize(100,80);
b = new Button("Aperte Aqui");
add(b);
b.setBounds(10,40,80,30);
b.addActionListener(new Bl());
}
class Bl extends MouseAdapter {
public void actionPerformed(ActionEvent e) {
if (b.getLabel().equals("Aperte Aqui"))
b.setLabel("Valeu");
else b.setLabel("Aperte Aqui");
}
}
public static void main(String args[]){
(new Botao()).setVisible(true);
}
}
Exemplo XX.XX Cdigo para tratar um evento gerado em boto.
No entanto, existem algumas desvantagens em se usar classes abstratas
no lugar de interfaces. A primeira delas que elimina a possibilidade da classe
ser subclasse de outra classe e a segunda que se o programador cometer algum
erro na digitao do nome de algum mtodo, ele ser encarado como um novo
mtodo e o original no ser sobrescrito.
Exemplo Bsico
Apresentaremos agora um exemplo um pouco mais complexo, porm
simples o suficiente para que seja facilmente entendido. O objetivo deste
exemplo e servir de base para apresentarmos os principais componentes da
biblioteca AWT. Portanto, a medida que novos componentes forem
apresentados, iremos exemplificar o uso deste componentes acrescentando-os
em nosso exemplo bsico.
A funo de nosso exemplo servir como ambiente para execuo de
comandos MS-DOS, tais como dir e type. O exemplo foi projetado para
funcionar nos ambientes MS-WINDOWS 95 e MS-WINDOWS 98 mas pode ser
facilmente adaptado para funcionar em outros ambientes operacionais. A figura
XX.XX mostra a interface da primeira verso de nosso exemplo. Note que,
apesar de simples, o nosso exemplo apresenta trs componentes em sua
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
178
interface: um boto e duas caixas de texto, sendo uma com barras de rolamento e
capacidade para mltiplas linhas.
Figura XX.XX Aparncia da aplicao para execuo de comandos MS-
DOS.
A caixa de texto com capacidade para uma linha de texto um componente
TextField e sua funo permitir a entrada de comandos dos para a
execuo. A caixa de texto com capacidade para mltiplas linhas de texto um
componente TextArea e sua funo exibir o resultado da execuo do
comando. Finalmente, o boto implementado por um componente Button e
sua funo e gerar eventos para execuo do comando digitado. O exemplo
XX.XX mostra o cdigo da aplicao, implementado pela classe Comando.
1
2
3
4
5
6
import java.io.*;
import java.awt.*;
import java.awt.event.*;
public class Comando extends Frame {
private TextField tfComando;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
179
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private TextArea taSaida;
private Button btExec;
private String com;
public Comando() {
com ="command.com /c "; // Altere essa linha para outros ambientes operacionais
tfComando =new TextField(50);
taSaida =new TextArea(20,60);
btExec =new Button(Executa);
taSaida.setEditable(false);
add(tfComando,BorderLayout.NORTH);
add(btExec,BorderLayout.SOUTH);
add(taSaida,BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
btExec.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
btExecActionPerformed(evt);
}
});
pack();
}
private void btExecActionPerformed(ActionEvent evt) {
String s =tfComando.getText();
if (s==null) return;
try {
Process p =Runtime.getRuntime().exec(com+s);
InputStream in =p.getInputStream();
BufferedReader br =new BufferedReader(new InputStreamReader(in));
String line;
taSaida.setText("");
while ((line =br.readLine()) !=null) {
taSaida.append(line+'\n');
}
taSaida.append("Fim!");
}catch(Exception e) {taSaida.setText(e.getMessage()); return;}
}
public stati c void main(String args[]) {
new Comando().show();
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
180
56
57
}
}
Exemplo XX.XX Cdigo que executa um comando DOS.
Na linha 12 criado um objeto String contendo o parte inicial do comando
necessrio para invocar a shell do MS-DOS. Essa parte inicial deve ser alterada
para adaptar o exemplo para outros sistemas operacionais. Nas linhas 14 a 16
so criados os componentes que faro parte da interface. Na linha 14 o
componente TextField criado com espao para exibir 50 caracteres. Na
linha 15 o componente TextArea criado com espao para exibir 20 linhas e
50 caracteres por linha. Na linha 16 o componente Button criado com um o
texto Executa. Na linha 18 chamado o mtodo setEditable() do
componente TextArea com o argumento false para impedir que o seu
contedo seja editado. Isso ocorre porque a funo do componente apenas
exibir o resultado da execuo dos comandos.
O leitor deve ter notado que a criao das classes que iro tratar os eventos
um pouco diferente do que mostramos at agora. Nas linhas 24 a 28 e 30 a 34 as
declaraes das classes so feitas no mesmo local onde os objetos so
instanciados. Este tipo de classe interna denominado de classe interna
annima. A classe denominada de annima pois nenhum nome associado a
ela. A classe annima se torna automaticamente subclasse da classe mencionada
aps o operador new. vantajoso usar este tipo de construo quando apenas
uma instncia da classe ser gerada, uma vez que amarra a declarao da classe
com seu uso. No entanto, em alguns casos esta tcnica pode diminuir a
legibilidade do cdigo.
Outro fato que pode intrigar o leitor a distribuio dos componentes na
janela. Aparentemente, pouco cdigo foi dedicado ao posicionamento dos
elementos na interface. Mesmo assim os componentes foram arranjados de
forma razoavelmente ordenada na interface. Isto se deve ao fato de todos os
componentes do tipo Container seguirem um arranjo predefinido (layout).
Este arranjo implementado pelas classes BorderLayout, CardLayout,
FlowLayout, GridBagLayout e GridLayout, sendo o BorderLayout
o arranjo default. Existe tambm a possibilidade de no se adotar nenhum
layout. Neste caso preciso posicionar os componentes em termos de
coordenadas dentro do objeto do tipo Container. Os objetos de layout sero
tratados mais adiante. No momento basta saber que o layout adotado o default
e que este tipo de layout arranja os componentes de acordo com os pontos
cardeais (NORTH, SOUTH, EAST, WEST, CENTER). As linhas 20 a 22
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
181
mostram as adies de componentes dentro do Frame, com a indicao do seus
posicionamentos relativos segundo o layout adotado. A adio de componentes
feita por meio do mtodo add().
As linhas 38 a 52 mostram o cdigo do mtodo que executa o comando MS-
DOS e exibe o resultado no componente TextArea. Na linha 42 o comando
MS-DOS executado por meio do mtodo exec() do objeto Runtime. O
objeto Runtime obtido pelo mtodo esttico getRuntime() da classe
Runtime, uma vez que no pode ser instanciado diretamente. O processo filho,
uma vez iniciado, executado de forma concorrente com o processo pai. O
mtodo exec() retorna um objeto do tipo Process, tornando possvel
controlar o processo e obter informaes sobre ele. No nosso caso estamos
interessados em capturar a sada padro do processo filho para exibi-la na
interface. Isso feito na linha 43 por meio do mtodo getInputStream()
do objeto Process. O objeto InputStream canalizado para um objeto
BufferedReader com o objetivo de facilitar sua manipulao. As linhas
restantes do mtodo tratam da leitura da sada padro do processo filho e de sua
exibio na TextArea. Na linha 46 usado o mtodo setText() para
colocar um texto vazio no componente e, dessa forma, limpar a TextArea. Na
linha 48 a String lida da sada padro do processo filho anexada na
TextArea.
Acrescentando Cores
Podemos alterar as cores de alguns componentes do exemplo XX.XX para
torn-lo visualmente mais interessante por meio de objetos da classe Color.
Esta classe encapsula a criao de cores por meio dos nveis RGB. Ela mantm
tambm um conjunto de atributos constantes com valores de cores predefinidos.
Podemos, por exemplo, alterar a cor de fundo do componente TextArea por
meio do mtodo setBackground().
taSaida.setBackground(Color.lightGray);
Podemos alterar tambm a cor de fundo do componente Button. Neste
caso vamos obter para definir a cor por meio de um nmero que representa seus
componentes RGB.
btExec.setBackground(new Color(0x08FDDF10));
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
182
Para modificar a cor frontal preciso utilizar o mtodo
setForeground(). Todos os componentes possuem mtodos equivalentes a
estes para alterao das cores.
Gerenciando o Layout
O posicionamento de componentes dentro de objetos do tipo Container
determinado por uma instncia de objeto denominado de gerenciador de layout
(layout managers). A AWT fornece 5 classes para a implementao de layouts,
descritas na tabela XX.XX. O layout default o implementado pela classe
BorderLayout. O pacote Swing acrescenta a classe BoxLayout ao conjunto
de gerenciadores de layout.
Gerenciador de Layout Descrio
BorderLayout
Posiciona e redimensiona os componentes de um Container
em cinco regies: norte, sul, leste e oeste. Cada regio
identificada respectivamente pelas constantes: NORTH, SOUTH,
EAST, WEST, e CENTER.
FlowLayout
Posiciona os componentes de um Container em um fluxo da
esquerda para a direita, como linhas em um pargrafo. Cada
linha centralizada.
CardLayout
Trata cada componente do Container como uma a carta.
Somente uma carta visvel em um determinado instante e o
Container funciona como uma pilha de cartas. O primeiro
componente adicionado o primeiro visvel quando o
Container exibido.
GridBagLayout o gerenciador de layout mais flexvel e o mais complexo. Ele
arranja os componentes verticalmente e horizontalmente sem
exigir que os componentes tenham o mesmo tamanho. Mantm
um grade retangular de clulas, sendo que cada componente
pode ocupar mais de uma clula.
GridLayout
Posiciona e redimensiona os componentes de um Container
em uma grade retangular. O Container dividido em
retngulos de tamanhos iguais e um componente colocado em
cada retngulo.
Tabela XX.XX Gerenciadores de Layout.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
183
Para definir o layout de um objeto do tipo Container basta utilizar o
mtodo setLayout() do objeto, passando como argumento um objeto
gerenciador de layout, como mostrado abaixo:
Frame f = new Frame();
f.setLayout(FlowLayout);
possvel tambm no adotar layout algum, optando por posicionar os
componentes em coordenadas absolutas dentro do Container. Para isso basta
passar null como argumento para o mtodo setLayout(). O
posicionamento absoluto de componentes pode ser feito pelos mtodos
setLocation() ou setBounds() do componente, como mostrado abaixo.
Frame f = new Frame();
f.setLayout(null);
Button b = new Button(Teste);
f.add(b);
b. setLocation(10, 10);
Porm, a adoo de gerenciadores de layout permite o desenvolvimento que
se adaptam mais facilmente redimensionamentos e mudanas de linguagens.
Isto o posicionamento e dimensionamento absoluto pode fazer com que
componentes tornem-se parcialmente ou totalmente ocultos com o
redimensionamento da janela. O mesmo pode ocorrer com os labels dos
componentes quando forem traduzidos para outra lngua. J estes problemas no
ocorrem com o posicionamento e dimensionamento relativo.
Exemplo com BorderLayout
O exemplo XX.XX utiliza este gerenciador de layout para distribuir os
componentes na interface. O exemplo abaixo mostra distribuio de cinco botes
em um Frame por meio deste tipo de gerenciador de layout.
import java.awt.*;
public class BorderTeste extends FrameX {
public BorderTeste() {
setLayout(new BorderLayout());
add(new Button("Norte"), BorderLayout.NORTH);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
184
add(new Button("Sul"), BorderLayout.SOUTH);
add(new Button("Leste"), BorderLayout.EAST);
add(new Button("Oeste"), BorderLayout.WEST);
add(new Button("Centro"), BorderLayout.CENTER);
}
public stati c void main(String a[]){new BorderTeste().show();}
}
Exemplo XX.XX Frame com BorderLayout.
A figura XX.XX mostra o resultado da execuo do cdigo do exemplo
XX.XX.
Figura XX.XX Aparncia do Frame com BorderLayout.
Exemplo com FlowLayout
O exemplo abaixo mostra distribuio de cinco botes em um Frame por
meio deste tipo de gerenciador de layout.
import java.awt.*;
public class FlowTeste extends FrameX {
public FlowTeste() {
setLayout(new FlowLayout());
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
185
add(new Button("UM"));
add(new Button("DOIS"));
add(new Button("TRS"));
add(new Button("QUATRO"));
add(new Button("CINCO"));
setSize(200,100);
}
public static void main(String a[]){new FlowTeste().show();}
}
Exemplo XX.XX Frame com FlowLayout.
A figura XX.XX mostra o resultado da execuo do cdigo do exemplo
XX.XX. Note que quando acaba o espao em uma linha os componentes so
posicionados na linha de baixo seguindo da esquerda para a direita. Note
tambm que cada linha centralizada no Container.
Figura XX.XX Aparncia do Frame com FlowLayout.
Exemplo com CardLayout
O exemplo abaixo mostra usar o CardLayout para alternar a exibio de
componentes. Um boto adicionado interface para receber eventos. Quando o
boto pressionado o tratador de eventos alterna a exibio dos componentes do
CardLayout por meio de chamadas ao mtodo next() do gerenciador de
layout. A J FC fornece o componente JtabbedPane que apresenta maiores
facilidades.
import java.awt.*;
import java.awt.event.*;
public class CardTeste extends FrameX {
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
186
Panel p;
CardLayout cl;
Button b;
public CardTeste() {
setLayout(new BorderLayout());
p =new Panel();
b =new Button("Muda carta");
cl =new CardLayout();
p.setLayout(cl);
p.add(new Label("Este Label est na primeira carta"),"um");
p.add(new Label("Este Label est na segunda carta"),"dois");
add(b, BorderLayout.NORTH);
add(p, BorderLayout.SOUTH);
b.addActionListener( new ActionListener() {
public void
actionPerformed(ActionEvent evt) {
cl.next(p);
}
});
pack();
}
public stati c void main(String a[]){new CardTeste().show();}
}
Exemplo XX.XX Frame com CardLayout.
Note que ao adicionar um componente ao Container preciso passar um
identificador. A figura XX.XX mostra o resultado da execuo do cdigo do
exemplo XX.XX.
Figura XX.XX Aparncia do Frame com CardLayout.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
187
Exemplo com GridLayout
O exemplo abaixo mostra distribuio de cinco botes em um Frame por
meio deste tipo de gerenciador de layout.
import java.awt.*;
public class GridTeste extends FrameX {
public GridTeste() {
setLayout(new GridLayout(3,2));
add(new Button("UM"));
add(new Button("DOIS"));
add(new Button("TRS"));
add(new Button("QUATRO"));
add(new Button("CINCO"));
}
public stati c void main(String a[]){new GridTeste().show();}
}
Exemplo XX.XX Frame com GridLayout.
A figura XX.XX mostra o resultado da execuo do cdigo do exemplo
XX.XX.
Figura XX.XX Aparncia do Frame com GridLayout.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
188
Exemplo com GridBagLayout
Este gerenciador o mais complexo, mas tambm o que permite um maior
controle sobre o posicionamento dos elementos, sem perder as vantagens de um
posicionamento relativo. O exemplo XX.XX mostra distribuio de nove botes
em um Frame por meio deste tipo de gerenciador de layout.
import java.awt.*;
public class GridBagTeste extends FrameX {
public GridBagTeste() {
Button b;
GridBagLayout gridbag =new GridBagLayout();
GridBagConstraints c =new GridBagConstraints();
setLayout(gridbag);
for (int i=1;i<10;i++) {
switch(i) {
case 1: c.fill =GridBagConstraints.BOTH;
c.weightx =1.0;
break;
case 6:
case 3: c.gridwidth =GridBagConstraints.REMAINDER;
c.weightx =1.0;
break;
case 4: c.weightx =0.0;
break;
case 5: c.gridwidth =GridBagConstraints.RELATIVE;
c.weightx =1.0;
break;
case 7: c.gridwidth =1;
c.gridheight =2;
c.weighty =1.0;
break;
case 8: c.gridwidth =GridBagConstraints.REMAINDER;
c.weighty =0.0;
c.gridheight =1;
break;
}
b =new Button("Boto "+i);
gridbag.setConstraints(b, c);
add(b);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
189
}
pack();
}
public static void main(String args[]) { new GridBagTeste().show(); }
}
Exemplo XX.XX Frame com GridBagLayout.
O posicionamento relativo dos componentes controlado por meio de um
objeto da classe GridBagConstraints. Ele possui vrios atributos pblicos que
orientam o gerenciador de layout no momento de posiciona e reorganizar os
componentes. O objeto associado a cada componente por meio do mtodo
setConstraints() da instncia GridBagLayout. Os atributos utilizados no
exemplo foram:
fill usado quando a rea para a exibio do componente maior que a
rea requisitada pelo componente. Os valores possveis (definidos na
classe GridBagConstraints) so NONE (default), HORIZONTAL (torna o
componente largo o suficiente para preencher a rea horizontalmente),
VERTICAL (torna o componente alto o suficiente para preencher a rea
na vertical), e BOTH (preenche nos dois sentidos).
weightx, weighty determina como o espao excedente distribudo,
definindo o comportamento para o redimensionamento. Ou seja define a
proporo do espao que excedente que ser distribudo entre os
componentes. Se no for especificado para pelo menos uma linha
(weightx) e coluna (weighty), todos os componentes sero agrupados
no centro do Container, uma vez que o peso de cada um zero
(default).
gridwidth, gridheight Especifica o numero de clulas em um linha
(gridwidth) ou coluna (gridheight) ocupadas pela rea de exibio
de um componente. O valor default 1. Os valores possveis (definidos
na classe GridBagConstraints) so REMAINDER para especificar que o
componente deve ser o ltimo da linha (para gridwidth) ou coluna
(para gridheight). RELATIVE para especificar que o componente deve
ser o vizinho do ltimo na linha (para gridwidth) ou coluna (para
gridheight). Ou valores inteiros especificando o nmero de linhas e
colunas ocupadas.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
190
A figura XX.XX mostra o resultado da execuo do cdigo do exemplo
XX.XX.
Figura XX.XX Aparncia do Frame com GridBagLayout.
Utilizando Listas
Muitas vezes necessrio que o usurio selecione um item a partir de uma
lista de itens disponveis. A AWT torna possvel a seleo de um item em uma
lista de itens por meio do componente Choice. Este componente possui mtodos
para a adio, remoo e acesso a itens. O exemplo abaixo mostra a alterao do
exemplo XX.XX que usa uma lista de escolha para armazenar os comandos
anteriores. Desta forma o usurio economiza na digitao de comandos
repetidos.
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.*;
import java.awt.*;
import java.awt.event.*;
public class Comando2 extends java.awt.Frame {
private TextField tfComando;
private TextArea taSaida;
private Button btExec;
private Panel panel;
private Choice ch;
private String com;
public Comando2() {
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
191
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
com ="command.com /c ";
tfComando =new TextField(50);
taSaida =new TextArea(20,60);
panel =new Panel();
btExec =new Button("Executa");
ch =new Choice();
ch.setVisible(false);
btExec.setBackground(new Color(0x08FDDF10));
taSaida.setBackground(Color.lightGray);
taSaida.setEditable(false);
add(panel,BorderLayout.NORTH);
panel.add(tfComando,BorderLayout.NORTH);
panel.add(ch,BorderLayout.CENTER);
add(btExec,BorderLayout.SOUTH);
add(taSaida,BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
btExec.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
btExecActionPerformed(evt);
}
});
ch.addItemListener( new ItemListener() {
public void itemStateChanged(ItemEvent evt) {
if (evt.getStateChange() ==ItemEvent.SELECTED)
tfComando.setText(ch.getSelectedItem());
}
});
pack();
}
private void btExecActionPerformed(ActionEvent evt) {
String s =tfComando.getText();
if (s==null) return;
boolean inclui =true;
for (int i=ch.getItemCount()-1;i>=0;i--)
if (s.equals(ch.getItem(i))) inclui=false;
if (inclui) {
ch.add(s);
ch.setVisible(true);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
192
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
pack();
}
try {
Process p =Runtime.getRuntime().exec(com+s);
InputStream in =p.getInputStream();
BufferedReader br =new BufferedReader(new InputStreamReader(in));
String line;
taSaida.setText("");
while ((line =br.readLine()) !=null) taSaida.append(line+'\n');
taSaida.append("Fim!");
}catch(Exception e)
{taSaida.setText(e.getMessage()); return;}
}
public static void main(String args[]) {new Comando2().show(); }
}
Exemplo XX.XX Aplicao para execuo de comandos MS-DOS com lista
de escolha.
Na linha 21 usado o mtodo setVisible() para que o componente
Choice fique invisvel inicialmente. Isto feito porque no incio a lista de itens
est vazia e, portanto, no preciso exibi-la. Nas linhas 45 a 50 adicionado um
objeto ItemListener lista de listener do objeto Choice. Este objeto receber
os eventos de seleo de itens na lista de escolha. Nas linhas 58 a 64 verificado
se o comando digitado j est includo na lista de itens. Caso no esteja o item
includo e o mtodo pack() do Frame chamado, para que a janela se ajuste ao
tamanho dos componentes.
A figura XX.XX mostra o resultado da execuo do cdigo do exemplo
XX.XX.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
193
Figura XX.XX Aparncia da aplicao para execuo de comandos MS-DOS
com lista de escolha.
Trabalhando com Menus e Dilogos
Outros componentes importantes para criao de interfaces com o usurio
so os menus e as caixas de dilogos. De forma a ilustrar o uso desses recursos
modificaremos o exemplo XX.XX para conter uma barra de menus com apenas
um menu. O menu conter dois itens de menu. O acionamento do primeiro item
de menu ocasionar a exibio de um pequeno texto de ajuda no componente
TextArea. O acionamento do segundo item de menu ocasionar a exibio de
uma caixa de dilogo contendo informaes sobre a aplicao.
1
2
3
4
5
6
import java.io.*;
import java.awt.*;
import java.awt.event.*;
public class Comando3 extends java.awt.Frame {
private TextField tfComando;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
194
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private TextArea taSaida;
private Button btExec;
private Panel panel;
private Choice ch;
private String com;
public Comando3() {
com ="command.com /c ";
tfComando =new TextField(50);
taSaida =new TextArea(20,60);
panel =new Panel();
btExec =new Button("Executa");
ch =new Choice();
ch.setVisible(fal se);
btExec.setBackground(new Color(0x08FDDF10));
taSaida.setBackground(Color.lightGray);
taSaida.setEditable(false);
Menu menu =new Menu("Ajuda");
menu.add("Resumo");
menu.addSeparator();
menu.add("Sobre");
MenuBar mb =new MenuBar();
mb.add(menu);
setMenuBar(mb);
add(panel,BorderLayout.NORTH);
panel.add(tfComando,BorderLayout.NORTH);
panel.add(ch,BorderLayout.CENTER);
add(btExec,BorderLayout.SOUTH);
add(taSaida,BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
btExec.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
btExecActionPerformed(evt);
}
});
ch.addItemListener( new ItemListener() {
public void itemStateChanged(ItemEvent evt) {
if (evt.getStateChange() ==ItemEvent.SELECTED)
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
195
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
tfComando.setText(ch.getSelectedItem());
}
});
menu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("Sobre")) mostraSobre();
else if (evt.getActionCommand().equals("Resumo"))
taSaida.setText("Digite o Comando e pressione +
o boto <executa>para executar.");
}
});
pack();
}
private void mostraSobre() {
Dialog d =new Dialog(this,"Sobre Comando");
d.setModal(true);
Label lb1 =new Label("Comando Verso 1.2", Label.CENTER);
Label lb2 =new Label("Alcione de Paiva Oliveira", Label.CENTER);
lb1.setFont(new Font ("Dialog", Font.BOLD|Font.ITALIC, 18));
lb2.setFont(new Font ("Courier New", 0, 16));
d.add(lb1,BorderLayout.NORTH);
d.add(lb2,BorderLayout.SOUTH);
d.setBackground(Color.cyan);
d.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
evt.getWindow().dispose();
}
});
d.pack();
d.show();
}
private void btExecActionPerformed(ActionEvent evt) {
String s =tfComando.getText();
if (s==null) return;
boolean inclui =true;
for (int i=ch.getItemCount()-1;i>=0;i--)
if (s.equals(ch.getItem(i))) inclui=false;
if (inclui) {
ch.add(s);
ch.setVisible(true);
pack();
}
try {
Process p =Runtime.getRuntime().exec(com+s);
InputStream in =p.getInputStream();
BufferedReader br =new BufferedReader(new InputStreamReader(in));
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
196
105
106
107
108
109
110
111
112
113
114
String line;
taSaida.setText("");
while ((line =br.readLine()) !=null) taSaida.append(line+'\n');
taSaida.append("Fim!");
}catch(Exception e)
{taSaida.setText(e.getMessage()); return;}
}
public static void main(String args[]) {new Comando3().show(); }
}
Exemplo XX.XX Aplicao para execuo de comandos MS-DOS com barra
de menus e uma caixa de dilogo.
As linhas 27 a 33 contm o cdigo para a insero da barra de menus e do menu.
Na linha 27 criado um componente Menu com o label Ajuda. Nas linhas 28 a
30 so adicionados dois itens de menu e um separador ao componente Menu. Nas
linha 31 e 32 criado um componente MenuBar e o componente Menu
adicionado ao MenuBar. Na linha 33 o componente MenuBar definida como a
barra de menu da janela corrente. Nas linhas 60 a 67 adicionado um objeto
ActionListener lista de Listener do objeto Menu. Este objeto receber os
eventos de seleo de itens do menu. Caso o item de menu selecionado seja o
Sobre ento o mtodo mostraSobre() invocado. Caso o item de menu
selecionado seja o Resumo ento exibido um texto de ajuda no componente
TextArea. As linhas 71 a 88 contm o cdigo do mtodo mostraSobre(). Este
mtodo responsvel pela montagem e exibio da caixa de dilogo com
informaes sobre a aplicao. Na linha 72 criada uma instncia da classe
Dialog. O construtor desta classe exige que seja passado como parmetro um
objeto da classe Frame ou Dialog para deter a posse do objeto a ser criado.
Quando o objeto possuidor tornado invisvel ou minimizado a janela Dialog
automaticamente tornada invisvel ou minimizada. No caso do exemplo o Frame
corrente passado como parmetro. Na linha 73 invocado o mtodo
setModal() para torna a o dilogo modal. O dilogo modal bloqueia toda
entrada em todas as janelas no contexto da aplicao, exceto pelas janelas
criadas tendo o dilogo como possuidor.
A figura XX.XX mostra o resultado da execuo do cdigo do exemplo
XX.XX.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
197
Figura XX.XX Aparncia da aplicao para execuo de comandos MS-DOS
com barra de menus.
Capturando Eventos do Teclado
Principais Classes
Color
Esta classe encapsula a criao de cores por meio dos nveis RGB. Ela
mantm tambm um conjunto de atributos constantes com valores de cores
predefinidos.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
198
Hierarquia
java.lang.Object
|
+--java.awt.Color
Atributos pblicos
Atributo Descrio
Color black A cor preta.
Color blue A cor azul.
Color cyan A cor azul claro.
Color darkGray A cor cinza escuro.
Color gray A cor cinza.
Color green A cor verde.
Color lightGray A cor cinza claro.
Color magenta A cor violeta.
Color orange A cor laranja.
Color pink A cor rosa.
Color red A cor vermelha.
Color white A cor branca.
Color yellow A cor amarela.
Construtores
Construtor Descrio
Color(float r, float g,
float b)
Cria uma cor opaca RGB com os valores red, green, e
blue especificados dentro da faixa (0.0 - 1.0).
Color(int rgb) Cria uma cor opaca com os valores RGB combinados no
parmetro rgb. O componente red est definido nos
bits 16-23, o componente green est definido nos bits 8-
15, e o componente blue est definido nos bits 0-7.
Color(int r, int g,
int b)
Cria uma cor opaca RGB com os valores red, green, e
blue especificados dentro da faixa (0 - 255).
Mtodos mais usados
Mtodo Descrio
Color brighter() Cria uma verso mais clara da cor corrente.
Color darker() Cria uma verso mais escura da cor corrente.
Color decode(String nm) Converte a String em um inteiro e retorna a cor
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
199
opaca relacionada.
equals(Object obj) Verifica se o objeto igual a essa cor.
int getBlue() Retorna o componente azul da cor.
int getGreen() Retorna o componente verde da cor.
int getRed() Retorna o componente vermelho da cor.
int getTransparency() Retorna o modo de transparncia desta cor.
String toString() Retorna a representao em String desta cor.
Exemplo
Color c = new Color(0xFFC0C0C0);
Component
Um componente um objeto que possui uma representao grfica que
pode ser exibida em uma tela e pode interagir com o usurio.
Hierarquia
java.lang.Object
|
+--java.awt.Component
Atributos pblicos
Atributo Descrio
float BOTTOM_ALIGNMENT Alinhamento na parte inferior.
float CENTER_ALIGNMENT Alinhamento ao centro.
loat LEFT_ALIGNMENT Alinhamento esquerda.
float RIGHT_ALIGNMENT Alinhamento esquerda.
float TOP_ALIGNMENT Alinhamento na parte superior.
Construtor
Construtor Descrio
Component()
Constri um novo Component.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
200
Mtodos mais usados
Mtodo Descrio
void add(PopupMenu popup)
Adiciona um menu do tipo PopupMenu ao
componente.
void addComponentListener(
ComponentListener l)
Adiciona o ComponentListener para
receber eventos sobre o componente.
boolean contains(int x,
int y)
Verifica se o componente possui a coordenada.
float getAlignmentX() Retorna o alinhamento no eixo x.
float getAlignmentY() Retorna o alinhamento no eixo y.
Color getBackground() Retorna a cor de fundo do componente.
Rectangle getBounds() Retorna as dimenses do componente.
Component getComponentAt(
int x, int y)
Retorna o componente do Component que
contm a coordenada especificada. Apenas o
primeiro nvel de descendncia examinado.
Cursor getCursor() Retorna o cursor deste componente.
Font getFont() Retorna o fonte deste componente.
Color getForeground() Retorna a cor de frente deste componente.
Graphics getGraphics() Cria um contexto grfico para este
componente.
int getHeight() Retorna a altura deste componente.
Point getLocation() Retorna a localizao deste componente.
String getName() Retorna o nome deste componente.
Container getParent()
Retorna o Container onde est inserido este
componente.
Dimension getSize() Retorna as dimenses deste componente.
Toolkit getToolkit()
Retorna o Toolkit deste componente.
int getWidth() Retorna a largura deste componente.
int getX()
Retorna a coordenada X deste componente.
int getY()
Retorna a coordenada Y deste componente.
boolean isDisplayable() Verifica se este componente pode se exibido.
boolean isEnabled() Verifica se este componente est habilitado.
boolean isFocusOwner() Verifica se este componente possui o foco.
boolean isVisible() Verifica se este componente esta visvel.
void list(PrintStream out)
Lista este componente no PrintStream.
void paint(Graphics g)
Pinta o este Container. Este mtodo deve
ser sobrescrito se o programador deseja
desenhar no Container. Neste caso
super.paint(g) deve ser invocado.
void processEvent(AWTEvent e) Processa os eventos ocorrendo neste
componente.
void remove(MenuComponent
popup)
Remove o menu popup menu deste
componente.
void setBounds(int x, int y,
int width,
Define os limites deste componente.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
201
int height)
void setEnabled(boolean b) Define este componente como habilitado.
void setFont(Font f)
Define o fonte deste Component.
void void setName(String name) Define o nome deste componente.
void setSize(int width,
int height)
Define o tamanho deste componente.
void setVisible(boolean b) Define este componente como visvel.
String toString()
Retorna a representao em String deste
componente.
Exemplo
Component c= new Component();
Button
Os objetos da classe Button so objetos grficos que simulam botes e
geram eventos quando so pressionados.
Hierarquia
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Button
Construtores
Construtor Descrio
Button() Constri um boto sem texto.
Button(String lbl) Constri um boto com um texto.
Mtodos mais usados
Mtodo Descrio
String getLabel() Retorna o texto apresentado no boto.
void setLabel(String lbl) Define o texto apresentado no boto como o
referenciado por lbl.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
202
Exemplo
Button b= new Button(ok);
Label
Os objetos da classe Label servem para exibir textos que no sero
editados pelo usurio.
Hierarquia
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Label
Construtores
Construtor Descrio
Label()
Constri um Label sem texto.
Label(String lbl)
Constri um Label com um texto.
Label(String lbl,
int alin)
Constri um Label com um texto e com o alinhamento
especificado por alin. Os valores possveis para o
alinhamento so Label.LEFT, Label.RIGHT, e
Label.CENTER.
Mtodos mais usados
Mtodo Descrio
String getText()
Retorna o texto apresentado no Label.
void setText(String lbl)
Define o texto apresentado no Label como o
referenciado por lbl.
int getAlignment() Retorna o alinhamento.
void setAlignment(int alin) Estabelece o novo alinhamento, especificado
por alin. Os valores possveis para o
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
203
alinhamento so Label.LEFT,
Label.RIGHT, e Label.CENTER.
List
O componente List permite que o programador crie uma lista de
elementos passveis de rolamento. Dependendo de como a lista foi definida o
usurio pode selecionar um item ou mltiplo itens.
Hierarquia
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.List
Construtores
Construtor Descrio
List() Constri uma nova lista rolvel.
List(int linhas) Constri uma nova lista rolvel com o nmero de linhas
visveis igual a linhas.
List(int linhas,
boolean sm)
Constri uma nova lista rolvel com o nmero de linhas
visveis igual a linhas e o parmetro sm indicando se
para permitir selees mltiplas.
Mtodos mais usados
Mtodo Descrio
void add(String item)
Adiciona o item referenciado por item no
final da lista.
void add(String item,
int ind)
Adiciona o item referenciado por item na
posio indicada por ind. A base 0. Se o
valor de ind for menor que 0 ou maior que o
nmero de elementos, o item ser inserido no
final da lista.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
204
void deselect(int ind) remove a seleo do item no ndice
especificado.
String getItem(int ind) Obtm o item no ndice especificado.
int getItemCount() Obtm o nmero de itens na lista.
String[] getItems() Obtm todos os itens da lista.
int getRows() Obtm o nmero de linhas visveis da lista.
int getSelectedIndex() Obtm o ndice do elemento selecionado.
Retorna -1 se nenhum elemento ou mais de um
elemento estiver selecionado.
int[] getSelectedIndexes() Retorna todos os itens selecionados.
String getSelectedItem() Obtm o elemento selecionado.
String[] getSelectedItems() Obtm todos os elementos selecionados.
boolean isMultipleMode() Indica se o modo de seleo mltiplo.
void makeVisible(int ind) Torna visvel o elemento no ndice
especificado.
void remove(int ind) Remove o elemento no ndice especificado.
void removeAll() Remove todos os elementos na lista.
void select(int ind) Seleciona o elemento no ndice.
Exemplo
List lista = new List(3);
lista.add("Laranja");
lista.add("Abacate");
lista.add("Pera");
lista.add("Uva");
TextField
O componente TextField usado para implementar entrada e edio
de uma linha de texto.
Hierarquia
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.TextComponent
|
+--java.awt.TextField
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
205
Construtores
Construtor Descrio
TextField()
Constri um novo TextField.
TextField(int cols)
Constri um novo TextField com o nmero de
colunas especificado.
TextField(String txt)
Constri um novo TextField exibindo o texto
especificado.
TextField(String
txt,int cols)
Constri um novo TextField com o nmero de
colunas e o texto especificados.
Mtodos mais usados
Mtodo Descrio
int getColumns() Retorna o nmero de colunas.
String getText() Retorna o texto exibido no componente.
void setColumns(int cols) Define o nmero de colunas.
void setText(String txt) Define o nmero o texto a ser editado.
Exemplo
TextField tf;
tf = new TextField("Ola mundo!";
TextArea
O componente TextArea usado para implementar entrada e edio
de texto com mltiplas linhas.
Hierarquia
java.lang.Object
|
+--java.awt.Component
|
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
206
+--java.awt.TextComponent
|
+--java.awt.TextArea
Construtores
Construtor Descrio
TextArea()
Constri um novo TextArea.
TextArea(int lin,
int cols)
Constri um novo TextArea com o nmero de linhas
e colunas especificados.
TextArea(String txt)
Constri um novo TextArea exibindo o texto
especificado.
TextArea(String txt,int
cols)
Constri um novo TextArea com o nmero de linhas,
colunas e o texto especificados.
Mtodos mais usados
Mtodo Descrio
int getColumns() Retorna o nmero de colunas.
int getRows() Retorna o nmero de linhas.
String getText() Retorna o texto exibido no componente.
void setColumns(int cols) Define o nmero de colunas.
void setRows(int lin) Define o nmero de linhas.
void setText(String txt) Define o nmero o texto a ser editado.
Exemplo
new TextArea("Ola mundo!", 3, 20);
Containers
Containers so componentes usados para conter outros componentes. Um
objeto da classe Container pode conter inclusive outros containers,
permitindo assim a construo de interfaces complexas.
Hierarquia
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
207
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Container
Construtor
Construtor Descrio
Container()
Constri um novo Container.
Mtodos mais usados
Mtodo Descrio
Component add(
Component comp)
Adiciona o componente no final da lista de
componentes deste Container.
Component add(
Component comp, int ind)
Adiciona o componente na posio ind da
lista de componentes deste Container.
Component findComponentAt(
int x, int y)
Retorna o componente visvel do Container
que contm a coordenada especificada. Todos
os descendentes so examinados (SDK 1.2).
float getAlignmentX() Retorna o alinhamento no eixo x.
float getAlignmentY() Retorna o alinhamento no eixo y.
Component getComponent(
int n)
Retorna o componente na posio n na lista de
componentes deste Container.
Component getComponentAt(
int x, int y)
Retorna o componente do Container que
contm a coordenada especificada. Apenas o
primeiro nvel de descendncia examinado.
int getComponentCount() Retorna o nmero de componentes deste
Container.
Component[] getComponents() Retorna todos os componentes deste
Container.
Insets getInsets()
Retorna o Insets deste Container.
Insets indicam o tamanho da borda do
Container.
LayoutManager getLayout()
Retorna o Layout deste Container.
boolean
isAncestorOf(Component c)
Indica se o componente est contido neste
Container.
void list(PrintStream out,
int indent)
Imprime uma lista com o contedo deste
Container.
void paint(Graphics g)
Pinta o este Container. Este mtodo deve
ser sobrescrito se o programador deseja
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
208
desenhar no Container. Neste caso
super.paint(g) deve ser invocado.
void remove(Component comp)
Remove o componente deste Container.
void remove(int index) Remove o componente com o ndice
especificado deste Container.
void removeAll() Remove todos os componentes deste
Container.
void setFont(Font f)
Define o fonte deste Container.
void setLayout(LayoutManager
mgr)
Define o layout deste Container.
Panel
Esta classe o Container mais simples. O Panel fornece um espao
onde podem ser colocados outros componentes, inclusive outros objetos do tipo
Panel.
Hierarquia
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Container
|
+--java.awt.Panel
Construtor
Construtor Descrio
Panel()
Constri um novo Panel.
Panel(LayoutManager layout)
Constri um novo Panel usando o LayoutManager
especificado.
Mtodo
Mtodo Descrio
void addNotify()
Cria um par (peer) para o Panel. O par permite modificar o
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
209
Panel sem alterar a sua aparncia.
Exemplo
Ver exemplo VI.XX.
Frame
Um Frame uma janela com ttulo e borda. A rea do Frame inclui a
rea destinada para a borda. As dimenses da borda pode ser obtida por meio do
mtodo getInsets().
Hierarquia
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Container
|
+--java.awt.Window
|
+--java.awt.Frame
Construtores
Construtor Descrio
Frame()
Constri um novo Frame.
Frame(String title)
Constri um novo Frame com o ttulo especificado.
Mtodos mais usados
Mtodo Descrio
static Frame[] getFrames() Retorna todos os frames criados pela aplicao.
Image getIconImage()
Retorna a imagem usada pelo Frame quando
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
210
minimizado.
MenuBar getMenuBar()
Retorna a barra de menu deste Frame.
int getState()
Retorna o estado deste Frame.
String getTitle()
Retorna o ttulo deste Frame.
boolean isResizable()
Indica se o tamanho deste Frame pode ser
mudado.
void setIconImage(Image im) Define a imagem a ser usada como cone para
este Frame.
void setMenuBar(MenuBar mb) Define o menu a ser usada como cone para
este Frame.
void setResizable(boolean r)
Define se o tamanho deste Frame pode ser
mudado.
void setState(int state)
Define o estado deste Frame.
void setTitle(String title)
Define o ttulo deste Frame.
Exemplo
Ver exemplo VI.XX.
###
Exemplo
import java.awt.*;
import java.awt.event.*;
class testeFrame3 extends FrameX
{
Button b;
class SymMouse extends MouseAdapter
{
public void mouseClicked(MouseEvent event)
{
Object object = event.getSource();
if (object == b) b.setLabel("Clik");
}
}
public testeFrame3 (String Titulo)
{
super(Titulo);
b = new Button("ola");
b.addMouseListener(new SymMouse());
this.add(b);
setSize(100,80);
}
public static void main(String args[])
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
211
{
testeFrame3 t = new testeFrame3("Teste 3");
t.show();
}
}
public class testeFrame4 extends FrameX {
public testeFrame4(String titulo) {
super(titulo);
setLayout(new GridLayout(1,2));
textField1 = new TextField(20);
add(textField1);
button1 = new Button("Duplica");
add(button1);
button1.addMouseListener(new SymMouse());
}
public synchronized void show() {
move(50, 50);
setSize(200,50);
super.show();
}
TextField textField1;
Button button1;
class SymMouse extends java.awt.event.MouseAdapter {
public void mouseClicked(java.awt.event.MouseEvent
event){
Object object = event.getSource();
if (object == button1) {
int i = Integer.parseInt(textField1.getText());
textField1.setText(""+i*2);
}
}
}
public static void main(String args[]){
new testeFrame4("Teste 4").show();
}
}
public class testeFrame5 extends FrameX {
public testeFrame5(String titulo) {
super(titulo);
setSize(220,70);
setLayout(null);
textField1 = new TextField();
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
212
textField1.setBounds(10,30,100,25);
add(textField1);
button1 = new Button("Duplica");
button1.setBounds(110,30,100,25);
button1.addMouseListener(new SymMouse());
add(button1);
}
public class testeFrame6 extends FrameX {
public testeFrame6(String titulo) {
super(titulo);
setSize(200,250);
move(50, 50);
theImage = tk.getImage("skisor.gif");
}
private static Toolkit tk = Toolkit.getDefaultToolkit();
private Image theImage;
public void paint(Graphics g) {
g.drawImage(theImage, 20, 20, getSize().width-20,
getSize().height-20, this);
}
public static void main(String args[]){
new testeFrame6("Teste 6").show();
}
}
O objeto Toolkit oferece recursos para carregar imagens da forma
correta para cada plataforma. O mtodo paint() responsvel por desenhar a
figura. Ele chamado toda vez que ocorre um evento sobre o componente, de
modo que a figura ser sempre redesenhada.
Agenda Eletrnica verso Grfica 1.0
/**
AgendaInt
Interface Grfica da agenda.
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
213
public class AgendaInt extends FrameX
{
Agenda ag;
TextArea textArea1 = new TextArea();
TextField txtNome = new TextField();
TextField txtEnd = new TextField();
TextField txtTel = new TextField();
Button btCarregar = new Button();
Button btGravar = new Button();
Button brInserir = new Button();
Button btListar = new Button();
Button btConsultar = new Button();
Label label1 = new Label();
Label lbStatus = new Label();
Label label2 = new Label();
Label label3 = new Label();
public AgendaInt()
{
ag = new Agenda();
setLayout(null);
setBackground(new Color(112,170,192));
setSize(400,320);
setVisible(false);
add(textArea1);
textArea1.setBackground(Color.white);
textArea1.setBounds(12,120,372,168);
btCarregar.setLabel("Carregar");
add(btCarregar);
btCarregar.setBackground(Color.lightGray);
btCarregar.setBounds(12,12,72,24);
btGravar.setLabel("Gravar");
add(btGravar);
btGravar.setBackground(Color.lightGray);
btGravar.setBounds(84,12,72,24);
brInserir.setLabel("Inserir");
add(brInserir);
brInserir.setBackground(Color.lightGray);
brInserir.setBounds(156,12,72,24);
btListar.setLabel("Listar");
add(btListar);
btListar.setBackground(Color.lightGray);
btListar.setBounds(228,12,84,24);
btConsultar.setLabel("Consultar");
add(btConsultar);
btConsultar.setBackground(Color.lightGray);
btConsultar.setBounds(312,12,72,24);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
214
add(txtNome);
txtNome.setBackground(Color.white);
txtNome.setBounds(60,48,144,24);
label1.setText("Nome:");
add(label1);
label1.setFont(new Font("Serif", Font.BOLD, 12));
label1.setBounds(12,48,48,24);
add(lbStatus);
lbStatus.setBackground(Color.lightGray);
lbStatus.setForeground(Color.red);
lbStatus.setBounds(0,300,396,16);
label2.setText("Telefone:");
add(label2);
label2.setFont(new Font("Serif", Font.BOLD, 12));
label2.setBounds(216,48,60,24);
add(txtTel);
txtTel.setBackground(Color.white);
txtTel.setBounds(276,48,108,24);
label3.setText("Endereo:");
add(label3);
label3.setFont(new Font("Serif", Font.BOLD, 12));
label3.setBounds(12,84,48,24);
add(txtEnd);
txtEnd.setBackground(Color.white);
txtEnd.setBounds(72,84,312,24);
setTitle("Agenda Eletnica");
// REGISTRA OS LISTENERS
SymWindow aSymWindow = new SymWindow();
this.addWindowListener(aSymWindow);
SymMouse aSymMouse = new SymMouse();
btGravar.addMouseListener(aSymMouse);
btCarregar.addMouseListener(aSymMouse);
btListar.addMouseListener(aSymMouse);
brInserir.addMouseListener(aSymMouse);
btConsultar.addMouseListener(aSymMouse);
}
public AgendaInt(String title)
{
this();
setTitle(title);
}
class SymWindow extends WindowAdapter
{
public void windowClosing(WindowEvent event)
{
Object object = event.getSource();
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
215
if (object == AgendaInt.this)
AgendaIntAwt_WindowClosing(event);
}
}
void AgendaIntAwt_WindowClosing(WindowEvent event)
{
setVisible(false);
}
class SymMouse extends MouseAdapter
{
public void mouseClicked(MouseEvent event)
{
Object object = event.getSource();
if (object == btGravar)
btGravar_MouseClicked(event);
else if (object == btCarregar)
btCarregar_MouseClicked(event);
else if (object == btListar)
btListar_MouseClicked(event);
else if (object == btConsultar)
btConsultar_MouseClicked(event);
else if (object == brInserir)
brInserir_MouseClicked(event);
}
}
void btGravar_MouseClicked(MouseEvent event)
{
gravar();
}
void btCarregar_MouseClicked(MouseEvent event)
{
carregar();
}
void btListar_MouseClicked(MouseEvent event)
{
Exibirlista();
}
void btConsultar_MouseClicked(MouseEvent event)
{
String nome = txtNome.getText();
if (nome.length()>0) exibirPessoa(nome);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
216
else lbStatus.setText(" necessrio preencher o campo
Nome!");
}
void brInserir_MouseClicked(MouseEvent event)
{
String nome = txtNome.getText();
String tel = txtTel.getText();
String end = txtEnd.getText();
if (nome.length()>0) ag.inserir(new Pessoa(nome
,tel,end));
else lbStatus.setText(" necessrio preencher o campo
Nome!");
}
/**
gravar
*/
public void gravar()
{
ObjectOutputStream fout;
try {
fout = new ObjectOutputStream(
new FileOutputStream("agenda.dat"));
fout.writeObject(ag);
fout.close();
} catch(FileNotFoundException e)
{ System.out.println("Arq. No encontrado");}
catch(IOException e){System.out.println("Erro na
gravao!");}
}
/**
carregar
*/
public void carregar()
{
ObjectInputStream fin;
try {
fin = new ObjectInputStream(
new FileInputStream("agenda.dat"));
ag = (Agenda) fin.readObject();
fin.close();
} catch(FileNotFoundException e)
{ System.out.println("Arq. No encontrado");}
catch(Exception e) {System.out.println("Erro na
leitura!");}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
217
/**
Exibirlista
*/
public void Exibirlista()
{
Pessoa p;
textArea1.setText("");
for (Enumeration e = ag.getPessoas();
e.hasMoreElements();)
{
p = (Pessoa) e.nextElement();
textArea1.append("\nNome:"+p.getNome()+"\nTelefone:"
+p.getTel()+"\nEndereo:"+p.getEnd()+"\n");
}
}
// main
public static void main(String args[])
{
(new AgendaIntAwt("Agenda")).setVisible(true);
}
/**
exibirPessoa
*/
public void exibirPessoa(String nome)
{
Pessoa p = ag.getPessoa(nome);
if (p!=null)
{
txtTel.setText(p.getTel());
txtEnd.setText(p.getEnd());
}
else textArea1.setText("Pessoa no cadastrada!");
}
}
Exerccios
Faa um programa para converter Graus Celcius em Farenheit
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
218
Captulo IX - Applets
Applets so aplicaes J ava projetadas para serem executadas por
navegadores da World Wide Web (WWW). Isto feito atravs de chamadas
especiais dentro do cdigo HTML (Hyper Text Markup Language) das pginas.
A possibilidade de desenvolver pginas HTML com a capacidade de invocar
programas em J ava foi uma das razes para o sucesso inicial, indito em termos
de linguagem de programao, de J ava. At ento, as pginas HTML eram
basicamente objetos passivos, com capacidade limitada de interao, a no ser
por meio de CGI (Common Gateway Interface), que implementa a interatividade
com o uso de cdigos executveis (geralmente escritos em Perl) rodados no
servidor. Esse tipo de arquitetura onera muito o servidor uma vez qualquer
processamento tem que ser efetuado nele.
Figura VII.1 Interao via CGI.
A idia do uso de J ava enviar cdigo para o lado cliente atravs da
rede, para que parte do processamento seja realizado no prprio cliente,
liberando o servidor para tarefas mais importantes. Claro que isto ser razovel
se o cdigo puder trafegar pela rede rapidamente. Os programas em Bytecodes
ocupam pouco espao e podem ser compactados antes de serem enviados pela
rede, o que reduz bastante o tempo de transmisso.
Cliente com browser
Servidor
Requisio de pgina Web
Pgina Web construda
pelo programa CGI
O servidor Web
executa o programa
CGI que constri a
pgina Web.
800
APO
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
219
Figura VII.2 Interao via Java.
No entanto, preciso ter cuidado quando se trata de enviar cdigo pela
rede para se executado em uma mquina cliente. Existe um grande potencial
para o desenvolvimento acidental ou proposital de programas que podem atuar
nocivamente nas mquinas clientes, seja pela leitura de dados privados, seja por
destruio no autorizada de informaes e programas. Preocupados com o isso,
os projetistas da linguagem J ava determinaram que, no caso de Applets, a
mquina virtual impede que o programa tenha acesso limitado aos recursos da
mquina. Nessa forma de execuo o programa dito estar sendo executado
dentro de uma caixa de areia (Sand Box). Esta soluo em alguns casos por
demais restritiva e tem sido relaxada nas ltimas verses de J ava para permitir o
acesso aos recursos das mquinas clientes a Applets digitalmente assinados,
denominados de Trusted (confiveis).
Outro benefcio do uso de J ava possibilidade da produo de pginas
para a WWW com animao. Inicialmente, as pginas em HTML no possuam
recurso para animao, a no ser por meio de GIFs animadas. Com J ava
possvel desenvolver animaes bem mais sofisticadas.
Para desenvolver um Applet preciso criar uma subclasse da classe classe
java.applet.Applet. Abaixo mostrada forma geral de um cdigo que
implementa um Applet:
import java.awt.*;
import java.applet.Applet;
Cliente com browser
Servidor
Requisio de pgina Web
Pgina Web e bytecodes
O servidor Web
envia pgina
Web e cdigo
embytecodes
Executa o
cdigo em
bytecodes
800
APO
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
220
public class indentificador extends Applet
{
corpo do applet
}
A figura VII.3 mostra a hierarquia de classes para a classe Applet.
Figura VII.3 Hierarquia de classes.
O exemplo VII.1 mostra o cdigo de um Applet que exibe o texto ola
mundo! quando executado.
import java.awt.*;
import java.applet.*;
public class Applet1 extends Applet
{
Label label1 = new Label();
public void init()
{
setLayout(null);
setSize(150,87);
label1.setText("Ola Mundo!");
add(label1);
label1.setBounds(24,12,84,48);
java.awt.Component
java.lang.Object
java.awt.Container
java.awt.Panel
java.applet.Applet
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
221
}
}
Exemplo VII.1 Applet simples.
O leitor pode observar algumas diferenas do cdigo do exemplo VII.1
para o cdigo do exemplo III.1 que implementava um programa que exibia ola
Mundo na console. A primeira diferena que no existe um mtodo main().
Isto ocorre porque os Applets foram projetados para serem executados por outra
aplicao: um navegador Web. A aplicao responsvel por criar uma
instncia da subclasse da classe Applet e chamar os mtodos de acordo com a
necessidade. No exemplo acima ser executado o mtodo init(), que o
primeiro mtodo executado em um Applet e executado apenas uma vez.
Para executarmos o Applet, alm de ser necessrio compil-lo, preciso
criar um arquivo com cdigo HTML com um link para o cdigo em bytecode.
Isto necessrio j que o Applet vai ser executado por um navegador. O
exemplo VII.2 mostra o cdigo HTML que possui um link para a classe Applet1.
O link para o cdigo em bytecodes pode possuir vrios parmetros. No exemplo
VII.2 so mostrados apenas os parmetros que indicam a largura e altura que o
Applet ocupar na pgina. Os outros parmetros sero abordados mais adiante.
<html>
<applet code=Applet1.class
width=400
height=300>
</applet>
</html>
Exemplo VII.2 HTML simples.
Para executar o cdigo basta direcionar o navegador para o HTML do
exemplo VII.2. O SDK possui tambm uma aplicao capaz de executar
Applets. o appletviewer. A linha de comando abaixo mostra como
executar o Applet por meio do appletviewer. Note que preciso passar o
nome do arquivo HTML como parmetro:
appletviewer applet1.html
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
222
A figura VII.4 mostra o resultado da execuo do Applet1 por meio do
appletviewer.
Figura VII.4 Execuo do Applet1.
Descrio do cdigo HTML
No entraremos em detalhes da codificao em HTML. Abordaremos
aqui apenas os parmetros relacionados com o link para o cdigo em bytecode.
A forma geral de um link deste tipo mostrada abaixo.
<html>
<applet..code= ... width=... height=...
archive=...
codebase=...
align=...
alt=...
name=...
hspace=...
vspace=...
mayscript=... >
<param name=... value=...>
...
<param name=... value=...>
</applet>
</html>
O link HTML possui vrios parmetros, sendo a maioria deles opcionais.
A tabela abaixo descreve cada um dos parmetros.
Parmetro Descrio
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
223
code Nome da classe em bytecode. Por exemplo: Applet1.class.
width Largura que o Applet vai ocupar na pgina HTML.
height Altura que o Applet vai ocupar na pgina HTML.
archive Opcional. Se a classe estiver armazenada em um arquivo J AR (J ava
Archive), ento este parmetro indica o nome do arquivo. Por
exemplo: minhasclasses.jar.
codebase Opcional. URL onde est localizada o Applet.
align
Alinhamento do Applet na pgina. (left, right, top,
texttop, middle, absmiddle, baseline, bottom e
absbottom).
alt Mensagem alternativa caso o navegador no seja capaz de executar
bytecodes.
name Nome do Applet. Pode ser usado por outros Applets na mesma
pgina para comunicao.
hspace Define o nmero de pixels livres nos lados direito e esquerdo do
Applet.
vspace Define o nmero de pixels livres acima e abaixo do Applet.
mayscript Valor booleano que indica se um Applet pode interagir com cdigo
J avascript.
param Opcional. usado para passar parmetros para o Applet. Cada
entrada param possui dois subparmetros, name e value,
indicando o nome do parmetro e o valor respectivamente. Mais
adiante ser mostrado como o cdigo J ava recebe esses parmetros.
Tabela VII.1 Parmetros do link para o cdigo em bytecodes.
Mtodos da Classe Applet
A classe Applet define um nmero razovel de mtodos. No entanto, na
maioria das aplicaes, o programador sobrescrever um pequeno subconjunto
deste mtodos. A tabela VII.2 descreve os mtodos mais utilizados na
implementao de Applets.
Mtodo Descrio
init o primeiro mtodo executado e executado apenas uma vez. utilizado
para as inicializaes do Applet.
start executado toda vez que o Applet aparece no navegador. utilizado para
iniciar a operao normal do Applet.
stop executado toda vez que o Applet passa a no ser exibido pelo navegador.
usado para terminar operaes caras em termos computacionais.
destroy executado quando o navegador no precisa mais do Applet. usado para
liberar recursos.
paint executado toda vez que o Applet aparece no navegador. Recebe uma
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
224
instncia da classe Graphics. O usurio pode solicitar a sua invocao por
meio de uma chamada ao mtodo repaint(). Neste caso o mtodo
paint() no ser chamado imediatamente, e sim escalado para ser
executado em um tempo menor do que 100msec.
Tabela VII.2 Principais mtodos da classe Applet.
Esses mtodos so invocados pelo navegador conforme as situaes descritas
acima. A motivao por trs dos mtodos start() e stop() que no faz
sentido desperdiar ciclos de processador com um Applet que no est sendo
visto.
O mtodo que talvez possa causar mais dvidas quanto a sua utilidade o
mtodo paint(). O mtodo paint() na verdade um mtodo herdado da
classe container e utilizado para desenhar em um objeto. O objeto da classe
Graphics, recebido pelo mtodo, representa a superfcie onde podem ser
feitos os desenhos e possui um conjunto de mtodos para desenhar. Para ilustrar
o uso do paint() o exemplo VII.3 mostra o cdigo de um Applet que desenha
um quadrado na tela que segue o mouse.
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class Applet2 extends Applet {
int x=0, y=0;
public void init(){
setLayout(null);
setSize(426,266);
this.addMouseMotionListener(new SymMouseMotion());
}
public void paint(Graphics g) {
if (x>0)g.drawRect(x, y, 30, 30);
}
class SymMouseMotion extends MouseMotionAdapter{
public void mouseMoved(MouseEvent event){
if (event.getSource()== Applet2.this) {
x = event.getX();
y = event.getY();
repaint();
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
225
}
}
Exemplo VII.3 Applet que desenha um quadrado que acompanha o mouse.
Note que o mtodo paint() no chamado diretamente pelo mtodo
mouseMoved(). O que ocorre que o mtodo repaint() solicita a
mquina virtual para chamar o mtodo update() que por sua vez chama o
mtodo paint(). A mquina virtual no executa imediatamente o mtodo
update(). Ela escala o mtodo update() para ser executado em pelo menos
100 milisegundos. Se antes deste perodo ocorrer outra solicitao ela ser
ignorada. O diagrama da figura VII.5 ilustra o ciclo repaint-update-paint.
Figura VII.5 Ciclo repaint-update-paint.
Ao executar o Applet do exemplo VII.3 o leitor notar que apenas um
quadrado permanece desenhado, apesar de existir cdigo apenas para desenhar e
nenhum para apagar. A pergunta : o que ocorre com os quadrados desenhados
anteriormente? Acontece que o mtodo update() sempre apaga os desenhos
que feitos anteriormente desenhando um retngulo com o tamanho da rea de
desenho preenchido com a cor de fundo. possvel sobrescrever o mtodo
update() para alterar esse comportamento, como veremos no captulo sobre
animao, no entanto necessrio sempre repintar todos os desenhos que
precisam permanecer a cada ciclo, at por que eles podem ser afetados pela
movimentao ou encobrimento da rea de desenho. No exemplo VII.3
utilizamos um mtodo do objeto da classe Graphics para desenhar um quadrado.
Essa classe possui vrios mtodos semelhantes para desenho de figuras e texto.
A tabela VII.3 descreve alguns mtodos desta classe.
Mtodo Descrio
drawArc desenha um arco elptico.
drawChars desenha o texto especificado por um array de bytes
drawline desenha uma linha entre dois pontos.
drawRect desenha um retngulo.
drawRoundRect desenha um retngulo com bordas arredondadas.
drawImage desenha um imagem
repaint() update(Graphics g)
escala (dentro de 100 ms)
paint(Graphics g)
Chama
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
226
draw3Drect desenha um retngulo 3D.
drawOval desenha um oval.
drawPolygon desenha um polgono usando um vetor de pontos.
drawString desenha um string.
fillRect desenha um retngulo preenchido.
fillRoundRect desenha um retngulo com bordas arredondadas preenchido.
fill3Drect desenha um retngulo 3D preenchido.
fillOval desenha um oval preenchido.
fillPolygon desenha um polgono usando um vetor de pontos preenchido.
getColor obtm a cor corrente.
setColor define a cor corrente.
getFont obtm a fonte corrente.
setFont define a fonte corrente.
Tabela VII.3 Principais mtodos da classe Graphics.
O exemplo VII.4 mostra os uso de alguns mtodos da classe Graphics. O
programa, ao ser executado, mostra uma figura com um texto ao usurio e cada
vez que o usurio pressiona o mouse a figura muda.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Applet3 extends Applet
{
private int i =0;
private static final int x[] = {10,100,105,80,20};
private static final int y[] = {10,15,70,40,65};
public void init()
{
setLayout(null);
setSize(200,150);
this.addMouseListener(new SymMouse());
}
public void paint(Graphics g)
{
switch(i)
{
case 0: g.setColor(Color.green);
g.fillRect(10,10,100,100);
g.setColor(Color.black);
g.drawString("Quadrado",30,50);
break;
case 1: g.setColor(Color.red);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
227
g.fillOval(10,10,100,70);
g.setColor(Color.black);
g.drawString("Oval",50,50);
break;
case 2: g.setColor(Color.blue);
g.fillPolygon(x,y,5);
g.setColor(Color.black);
g.drawString("Poligono",40,30);
break;
}
i = (i+1)%3;
}
class SymMouse extends MouseAdapter
{
public void mouseClicked(MouseEvent event)
{
if (event.getSource()== Applet3.this) repaint();
}
}
}
Exemplo VII.4 Applet que desenha vrias figuras na tela.
Exibindo uma imagem
Um dos mtodos mais interessantes desta classe Graphics o mtodo
drawImage(), que permite exibir uma imagem. O exemplo VII.5 contm o
cdigo de um applet que mostra uma imagem que muda quando o mouse
pressionado. A imagem carregada no exemplo est codificada no formato jpeg.
Os tipos de imagens suportadas dependem do navegador sendo utilizado. A
figura VII.6 mostra o resultado da execuo do Applet.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Applet4 extends Applet
{
Image img[];
private static int i=0;
public void init()
{
img = new Image[2];
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
228
img[0] = getImage(getDocumentBase(),"baleia1.jpg");
img[1] = getImage(getDocumentBase(),"baleia2.jpg");
this.addMouseListener(new SymMouse());
}
public void paint(Graphics g)
{
g.drawImage(img[i],0,0,this);
i=i==0?1:0;
}
class SymMouse extends MouseAdapter
{
public void mouseClicked(MouseEvent event)
{
if (event.getSource() == Applet4.this) repaint();
}
}
}
Exemplo VII.5 Applet que exibe imagens.
Primeiramente foi necessrio obter objetos to tipo Image. Para isso
utilizamos o mtodo getImage() que possui dois parmetros. O primeiro
uma URL que indica a localizao do arquivo contendo a figura e o segundo o
nome do arquivo da figura, que pode conter informao de diretrio relativo
URL. Se o arquivo estiver no mesmo diretrio de onde foi carregado o arquivo
HTML ento basta usar a mtodo getDocumentBase(), como no exemplo
VII.5. Se o Se o arquivo estiver no mesmo diretrio de onde foi carregado o
Applet ento basta usar o mtodo getCodeBase().
Figura VII.6 Sadas do Applet4.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
229
O mtodo getImage() retorna null se o arquivo no foi encontrado,
caso contrrio um objeto do tipo Image retornado. A carga de uma imagem
pode ser muito demorada, dependendo do tamanho formato de
armazenamento, principalmente em se tratando de imagens transmitidas atravs
de uma rede com alto trafego de dados. Alm disso, no caso de Applets, o
usurio pode mudar de pgina antes mesmo de uma imagem ser completamente
exibida. Por essas razes, o mtodo getImage() foi projetado para retornar
imediatamente, antes mesmo da carga da imagem, de modo que a tarefa de
carregar a imagem iniciada no momento em que a imagem usada e feita em
paralelo com a execuo do programa por outra linha (Thread) de execuo.
Threads so descritos em detalhes no captulo VIII. Por ora basta visualiz-los
como um tipo de processo leve que compartilha o mesmo espao de
endereamento com outros Threads.
Uma vez de posse de um objeto tipo Image podemos exibi-lo por meio
do mtodo:
Graphics.drawImage(Image img,int x,int y, ImageObserver O)
O primeiro parmetro o objeto tipo Image. Os segundo e terceiro
definem a posio dentro Applet. O quarto parmetro do tipo
ImageObserver o que necessita ser melhor descrito. O objeto passado
como quarto parmetro deve implementar a interface ImageObserver, o que
o habilita a receber notificaes sobre a carga da imagem. Como a classe
Component implementa esta interface, ento qualquer subclasse da classe
Component tambm a implementa, portanto, podemos passar o prprio Applet
como parmetro, usando a palavra chave this.
O mtodo drawImage() desenha a imagem no estgio em que ela
estiver. Deste modo, se apenas metade da imagem tiver sido carregada ento
apenas metade ser mostrada. Em alguns casos o programador pode querer
exibir uma imagem apenas quando ela for completamente carregada. Isto pode
ser feito por meio de um objeto da classe MediaTracker. A classe
MediaTracker usada para acompanhar o status de objetos de mdia. Um
objeto de mdia pode ser imagens ou sons, no entanto, no momento apenas
imagens so suportadas. O exemplo XX.XX mostra o uso de um objeto desta
classe para monitorar o status de uma imagem.
public void init() {
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
230
MediaTracker tr = new MediaTracker(this);
im = getImage(getDocumentBase(),img.gif);
tr.addImage(im,0);
try {
tr.waitForID(0);
}
catch (InterruptedException excep) {}
}
Exemplo XX.XX Uso do MediaTracker.
No exemplo XX.XX criado uma instncia da classe MediaTracker e os
objetos que devem ser monitorados so adicionados instncia por meio do
mtodo addImage(). Alm da imagem tambm atribudo um identificador
nico que ser usado para controlar a ordem de prioridade de carga do objeto.
Tambm pode ser usado para identificar subconjuntos imagens. As imagens com
nmero menor possuem maior prioridade no processo de carga em relao as
imagens com nmero maior. O incio da carga da imagem feita por meio do
mtodo:
public void waitForID(int id) throws
InterruptedException
O identificador da imagem (ou do subconjunto de imagens) passado por
parmetro para o mtodo. Este mtodo espera at que todas as imagens com o
identificador sejam carregadas. Se ocorrer algum erro na carga a imagem
considerada carregada. O programador deve usar os mtodos isErrorAny()
e isErrorID() para detectar a ocorrncia de erros.
udio
O verso J DK1.0 oferece suporte para execuo de arquivos de udio
apenas no formato AU. No entanto, o SDK1.2 estendeu este suporte para
arquivos de udio no formato AIFF, WAV, MIDI (tipo 0 e 1) e RMF. J ava pode
manipular dados de udio em 8 e 16bits. A classe usada tratamento de udio a
AudioClip, que contm os seguintes mtodos:
play() Inicia a execuo do audio clip.
loop() Executa o audio clip em um loop.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
231
stop() Para a execuo do audio clip.
Para se criar uma instncia da classe AudioClip pode-se usar o mtodo
getAudioClip() da classe Applet:
getAudioClip(URL url, String nome)
O mtodo retorna imediatamente mesmo que o arquivo de udio no
exista. O arquivo ser carregado quando o programa tentar us-lo. O Exemplo
VII.xx mostra um Applet que faz uso de um objeto AudioClip.
import java.lang.*;
import java.net.URL;
public class ExSom extends java.applet.Applet
{
AudioClip som;
public void init()
{
som = getAudioClip(getDocument(),ola.au);
}
public void start() {som.play();}
}
Exemplo VII.XX Applet que executa um arquivo de audio.
Obtendo parmetros
Na seo XX comentamos o formato do link HTML que faz referncia a
um arquivo em bytecodes. Comentamos tambm a existncia de marcadores no
formato
<param name=... value=...>
que so usados para passagem de parmetros do HTML para o programa em
bytecodes. Nesta seo mostrado o cdigo J ava necessrio para capturar esses
parmetros. De modo a facilitar a explicao faremos uso de um exemplo. O
exemplo VII.7 mostra o cdigo HTML que passa dois valores e o exemplo VII.8
mostra um cdigo em J ava que recebe os parmetros.
<HTML>
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
232
<applet code=Applet5.class width=400 height=250>
<param name=numero value=5>
<param name=nome value=Ana>
</APPLET>
</HTML>
Exemplo VII.7 Cdigo HTML passando valores.
import java.awt.*;
public class Applet5 extends java.applet.Applet
{
Label label1 = new Label();
public void init()
{
setLayout(null);
int i = Integer.parseInt(getParameter(numero));
setSize(150,87);
label1.setText(getParameter(nome)+ :+i);
add(label1);
label1.setBounds(24,12,84,48);
}
}
Exemplo VII.8 Applet que recebe parmetros.
Os valores so recebidos por meio do mtodo getParameter() que
recebe como argumento o nome do parmetro definido no cdigo HTML. Os
valores so retornados como objetos do tipo String. Se no existir um parmetro
com o nome passado para o mtodo getParameter() o retorno ser null.
O programador tambm pode definir o mtodo getParameterInfo(),
cuja nica ao retornar um array de duas dimenses, contendo as informaes
sobre os parmetros. As informaes armazenadas so o nome, tipo e descrio
de cada parmetro. Este mtodo pode ser usado pelos navegadores Web para
ajudar ao usurio a definir os valores a serem passados para o Applet.
public String[][] getParameterInfo()
{
String[][] info = {{numero,int,number qualquer},
{nome,string,nome de alguem}};
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
233
return info;
}
Exemplo VII.9 Definindo informaes sobre os parmetros .
Executando um Applet como aplicao
Algumas vezes desejamos desenvolver um programa que possa funcionar
como aplicao e como Applet. Podemos atingir este objetivo criando um
mtodo main() dentro da subclasse Applet que est sendo implementada. O
mtodo main() deve criar uma instncia da classe Frame e adicionar a ele um
objeto da subclasse do Applet. O exemplo VII.10 mostra como criar um mtodo
main() para o Applet do exemplo VII.1.
import java.awt.*;
import java.applet.*;
public class Applet6 extends Applet
{
Label label1 = new Label();
public void init()
{
setLayout(null);
setSize(150,87);
label1.setText("Ola Mundo!");
add(label1);
label1.setBounds(24,12,84,48);
}
static public void main(String[] args)
{
FrameX frame = new FrameX("OLA");
Applet6 applet = new Applet6();
frame.add("Center", applet);
frame.setSize(200,100);
frame.setVisible(true);
applet.init();
applet.start();
}
}
Exemplo VII.10 Applet com mtodo main.
Preparando Applets para produo e arquivos JARs
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
234
Aps o desenvolvimento e teste do Applet chega o momento de coloc-lo
em produo. Isto feito colocando a pgina HTML que faz referncia ao
arquivo em bytecodes, resultante da compilao do Applet, em um diretrio
acessado por um servidor Web. Voc j deve ter notado que cada classe J ava
gera um arquivo em bytecodes. Deste modo, um arquivo contendo vrias classes
em J ava gerar, aps a compilao vrios arquivos de bytecodes, um para cada
classe. No caso de Applets com um tamanho razovel pode ser gerado um
grande nmero de arquivos. Isto pode ser um problema em se tratando de uma
aplicao que projetada para ser transmitida em uma rede de longa distncia
por meio do protocolo HTTP, j que cada classe ir gerar uma transao HTTP
quando for referenciada pela primeira vez. Alm disso, apesar do cdigo em
bytecodes ser menor do que o cdigo gerado pela compilao da maioria dos
programas escritos em outras linguagens de programao seria importante
diminuir o mximo possvel o tamanho dos arquivos, de modo a minimizar o
trfego na rede. Para solucionar esses e outros problemas foi introduzido a partir
da verso 1.1 da linguagem J ava o formato de arquivo J AR (Java Archive). O
formato de arquivo J AR permite o agrupamento de vrios arquivos em um nico
arquivo. Alm disso, o formato J AR permite a compresso de dados de modo
otimizar o armazenamento e a transmisso de dados. O principais benefcios do
uso do formato J AR so os seguintes:
Menor tempo de carga de Applets: Se todos os arquivos relacionados com
um Applet esto agrupados em um nico arquivo J AR, apenas uma transao
HTTP ser necessria para carregar o Applet. Este tempo ser ainda menor
se os arquivos estiverem compactados.
Segurana: o contedo do arquivos J AR podem ser assinados digitalmente.
Deste modo, os usurios que reconhecerem a sua assinatura podem conceder
privilgios para acessar recursos que no estariam disponveis, caso
contrrio.
Portabilidade: a API para manipulao dos arquivos J AR parte integrante
do ncleo da biblioteca de classes de J ava, o que a torna independente de
plataforma.
Outros benefcios foram adicionados com o lanamento da verso 1.2 do
SDK, como por exemplo, informaes sobre verso.
Os arquivos contidos em um arquivo J AR podem ser de tipos variados como,
como bytecodes, imagens e sons, podendo pertencer a um Applet, aplicao ou
simplesmente a uma biblioteca de classes. Alm disso, um arquivo J AR pode
conter uma descrio dos arquivos armazenados, chamada de manifest. O SDK
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
235
vem com uma ferramenta para criao e manuteno de arquivos J AR. O
formato mais comum de invocao do programa :
jar [opes] destino arquivo(s)-de-entrada
onde destino o nome do arquivo, arquivo(s)-de-entrada representa o
nome dos arquivos que sero includos no arquivo J AR e opes uma
coleo de letras com o seguinte significado:
Opes Descrio
c Cria um arquivo novo.
t Lista o contedo.
x Extrai todos os arquivos.
x file Extrai o arquivo especificado.
f Indica que o nome do arquivo de sada, caso seja a criao de um arquivo, ou
de entrada caso contrrio, ser especificado. Sem essa opo o programa jar
assume que sada ou a entrada ser a padro.
m Indica que o primeiro argumento ser o nome de um arquivo manifest criado
pelo usurio.
v Gera sada com os detalhes da execuo.
O No comprime os arquivos. Usada para criar arquivos J AR que podem ser
colocados no classpath.
M No cria o arquivo manifest.
Se um subdiretrio for includo nos arquivos de entrada ento o
subdiretrio ser automaticamente inserido no arquivo J AR, incluindo os seus
subdiretrios. As informaes sobre o caminho at o arquivo tambm
armazenada.
Para invocar um Applet inserido em um arquivo J AR utilize a palavra
chave archive no arquivo HTML. O exemplo VII.11 mostra como invocar um
Applet desta forma.
<applet code=meuApplet.class
archive=meuarquivo.jar
width=width height=height>
</applet>
Exemplo VII.10 Applet com mtodo main.
No caso de uma aplicao necessrio passar o arquivo J AR como
parmetro. Na verso J DK1.1 preciso usar o comando jre no lugar do
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
236
comando java. Por exemplo, suponha que armazenamos um aplicao, cuja
classe principal Mainclass, em um arquivo arq.jar. Para execut-la
basta digitar o comando:
jre -cp arq.jar Mainclass
onde a opo cp indica que o arquivo arq.jar deve ser anexado ao
classpath. J na verso SDK1.2 usa-se o comando java, sendo que o
arquivo J AR deve conter um manifest indicando a classe principal:
java -jar arq.jar
A tabela VII.4 mostra alguns exemplos do uso do utilitrio que gera
arquivos J AR.
jar cf meuarq.jar *.class Cria um arquivo J AR com o nome meuarq.jar contendo todos
os arquivos de classes do diretrio corrente. Um arquivo
manifest gerado automaticamente.
jar cmf meuarq.jar
meuManifest.mf *.class
Como o exemplo anterior, porm o arquivo manifest
meuManifest.mf adicionado.
jar tf meuarq.jar Lista o contedo do arquivo meuarq.jar.
jar xf meuarq.jar Extrai todos os arquivos contidos em meuarq.jar.
Tabela VII.4 Exemplos do uso do comando jar.
Criando os prprios arquivos manifest
A opo m da ferramenta para criao de arquivos J AR permite adicionar
informaes ao arquivo manifest default. necessrio que o usurio crie um
arquivo contendo as adies que devem ser feitas. O formato bsico do comando
:
jar cmf arq_adies arq_jar arquivo(s)
O arquivo de adies simplesmente um arquivo texto composto por
um conjunto de declaraes. Por exemplo se o usurio quiser especificar que a
classe que deve ser usada como ponto de entrada a classe Mainclass, ento
basta inserir a seguinte linha no arquivo de adies:
Main-Class: Mainclass
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
237
Exerccios
Faa uma calculadora com o seguinte layout:
Agenda Eletrnica verso Applet 1.0
0 . =
3 2 1
6 5 4
9 8 7
/
*
-
+
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
238
Captulo X JavaBean
O que um JavaBean?
A API J avaBeans a especificao que torna possvel escrever
componentes de software na linguagem J ava. Componentes so peas de
software, anlogas a bloquinhos de montar, reutilizveis, auto-contidas e que
podem ser usadas para comporem visualmente outros componentes, Applets,
aplicaes e Servlets usando um ambiente de desenvolvimento que suporte a
especificao de J avaBeans. Componentes J avaBean so conhecidos como
Beans.
Diferente de outras ferramentas de programao, como Delphi ou VB, o
suporte ao desenvolvimento de componentes foi acrescentado, de forma
elegante, na linguagem J ava sem alter-la.
JavaBeans so classes Java comuns que seguem na sua construo uma
especificao que permite o seu uso visual em ambientes RAD.
J avaBeans foram projetados para trabalhar em conjunto com ferramentas
de desenvolvimento "J avaBeans-enabled".
JavaBeans e ferramentas RAD
As ferramentas de desenvolvimento expem as caractersticas pblicas do
Bean visualmente. Eles obtm as caractersticas do Bean (propriedades, mtodos
e eventos) em um processo conhecido como introspection. A introspection pode
ser feita de duas maneiras:
Atravs da utilizao de Reflection para o obteno dos mtodos, e do uso
das convenes para determinao dos eventos e propriedades.
Por uso de uma class de informaes denominada BeanInfo. Uma classe
BeanInfo implementa a interface BeanInfo. Uma classe BeanInfo
explicitamente lista todas as caractersticas do Bean que devem ser expostas
para o ambiente de desenvolvimento.
As to faladas propriedades so caractersticas do Bean que podem ser
mudadas durante a programao. O ambiente de desenvolvimento faz a
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
239
introspeo em um Bean para descobrir as propriedade e expo-las para
manipulao.
Os Beans utilizam eventos para se comunicarem com outros Beans. Os
ambientes de desenvolvimento pode examinar os Beans e determinarem que
eventos um determinado Bean pode disparar (fire) ou que eventos ele pode
manipular (receive).
Os mtodos das classes que compem um Bean so mtodos J ava simples,
que podem ser chamados por qualquer outras classes.
J avaBean um padro desenhado para ser utilizado por um ambientes de
desenvolvimento RAD. E todas as suas caractersticas foram projetas para
permitir o uso fcil por programadores sem modificar a linguagem J ava. Nos
prximos tpicos veremos as convenes de nomes e o funcionamento e
utilizao dessa poderosa especificao.
Propriedades
Em J avaBeans propriedade um atributo pblico simples que pode ser de
leitura/escrita, apenas leitura ou apenas escrita. Existem quatro tipos de
propriedades: simples, indexada, ligada (bound), e restrita (constrained).
Simples
Representa um valor simples (Ex.: int, float, Object, ...). Pode ser
definida com um par de mtodos getXxx/setXxx, onde xxx o nome da
propriedade. Se for definido os dois mtodos para a propriedade, esta ser de
leitura/escrita, caso seja definido apenas o mtodo getXxx a propriedade ser
apenas leitura, e finalmente se for definida apenas o mtodo setXxx ser apenas
escrita.
Quando uma propriedade for booleana, a conveno e modificada para
isXxx ou invs de getXxx (no desenho dessa caracterstica resolveram aderir a
mxima toda regra possui uma exceo).
Abaixo temos o exemplo de uma classe que define uma propriedade:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
240
Class Pessoa
{
private String nome;
private String telefone;
private String endereo;
public Pessoa(String n, String t, String e)
{
nome = n; telefone = t; endereo = e;
}
public void setNome(String n) { nome=n; }
public void setTelefone(String t) telefone = t; }
public void setEndereo(String e) { endereo = e; }
public String getNome() { return nome; }
public String getTelefone() { return telefone; }
public String getEndereo() { return endereo; }
}
A classe acima define as propriedades simples: telefone, nome e
endereo, sendo todas as trs propriedades de leitura/escrita.
Indexada
Representa um array de valores (ex.: int[], float[], Object[] , ...). Os
mtodos getXxx/setXxx que definem a propriedade devem ter como parmetro
um inteiro que ser o ndice de acesso ao array. A propriedade pode tambm
suportar getXxx/setXxx para todo o array.
O exemplo abaixo trs a definio parcial de uma classe agenda:
Public class Agenda
{
private Pessoa pessoas[];
.
.
.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
241
public Pessoa[] getPessoas(){return pessoas;}
public void setPessoas(Pessoa[] i){
this.pessoas = i;
}
public Pessoa getPessoas(int indice){
return pessoas[indice];
}
public void setPessoas(int indice, Pessoa p){
pessoas[indice] = p;
}
.
.
.
}
Neste exemplo, definimos uma propriedade indexada pessoas, que pode
ser acessada tanto na forma de uma array completo, quanto nos seus elementos,
atravs dos seus ndice.
Ligada (Bound)
Uma propriedade bound notifica outros objetos quando o seu valor e
alterado. Toda vez que o valor de uma propriedade bound modificado, a
propriedade dispara um evento PropertyChange que contm o nome, o novo
e o velho valores da propriedade.
Class Pessoa {
private String nome;
private String telefone;
private String endereo;
Private PropertyChangeSupport changes =
New PropertyChangeSupport(this);
public Pessoa(String n, String t, String e)
{nome = n; telefone = t; endereo = e;}
public
void addPropertyChangeListener(PropertyChangeListener l){
changes.addPropertyChangeListener(l);
}
public
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
242
void removePropertyChangeListener(PropertyChangeListener l)
{
changes.removePropertyChangeListener(l);
}
public void setNome(String n) {
String nomevelho = nome;
Nome = n;
Changes.firePropertyChange(nome, nomevelho, nome);
}
public void setTelefone(String t) {
String telefonevelho = telefone; telefone = t;
Changes.firePropertyChange(telefone, telefonevelho,
telefone);
}
public void setEndereo(String e) {
String endereovelho = endereo; endereo = e;
Changes.firePropertyChange(endereo, nomeendereo,
endereo);
}
public String getNome() { return nome; }
public String getTelefone() { return telefone; }
public String getEndereo() { return endereo; }
}
A classe Pessoa j foi implementada anteriormente neste captulo, as
modificaes introduzidas tornaram as propriedades nome, telefone e endereo
ligadas, i. e., sempre que elas sofrerem alteraes, os listener que implementam
PropertyChangeListener e esto registrados como ouvintes da nossa
instncia da classe, sero notificados.
Alm das alteraes no corpo dos mtodos setXxx, que adicionou o
cdigo que dispara o evento PropertyChange, nosso Bean tambm ganhou
um novo objeto changes e dois mtodos que cuidam do registro e excluso de
listener.
Restringidas(Constrained)
Um objeto com propriedade restrita permite que outros objetos vetem a
alterao do valor dessa propriedade. listener de propriedades restritas podem
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
243
vetar uma mudana de valor da propriedade atravs de uma exceo
PropertyVetoException que levantada. Geralmente, apesar de no ser
obrigatrio, as propriedades restringidas tambm so ligadas.
class CartoCrdito
{
private String nmero;
private PropertyChangeSupport changes =
new PropertyChangeSupport(this);
private VetoableChangeSupport vetos =
new VetoableChangesSupport(this);
public
addVetoableChangeListener(VetoableChangeListener l){
vetos.addVetoableChangeListener(l);
}
public
removeVetoableChangeListener(VetoableChangeListener l){
vetos.removeVetoableChangeListener(l);
}
.
.
.
public void setNmero(String n) {
String numeroVelho = numero;
Vetos.fireVetoableChange(nmero,numeroVelho,n);
nmero = n;
changes.firePropertyChange(nmero,numeroVelho,numero);
}
.
.
.
}
No exemplo acima definimos parcialmente uma classe com o nome
CartoCrdito, esta classe possui uma propriedade de nome nmero que uma
propriedade restringida. Para implementamos esta caracterstica, primeiro
introduzimos uma novo objeto, veto, que nos d o suporte ao registro dos
listener que tero poder de veto sobre a propriedade.
Em seguida aparecem dois mtodos que cuidam apropriadamente,
repassando para VetoableChangeSupport, do registro dos listener que
podem vetar alteraes.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
244
A parte mais interessante fica por conta do mtodo setNmero, ele muito
parecido com um mtodo de uma propriedade ligada, mas acrescenta uma linha
antes de alterar o valor da varivel nmero. Sendo assim, a alterao s ser
realizada, se o evento disparado com fireVetoableChange no levantar
nenhuma exceo. Depois disso tudo, as coisa voltam a funcionar como em uma
propriedade ligada convencional.
Eventos
Sempre que estudamos algo, inicialmente obtemos uma grande
quantidade de informaes e depois comeamos a fazer generalizaes
transformando o estudado em conhecimento. Bem, at agora vimos que
J avaBeans um padro que nos permite utilizar um ambiente de programao
RAD, e vimos algumas caractersticas de classes que seguem este padro.
Mas alm desse padro definir como as classes interage com o ambiente
de programao, ele tambm define como objetos destas classes interagem entre
si. Aparece agora o conceito de eventos, que j vimos em captulo anterior e
agora veremos com as convenes de nossa API de componentes.
Um bom lugar para comearmos : o que um evento? Para nossos
propsitos um evento um objeto que encapsula dados a respeito de alguma
coisa que ocorreu. Por exemplo, o mouse foi movido, uma tecla foi digitada,
chegou um pacote UDP pela rede. Todas estas ocorrncias podem ser modeladas
como eventos e informaes sobre o que aconteceu podem ser inclusas no objeto
evento.
S para relembrar, no novo modelo de eventos da biblioteca de classes
J ava, um evento e escutado por classes que esto capacitadas para trat-los,
estas classes so chamadas de EventListener, e so um mecanismo geral de
comunicao entre objetos sem a utilizao de herana.
Nesta seo, devemos nos preocupar apenas com as convenes de
nomes de eventos e classes relacionadas para utilizao na construo de Beans.
Suponhamos que nos desejamos construir um Bean de nome Timer. Nosso
evento teria o nome TimerEvent, e nosso Listener para este evento
TimerEventListener.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
245
Na prxima seo veremos como juntar todos estes conceitos e o que
aprendemos ate agora em um exemplos de Bean completo um no-visual, um
Bean visual ser mostrado no captulo sobre MVC.
Um Bean para ser visual deve ser subclasse de java.awt.Component ou de
classes que herdem java.awt.Component.
Desenvolvimento do exemplo
O Bean de exemplo que estudaremos agora um componente que dispara
um evento periodicamente em um intervalo de tempo definido pelo seu
utilizador, este componente e semelhante ao componente Timer do Delphi e ao
ActiveX Timer do VB. Suas aplicaes incluem atualizar o display de um
relgio ou acionar o mtodo que mostra o prximo frame de uma animao.
Nosso primeiro Bean ser composto das seguintes classes:
TimerBean - A classe principal do Bean;
TimerEvent - A classe do evento disparado pelo Bean;
TimerEventListener - A interface ouvinte para o evento do Bean;
TimerEventListener
A classe TimerEventListener implementa a interface que ser utilizada para que
o nosso Bean notifique seus listeners sobre cada evento.
Package timer;
public interface TimerEventListener extends
java.util.EventListener
{
void timerEventDisparado(TimerEvent te);
}
Todos os listeners para J avaBeans devem herdar java.util.EventListener
ou de alguma subclasse dela. O nome da interface deve ser XxxxListener, onde
Xxxx corresponde ao nome do evento que esta interface habilita a tratar. No
nosso exemplo temos o evento TimerEvent e consequentemente a interface se
chama TimerEventListener.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
246
Uma interface listener pode declarar quantos mtodos seu desenvolvedor
desejar. Normalmente estes mtodos tm como parmetro um objeto event. No
nosso caso declaramos somente um mtodo.
TimerEvent
A classe TimerEvent implementa o evento que ser passado para cada
TimerEventListener.
package timer;
public class TimerEvent extends java.util.EventObject
{
public TimerEvent(Object source)
{
super(source);
}
}
Todos eventos J avaBeans devem herdar java.util.EventObject e seu nome
deve obedecer ao padro XxxxEvent, onde Xxxx arbitrrio. No nosso caso
ficamos com o nome TimerEvent.
Nosso construtor para a classe TimerListener tem como parmetro um
objeto do tipo Object, e quando este construtor for chamado passaremos a
referncia para o objeto que o esta chamando.
Eventos, por serem classes comuns, tambm podem carregar informaes
adicionais, o que no o nosso caso.
TimerBean
Esta a nossa classe principal, e onde realmente implementamos nosso
Bean.
package timer;
import java.util.*;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
247
import java.beans.*;
public class TimerBean implements
java.io.Serializable, Runnable
{
protected long intervalo = 1000;
transient protected Thread th;
protected java.util.Vector listeners = new
java.util.Vector();
private boolean ativo = false;
private java.beans.PropertyChangeSupport mudancas = new
java.beans.PropertyChangeSupport(this);
public TimerBean()
{
super();
th = new Thread(this);
th.start();
}
public void addPropertyChangeListener(
PropertyChangeListener l)
{
mudancas.addPropertyChangeListener(l);
}
public void addTimerEventListener(TimerEventListener tl)
{
listeners.addElement(tl);
}
public void disparaEvento(TimerEvent e)
{
Vector v;
synchronized (this)
{
v = (Vector) listeners.clone();
}
for (int elem = 0; elem < v.size(); elem++)
{
((TimerEventListener)
v.elementAt(elem)).timerEventDisparado(e);
}
}
public long getIntervalo()
{
return intervalo;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
248
}
public synchronized void inicia()
{
ativo = true;
}
public synchronized void para()
{
ativo = false;
}
public void
removePropertyChangeListener(PropertyChangeListener l)
{
mudancas.removePropertyChangeListener(l);
}
public void removeTimerEventListener(TimerEventListener tl)
{
listeners.removeElement(tl);
}
public void run()
{
try
{
while (true)
{
th.sleep(intervalo);
if (ativo)
{
TimerEvent evento = new TimerEvent(this);
disparaEvento(evento);
}
}
}catch (Exception e) {e.printStackTrace(); }
}
public void setIntervalo(long interv)
{
long valorVelho = intervalo;
intervalo = interv;
mudancas.firePropertyChange("intervalo",
new Long(valorVelho), new Long(intervalo));
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
249
Comecemos pelo princpio. Todos os Beans devem ser serializveis, este
o mecanismo que normalmente utilizado para armazenar aplicaes
J avaBeans. Para tornarmos nossa classe serializvel declaramos que esta
implementa a interface java.io.Serializable e marcamos nossos campos que no
so serializveis como transient ou providenciarmos mtodos de serializao
customizados.
Nossa classe tambm implementa Runnable para podermos utiliz-la em
um thread. Em nossa classe possumos os campos:
1. intervalo: que armazena de quanto em quanto tempo desejamos que um
evento seja disparado. Atravs dos mtodos getIntervalo() e
setIntervalo(long) implementamos uma propriedade bound de nome
intervalo.
2. th: Este campo transient, isto , quando esta classes for serializada esta
informao no ser gravada. Para nosso Bean th o thread que
periodicamente dispara eventos para seus listeners.
3. listeners: Um Vector armazena a lista de listeners que esto registrados neste
Bean para receber os eventos. Novos mtodos so colocados em nossa
classes para registrar ou remover listeners, este mtodos tem nomes que
seguem o padro J avaBeans e tm as formas addXxxx e removeXxxx,
onde Xxxx o nome do tipo de listener que deve ser registrado ou removido.
No nosso exemplo, temos addTimerEventListener e
removeTimerEventListener.
4. ativo: este campo utilizado para indicar para o Bean se ele deve ou no
disparar eventos para os seus listeners. Ativo no acessado diretamente, e
sim atravs dos mtodos sincronizado para() e inicia().
Os mtodos que merecem destaque so:
1. run(): mtodo que implementa o thread, em nosso caso ele contm
um lao infinito e dentro do lao, depois de fazer nosso thread
dormir, com sleep, ele verifica se deve disparar um evento. Se deve
dispar-lo, um evento e criado e o mtodo disparaEvento e chamado.
2. disparaEvento(TimerEvent e): inicialmente este mtodo cria dentro
de uma seo sincronizado uma cpia do Vector listener. Em seguida
atravs de um lao for, percorre este Vector chamando o mtodo
timerEventDisparado para cada listener registrado.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
250
Temos agora um exemplo completo de um J avaBeans. Mas esta tecnologia tem
pouca ou nenhuma utilidade se no a utilizarmos com ferramentas de
programao visual como Visual Age, Visual Caf, BDK e tantos outros.
Como o BDK de graa, ns o utilizaremos para mostrar nosso Bean em
ao.
Instalando o Beans Development Kit (BDK)
O Beans Development Kit (BDK) uma aplicao J ava pura, portanto s
depende do SDK para rodar. O BDK possui suporte para a API J avaBeans e um
container de teste (BeanBox), que manipula Beans visualmente.
Para instalar o BDK basta ter na maquina o SDK instalado (acima do
1.1.4), entrar na pagina http://www.javasoft.com e fazer download e
descompact-lo. Pronto, e s rodar. Acompanhando o BDK temos tambm
documentao e J avaBeans com cdigo fonte para serem explorados.
Testando exemplo no BDK
Para rodar o BDK utilizamos o arquivo run.bat ou run.sh, dependendo do
seu sistema operacional. Quando o aplicativo e inicializa sua rea de trabalha
fica parecido com a figura abaixo. O BDK composto de 3 janelas:
BeanBox: que a janela onde os Beans so manipulados
visualmente;
ToolBox: uma lista de Beans que podem ser usados;
Properties: um janela que se altera dependendo do Bean que esta
selecionado no BeanBox. Ela mostra as propriedades do Bean
selecionado e atravs dela o desenvolvedor pode alterar estas
propriedade no Componente;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
251
Com o BDK rodando nosso prximo passo e criar um arquivo jar
contendo o nosso Bean compilado.
Para criarmos um jar contendo Beans, devemos informar para a
ferramenta na qual este Bean ser utilizado, quais classes so Beans. Para isso
utilizamos o arquivo de manifesto do jar. Que ficaria assim para o nosso caso:
Nome do arquivo: manifest.mf
Manifest-Version: 1.0
Name: timer/TimerBean.class
Java-Bean: True
Name: timer/TimerEventListener.class
Name: timer/TimerEvent.class
Para criar o arquivo jar, dentro do diretrio que contenha o diretrio
timer, que onde esto nossas classes compiladas, digite:
jar cvfm timer.jar manifest.mf .
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
252
Com nosso jar criado temos agora que apresenta-lo ao BDK. Para isso
devemos utilizar a opo File->LoadJ ar do menu da J anela BeanBox.
Escolhemos ento o arquivo jar que geramos, e o BDK ir carrega-lo. Aps
carregar nosso Bean a lista de Beans do ToolBean ser adicionada de um entrada
chamada TimerBean, como mostrado na figura abaixo:
Agora tudo mais divertido, acabou a parte chata!!!
Vamos comear a colocar os Beans na janela BeanBox para criarmos
uma aplicao. Devemos colocar os seguintes Beans:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
253
Bean Propriedade(mudada) Novo valor
Ourbutton label Iniciar
Ourbutton label Parar
TimerBean intervalo 2000
EventMonitor
A posio dos Beans deve ser como na figura abaixo:
Depois de colocar todos os Beans no lugar e mudarmos suas
propriedades, devemos conectar os eventos nos mtodos corretos de cada Bean.
Para ligar um evento disparado por um Bean a um mtodo de outro, devemos
selecionar o primeiro e clicarmos em Edit->Events, escolhermos o evento e
clicarmos no Bean alvo. Um dialogo aparecer com os mtodos que podem ser
escolhidos para serem chamados.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
254
Bean fonte Evento Bean alvo Mtodo
TimerBean TimerEvent-
timerEventDisparado
EventMonitor InitiateEventSourceMonito
ring()
OurButton
(iniciar)
action-actionPerformed TimerBean inicia()
OurButton
(parar)
action-actionPerformed TimerBean para()
A figura abaixo mostra parte da operao.
Depois de tudo ligado, para testar basta clicar no boto de iniciar, ento
eventos sero disparados e aparecero no Monitor de eventos. Depois clique no
boto parar parar para que os eventos deixem de ser disparados pela instncia de
TimerBean . Uma opo interessante para teste no BDK e clicarmos na opo de
menu View->Disable Design Mode.
A figura abaixo mostra o teste do Bean.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
255
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
256
Captulo XI - Concorrncia
Um sistema operacional dito concorrente se permite que mais que uma
tarefa seja executada ao mesmo tempo. Na prtica a concorrncia real ou
paralelismo s possvel se o hardware subjacente possui mais de um
processador. No entanto, mesmo em computadores com apenas um processador
possvel obter um certo tipo de concorrncia fazendo com o processador
central execute um pouco de cada tarefa por vez, dando a impresso de que as
tarefas esto sendo executadas simultaneamente.
Dentro da nomenclatura empregada, uma instncia de um programa em
execuo chamada de processo. Um processo ocupa um espao em memria
principal para o cdigo e para as variveis transientes (variveis que so
eliminadas ao trmino do processo). Cada processo possui pelo menos uma linha
de execuo (Thread). Para ilustrarmos o que uma linha de execuo suponha
um determinado programa prog1. Ao ser posto em execuo criado um
processo, digamos A, com uma rea de cdigo e uma rea de dados e iniciada
a execuo do processo a partir do ponto de entrada. A instruo inicial assim
como as instrues subsequentes formam uma linha de execuo do processo A.
Portanto, um thread nada mais que uma sequncia de instrues que est em
execuo de acordo com que foi determinado pelo programa. O estado corrente
da linha de execuo representada pela instruo que est sendo executada. A
figura IX.1 mostra a relao entre estes elementos.
arquivo prog1 Memria Principal
Figura IX.1 Relao entre Programa, Processo e Thread.
possvel existir mais de uma linha de execuo em um nico processo.
Cada linha de execuo pode tambm ser vista como um processo, com a
101001101
010110010
010101100
100011101
100101010
101001010
rea de dados
rea de cdigo
Linha de execuo
(thread)
Processo
101001101
010110010
010101100
100011101
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
257
diferena que enquanto cada processo possui sua rea de cdigo e dados
separada de outros processos, os threads em um mesmo processo compartilham
o cdigo e a rea de dados. O que distingue um thread de outro em um mesmo
processo a instruo corrente e uma rea de pilha usada para armazenar o
contexto da sequncia de chamadas de cada thread. Por isso os threads tambm
so chamados de processos leves (light process). A figura IX.2 mostra
esquematicamente a diferena entre processos e threads.
Memria Processo
Figura IX.2 (a) Processos; (b) Threads.
Sistemas monotarefas e monothreads como o DOS possuem apenas um
processo em execuo em um determinado instante e apenas um thread no
processo. Sistemas multitarefas e monothreads como o Windows 3.1 permitem
vrios processos em execuo e apenas um thread por processo. Sistemas
multitarefas e multithread como o Solaris, OS/2, Linux e Windows 95/98/NT
permitem vrios processos em execuo e vrios threads por processo.
Como os threads em um mesmo processo possuem uma rea de dados em
comum, surge a necessidade de controlar o acesso a essa rea de dados, de modo
que thread no leia ou altere dados no momento que esto sendo alterados por
outro thread. A incluso de instrues para controlar o acesso a reas
compartilhadas torna o cdigo mais complexo do que o cdigo de processos
monothreads.
Uma pergunta pode surgir na mente do leitor: se a incluso de mais de
um thread torna o cdigo mais complexo porque razo eu deveria projetar
cdigo multithread. Processos com vrios threads podem realizar mais de uma
10100
01001
11001
01010
1010
0111
10100
01001
11001
01010
1010
0111
10100
01001
11001
01010
1010
0111
A
B
C
1010001001110
0101010101010
1010000101101
1010100010101
0101011011001
0101010100101
0101010010101
0101001000000
1010101010101
10100111001
01010101010
10101010101
01010101000
11110101010
Thread 1
Thread 2
Cdigo
Dados
rea de pilha do thread1
rea de pilha
do thread2
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
258
tarefa simultaneamente. So teis na criao de processos servidores, criao de
animaes e no projeto de interfaces com o usurio que no ficam travadas
durante a execuo de alguma funo. Por exemplo, imagine um processo
servidor a espera de requisies de servios, podemos projet-lo de modo que ao
surgir uma solicitao de um servio por um processo cliente ele crie um thread
para atender a solicitao enquanto volta a esperar a requisio de novos
servios. Com isto os processos clientes no precisam esperar o trmino do
atendimento de alguma solicitao para ter sua requisio atendida.
O mesmo pode ser dito em relao ao projeto de interfaces com o
usurio. O processo pode criar threads para executar as funes solicitadas pelo
usurio, enquanto aguarda novas interaes. Caso contrrio, a interface ficaria
impedida de receber novas solicitaes enquanto processa a solicitao corrente,
o que poderia causar uma sensao de travamento ao usurio.
Outra aplicao para processos multithread a animao de interfaces.
Nesse caso cria-se um ou mais threads para gerenciar as animaes enquanto
outros threads cuidam das outras tarefas como por exemplo entrada de dados.
A rigor todas as aplicaes acima como outras aplicaes de processos
multithread podem ser executados por meio de processos monothreads. No
entanto, o tempo gasto na mudana de contexto entre processos na maioria dos
sistemas operacionais muito mais lenta que a simples alternncia entre threads,
uma vez que a maior parte das informaes contextuais so compartilhadas pelos
threads de um mesmo processo.
Mudana de Contexto (task switch)
o conjunto de operaes necessrias para gravar o estado atual do processo corrente e
recuperar o estado de outro processo de modo a torn-lo o processo corrente.
Mesmo que voc no crie mais de um thread todo processo J ava possui
vrios threads: thread para garbage collection, thread para monitoramento de
eventos, thread para carga de imagens, etc.
Criando threads em Java
Processos Multithread no uma inveno da linguagem J ava. possvel
criar processos multithread com quase todas as linguagens do mercado, como
C++, e Object Pascal. No entanto J ava incorporou threads ao ncleo bsico da
linguagem tornado desta forma mais natural o seu uso. Na verdade o uso de
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
259
threads est to intimamente ligado a J ava que quase impossvel escrever um
programa til que no seja multithread.
A classe Thread agrupa os recursos necessrios para a criao de um
thread. A forma mais simples de se criar um thread criar uma classe derivada
da classe Thread. Por exemplo:
class MeuThread extends Thread {
...
}
preciso tambm sobrescrever o mtodo run() da classe Thread. O
mtodo run() o ponto de entrada do thread, da mesma forma que o mtodo
main() ponto de entrada de uma aplicao. O exemplo IX.1 mostra uma
classe completa.
public class MeuThread extends Thread {
String s;
public MeuThread (String as) {
super();
s = new String(as);
}
public void run() {
for (int i = 0; i < 5; i++)
System.out.println(i+ +s);
System.out.println("FIM! "+s);
}
}
Exemplo IX.1 Subclasse da classe Thread.
No exemplo IX.1foi inserido um atributo para identificar o thread, apesar
de existir formas melhores de se nomear um thread como veremos mais adiante.
O mtodo run() contm o cdigo que ser executado pelo thread. No exemplo
IX.1 o thread imprime cinco vezes o atributo String. Para iniciar a execuo de
um thread cria-se um objeto da classe e invoca-se o mtodo start() do
objeto. O mtodo start() cria o thread e inicia sua execuo pelo mtodo
run(). Se o mtodo run() for chamado diretamente nenhum thread novo ser
criado e o mtodo run() ser executado no thread corrente. O exemplo IX.2
mostra uma forma de se criar um thread usando a classe definida no exemplo
IX.1.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
260
public class TesteThread1 {
public static void main (String[] args) {
new MeuThread("Linha1").start();
}
}
Exemplo IX.2 Criao de um Thread.
No exemplo acima apenas um thread, alm do principal criado. Nada
impede que sejam criados mais objetos da mesma classe para disparar um
nmero maior de threads. O exemplo IX.3 mostra a execuo de dois threads
sobre dois objetos de uma mesma classe.
public class TesteThread2 {
public static void main (String[] args) {
new MeuThread("Linha1").start();
new MeuThread("Linha2").start();
}
}
Exemplo IX.3 Criao de dois Threads.
Cada thread executado sobre uma instncia da classe e, por
consequncia, sobre uma instncia do mtodo run(). A sada gerada pela
execuo do exemplo IX.3 depende do sistema operacional subjacente. Uma
sada possvel a seguinte:
0 Linha2
0 Linha1
1 Linha2
1 Linha1
2 Linha2
2 Linha1
3 Linha2
3 Linha1
4 Linha2
4 Linha1
FIM! Linha2
FIM! Linha1
A sada acima mostra que os threads executam intercaladamente. No
entanto, em alguns sistemas operacionais os threads do exemplo IX.3
executariam um aps o outro. A relao entre a sequncia de execuo e o
sistema operacional e dicas de como escrever programas multithread com
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
261
sequncia de execuo independente de plataforma operacional sero em uma
seo mais adiante neste mesmo captulo.
Criando threads por meio da interface Runnable
Algumas vezes no possvel criar uma subclasse da classe Thread
porque a classe j deriva outra classe, por exemplo a classe Applet. Outras
vezes, por questes de pureza de projeto o projetista no deseja derivar a classe
Thread simplesmente para poder criar um thread uma vez que isto viola o
significado da relao de classe-subclasse. Para esses casos existe a interface
Runnable. A interface Runnable possui apenas um mtodo para ser
implementado: o mtodo run(). Para criar um thread usando a interface
Runnable preciso criar um objeto da classe Thread, passando para o
construtor uma instncia da classe que implementa a interface. Ao invocar o
mtodo start() do objeto da classe Thread, o thread criado, inicia sua
execuo no mtodo run() da instncia da classe que implementou a interface.
O exemplo IX.4 mostra a criao de um thread usando a interface Runnable.
public class TesteThread2 implements Runnable
{
private String men;
public static void main(String args[])
{
TesteThread2 ob1 = new TesteThread2 (ola);
Thread t1 = new Thread(ob1);
t1.start();
}
public TesteThread2 (String men) {this.men=men;}
public void run()
{
for(;;) System.out.println(men);
}
}
Exemplo IX.4 Criao de um thread por meio da interface Runnable.
Note que agora ao invocarmos o mtodo start() o thread criado
iniciar a execuo sobre o mtodo run() do objeto passado como parmetro, e
no sobre o mtodo run() do objeto Thread.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
262
Nada impede que seja criado mais de um thread executando sobre o
mesmo objeto:
Thread t1 = new Thread(ob1);
Thread t2 = new Thread(ob1);
Neste caso alguns cuidados devem ser tomados, uma vez que existe o
compartilhamento das variveis do objeto por dois threads. Os problemas que
podem advir de uma situao como esta sero tratados mais adiante.
A classe Thread
A classe Thread extensa, possuindo vrios construtores, mtodos e
variveis pblicas. Aqui mostraremos apenas os mais usados.
Hierarquia
A classe Thread deriva diretamente da classe Object.
java.lang.Object
java.lang.Thread
Construtores
Construtor Descrio
Thread(ThreadGroup g, String nome) Cria um novo thread com o nome
especificado dentro do grupo g.
Thread(Runnable ob, String nome) Cria um novo thread para executar
sobre o objeto ob, com o nome
especificado.
Thread(ThreadGroup g, Runnable ob,
String nome)
Cria um novo thread para executar
sobre o objeto ob, dentro do grupo
g, com o nome especificado.
Thread(String nome) Cria um novo thread com o nome
especificado.
Thread() Cria um novo thread com o nome
default.
Thread(Runnable ob) Cria um novo thread para executar
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
263
sobre o objeto ob.
Thread(ThreadGroup g, Runnable ob) Cria um novo thread para executar
sobre o objeto ob, dentro do grupo
g.
Tabela IX.1 Construtores da classe Thread.
A tabela X.1 mostra os principais construtores da classe Thread.
Podemos notar que possvel nomear os threads e agrup-los. Isto til para
obter a referncia de threads por meio do seu nome.
Mtodos
Mtodo Descrio
currentThread() Retorna uma referncia para o thread corrente em
execuo.
destroy() Destroi o thread sem liberar os recursos.
dumpStack() Imprime a pilha de chamadas do thread corrente.
enumerate(Thread[] v) Copia para o array todos os thread ativos no
grupo do thread.
getName() Obtm o nome do thread.
getPriority() Obtm a prioridade do thread.
getThreadGroup() Retorna o grupo do thread.
resume() Reassume a execuo de um thread previamente
suspenso.
run() Se o thread foi construdo usando um objeto
Runnable separado ento o mtodo do objeto
Runnable chamado. Caso contrrio nada
ocorre.
setName(String name) Muda o nome do thread.
setPriority(int newPriority) Muda a prioridade do thread.
sleep(long millis) Suspende o thread em execuo o nmero de
milisegundos especificados.
sleep(long millis, int
nanos)
Suspende o thread em execuo o nmero de
milisegundos mais o nmero de nanosegundos
especificados.
start() Inicia a execuo do thread. A mquina virtual
chama o mtodo run() do thread.
stop() Fora o encerramento do thread.
suspend() Suspende a execuo de um thread.
yield() Faz com que o thread corrente interrompa
permitindo que outro thread seja executado.
Tabela IX.2 Mtodos da classe Thread.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
264
A tabela X.2 apresenta os principais mtodos do classe Thread. Alguns
mtodos muito usados nas verses anteriores do SDK1.2 foram depreciados na
verso atual por serem considerados inseguros ou com tendncia a causarem
deadlock . Os mtodos depreciados so: stop(), suspend(), resume() e
destroy().
Deadlock
Travamento causado pela espera circular de recursos em um conjunto de threads. O
travamento por deadlock mais simples o abrao mortal onde um thread A espera que um thread
B libere um recurso, enquanto que o thread B s libera o recurso esperado por A se obter um
recurso mantido por A. Desta forma os dois threads so impedidos indefinidamente de
prosseguir.
Existem alguns mtodos da classe Object que so importantes para o
controle dos threads. O leitor pode estar se perguntando porque mtodos
relacionados threads esto na superclasse Object que me de todas as
classe em J ava. A razo disso que esses mtodos lidam com um elemento
associado a todo objeto e que usado para promover o acesso exclusivo aos
objetos. Esse elemento chamado de monitor. Na seo que aborda a
sincronizao os monitores sero discutidos mais detalhadamente. Os mtodos
herdados relacionados com controle dos threads esto descritos na tabela IX.3.
Mtodo Descrio
notify() Notifica um thread que est esperando sobre
um objeto.
notifyAll() Notifica todos os threads que est esperando
sobre um objeto.
wait() Espera para ser notificado por outro thread.
wait(long timeout, int nanos) Espera para ser notificado por outro thread.
wait(long timeout) Espera para ser notificado por outro thread.
Tabela IX.3 Mtodos da classe Object relacionados com threads.
Variveis pblicas
As variveis pblicas da classe Thread definem valores mximo, mnimo
e default para a prioridade de execuo dos threads. J ava estabelece dez valores
de prioridade. Como essas prioridades so relacionadas com as prioridades do
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
265
ambiente operacional depende da implementao mquina virtual e pode
influenciar no resultado final da execuo do programa. Mais adiante
abordaremos a influncia do ambiente operacional na execuo de programas
multithread.
Varivel Descrio
static final int MAX_PRIORITY A prioridade mxima que um thread pode ter.
static final int MIN_PRIORITY A prioridade mnima que um thread pode ter.
static final int NORM_PRIORITY A prioridade default associado a um thread.
Tabela IX.4 Variveis pblicas.
Ciclo de Vida dos Threads
Um thread pode possuir quatro estados conforme mostra a figura IX.3.
Podemos observar que uma vez ativo o thread alterna os estados em execuo e
suspenso at que passe para o estado morto. A transio de um estado para
outro pode ser determinada por uma chamada explcita a um mtodo ou devida a
ocorrncia de algum evento a nvel de ambiente operacional ou de programa.
Estados Ativos
Figura IX.3 Estados de um thread.
A transio de um thread do estado novo para algum estado ativo
sempre realizada pela invocao do mtodo start() do objeto Thread. J as
transies do estado em execuo para o estado suspenso e vice-versa e desses
para o estado morto podem ser disparadas tanto pela invocao de variados
mtodos como pela ocorrncia de eventos. O exemplo IX.5 mostra as ocorrncia
de transio em um cdigo.
thread
novo
thread em
Execuo
thread
morto
thread
suspenso
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
266
public class TesteThread3 extends Thread
{
public TesteThread3 (String str) {super(str);}
public void run()
{
for (int i = 0; i < 10; i++)
{
System.out.println(i + " " + getName());
try {
// Comando para suspender o thread por
// 1000 milisegundos (1 segundo)
// Transio do estado em execuo para o
// estado suspenso
sleep(1000);
} catch (InterruptedException e) {}
// Evento: fim do tempo de suspenso
// Transio do estado em suspenso para o
// estado em execuo
}
System.out.println("FIM! " + getName());
// Evento: fim da execuo do thread
// Transio do estado ativo suspenso para o
// estado morto
}
public static void main(String args[])
{
TesteThread3 t1 = new TesteThread3(args[0]);
t1.start(); // Transio para um estado ativo
}
}
Exemplo IX.5 Alguns comandos e eventos que acarretam transio de
estados.
sleep(), yield(), join(), destroy(), stop(), suspend() e
resume().
Agora que vimos os estados que podem ser assumidos por um thread em
seu ciclo de vida vamos examinar mais detalhadamente alguns dos mtodos
responsveis pela mudana de estado de um thread.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
267
sleep()
O mtodo sleep() um mtodo esttico e possui as seguintes
interfaces:
static void sleep(long ms) throws InterruptedException
ou
static void sleep(long ms, int ns) throws InterruptedException
Onde ms um valor em milisegundos e ns um valor em nanosegundos.
O mtodo sleep() faz com que o thread seja suspenso por um
determinado tempo, permitindo que outros threads sejam executados. Como o
mtodo pode lanar a exceo InterruptedException, preciso envolver a
chamada em um bloco try/catch ou propagar a exceo. O exemplo IX.6
define uma espera mnima de 100 milisegundos entre cada volta do loop. Note
que o tempo de suspenso do thread pode ser maior que o especificado, uma vez
que outros threads de maior ou mesmo de igual prioridade podem estar sendo
executados no momento em que expira o tempo de suspenso solicitado.
public class ThreadComYield extends Thread {
String s;
public ThreadComYield(String as) {
super();
s = new String(as);
}
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(i+ +s);
try{
Thread.sleep(100);
catch(InterruptedException e){}
}
System.out.println("FIM! "+s);
}
}
Exemplo IX.6 Uso do mtodo sleep().
Outro problema com o sleep() que a maioria dos Sistemas
Operacionais no suportam resoluo de nanosegundos. Mesmo a resoluo a
nvel de unidade de milisegundo no suportada pela maioria dos SOs. No caso
do SO no suportar a resoluo de tempo solicitada, o tempo ser arredondado
para a nvel de resoluo suportado pela plataforma operacional.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
268
yield()
O mtodo yield() um mtodo esttico com a seguinte interface:
static void yield()
Uma chamada ao mtodo yield() faz com que o thread corrente libere
automaticamente a CPU para outro thread de mesma prioridade. Se no houver
nenhum outro thread de mesma prioridade aguardando, ento o thread corrente
mantm a posse da CPU. O exemplo IX.7 altera o exemplo IX.1 de modo a
permitir que outros threads de mesma prioridade sejam executados a cada volta
do loop.
Public class ThreadComYield extends Thread {
String s;
public ThreadComYield(String as) {
super();
s = new String(as);
}
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(i+ +s);
Thread.yield();
}
System.out.println("FIM! "+s);
}
}
Exemplo IX.7 Uso do mtodo yield().
join()
O mtodo join() um mtodo de instncia da classe Thread e
utilizado quando existe a necessidade do thread corrente esperar pela trmino da
execuo de outro thread. As verses do mtodo join() so as seguintes:
public final void join();
public final void join(long millisecond);
public final void join(long millisecond, int nanosecond);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
269
Na primeira verso o thread corrente espera indefinidamente pelo
encerramento da execuo do segundo thread. Na segunda e terceira verso o
thread corrente espera pelo trmino da execuo do segundo thread at no
mximo um perodo de tempo prefixado. O exemplo IX.8 mostra o como usar o
mtodo join().
class ThreadComJoin extends Thread {
String s;
public ThreadComJoin(String as) {
super();
s = new String(as);
}
public void run() {
for (int i = 0; i < 10; i++)
System.out.println(i+ +s);
System.out.println("Fim do thread!");
}
}
public class TestaJoin
{
public static void main(String args[])
{
ThreadComJoin t1 = new ThreadComJoin(args[0]);
t1.start(); // Transio para um estado ativo
t1.join(); // Espera pelo trmino do thread
System.out.println("Fim do programa!");
}
}
Exemplo IX.8 Uso do mtodo join().
stop(), suspend(), resume() e destroy()
A partir da verso 1.2 do SDK os mtodos stop(), suspend(), and
resume() tornaram-se deprecated uma vez que a utilizao desses mtodos
tendia a gerar erros. No entanto, devido a grande quantidade de cdigo que ainda
utiliza estes mtodo, acreditamos que seja importante mencion-los.
O mtodo stop() um mtodo de instncia que encerra a execuo do
thread ao qual pertence. Os recursos alocados ao thread so liberados.
recomendvel substituir o mtodo stop() pelo simples retorno do mtodo
run().
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
270
O mtodo suspend() um mtodo de instncia que suspende a
execuo do thread ao qual pertence. Nenhum recurso liberado, inclusive os
monitores que possuir no momento da suspenso (os monitores sero vistos mais
adiante e servem para controlar o acesso variveis compartilhadas). Isto faz
com que o mtodo suspend() tenda a ocasionar deadlocks. O mtodo
resume() um mtodo de instncia que reassume a execuo do thread ao qual
pertence. Os mtodos suspend() e resume() devem ser substitudos
respectivamente pelos mtodos wait() e notify(), como veremos mais
adiante.
O mtodo destroy() um mtodo de instncia que encerra a execuo
do thread ao qual pertence. Os recursos alocados ao thread no so liberados.
No um mtodo deprecated mas recomendvel substitu-lo pelo simples
retorno do mtodo run().
Daemon Threads
Daemon threads so threads que rodam em background com a funo de
prover algum servio mas no fazem parte do propsito principal do programa.
Quando s existem threads do tipo daemon o programa encerrado. Um
exemplo de daemon o thread para coleta de lixo.
Um thread definido como daemon por meio do mtodo de instncia
setDaemon(). Para verificar se um thread um daemon usado o mtodo de
instncia isDaemon(). O exemplo IX.9 mostra o como usar esses mtodos.
import java.io.*;
class ThreadDaemon extends Thread
{
public ThreadDaemon()
{
setDaemon(true);
start();
}
public void run()
{
for(;;) yield();
}
}
public class TestaDaemon
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
271
public static void main(String[] args)
{
Thread d = new ThreadDaemon();
System.out.println("d.isDaemon() = " +
d.isDaemon());
BufferedReader stdin = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Digite qualquer coisa");
try
{
stdin.readLine();
} catch(IOException e) {}
}
}
Exemplo IX.9 Uso dos mtodos relacionados com daemons.
No exemplo IX.9 o mtodo main() da classe TestaDaemon cria um
objeto da classe ThreadDaemon. O construtor da classe ThreadDaemon
define o thread como daemon por meio do mtodo setDaemon() e inicia a
execuo do thread. Como apenas um thread de demonstrao o mtodo run()
da classe ThreadDaemon no faz nada, apenas liberando a posse da CPU toda
vez que a adquire. Aps a criao da instncia da classe ThreadDaemon no
mtodo main() testado se o thread criado um daemon, utilizando para esse
fim o mtodo isDaemon(). Depois disso o programa simplesmente espera o
usurio pressionar a tecla <enter>. O programa termina logo em seguida ao
acionamento da tecla, mostrando dessa forma que o programa permanece ativo
apenas enquanto existem threads no daemons ativos.
Influncia do Sistema Operacional no Comportamento
dos Threads
Apesar da linguagem J ava prometer a construo de programas
independentes de plataforma operacional, o comportamento dos threads pode ser
fortemente influenciado pelo sistema operacional subjacente. Portanto, o
programador deve tomar alguns cuidados se deseja construir programas que
funcionem da mesma forma, independente do ambiente onde est sendo
executado.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
272
Alguns sistemas operacionais no oferecem suporte a execuo de
threads. Neste caso, cada processo possui apenas um thread. Mesmo em sistemas
operacionais que oferecem suporte a execuo de mltiplos threads por processo
o projetista da mquina virtual pode optar por no usar o suporte nativo a
threads. Deste modo, responsabilidade da mquina virtual criar um ambiente
multithread. Threads implementados desta forma, a nvel de usurio, so
chamados de green-threads.
As influncias da plataforma operacional podem agrupadas em dois
tipos:
1) Forma de escalonamento de threads. O ambiente pode adotar um
escalonamento no preemptivo ou preemptivo. No escalonamento
no preemptivo (tambm chamado de cooperativo) um thread em
execuo s perde o controle da CPU (Central Processing Unit) se a
liberar voluntariamente ou se necessitar de algum recurso que ainda
no est disponvel. J no escalonamento preemptivo, alm das
formas acima um thread pode perde o controle da CPU por eventos
externos, como o fim do tempo mximo definido pelo ambiente para
a execuo contnua de um thread (fatia de tempo) ou porque um
thread de mais alta prioridade est pronto para ser executado.
Exemplos de sistemas operacionais no preemptivos so Windows
3.1 e IBM OS/2. Exemplos de sistemas operacionais preemptivos so
Windows 95/98/NT e Linux, QNX, e muitos outros. Alguns sistemas
operacionais adotam uma abordagem hbrida, suportando tanto o
modelo cooperativo como o preemptivo, como o Solaris da Sun.
2) Relacionamento entre os nveis de prioridades definidas na
linguagem Java e os nveis de prioridades definidas nos Sistemas
Operacionais. Em um SO preemptivo um thread de uma
determinada prioridade perde a posse da CPU para um thread de
prioridade mais alta que esteja pronto para ser executado. A
linguagem J ava prev dez nveis de prioridades que podem ser
atribudas aos threads. No entanto, cada SO possui um nmero de
prioridades diferente e o mapeamento das prioridades da linguagem
J ava para as prioridades do SO subjacente pode influenciar o
comportamento do programa.
Forma de escalonamento de threads
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
273
A especificao da mquina virtual J ava determina que a forma de
escalonamento de threads seja preemptiva. Portanto, mesmo em ambiente
operacionais cooperativos a mquina virtual deve garantir um escalonamento
preemptivo. No entanto, um escalonamento preemptivo no obriga a preempo
por fim de fatia de tempo. Podemos ter um escalonamento preemptivo onde um
thread de mais alta prioridade interrompe o thread que tem a posse da CPU mas
no existe preempo por fim de fatia de tempo. Um escalonamento onde
threads de mesma prioridade intercalam a posse da CPU por fora do fim da
fatia de tempo chamado de escalonamento Round-Robin. A especificao da
mquina virtual J ava no prev o escalonamento Round-Robin, mas tambm no
o descarta, abrindo uma possibilidade de implementaes distintas de mquina
virtual e introduzindo o no determinismo na execuo de programas
multithread. Por exemplo, o exemplo IX.3 poderia ter uma sada distinta da
apresentada anteriormente caso seja executado por uma mquina virtual que no
implementa o escalonamento Round-Robin. Nesse caso a sada seria a seguinte:
0 Linha2
1 Linha2
2 Linha2
3 Linha2
4 Linha2
FIM! Linha2
0 Linha1
1 Linha1
2 Linha1
3 Linha1
4 Linha1
FIM! Linha1
Neste caso, se o programador deseja que a execuo de threads se
processe de forma alternada, independentemente da implementao da mquina
virtual, ento necessrio que ele insira cdigo para a liberao voluntria da
CPU. Isso pode ser feito com o mtodo yield() ou com o mtodo sleep().
Relacionamento entre os nveis de prioridades definidas na
linguagem Java e os nveis de prioridades definidas nos Sistemas
Operacionais.
Como j dissemos a linguagem J ava prev dez nveis de prioridades que
podem ser atribudas aos threads. Na verdade so onze prioridades, mas a
prioridade nvel 0 reservada para threads internos. As prioridades atribudas
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
274
aos threads so estticas, ou seja no se alteram ao longo da vida do thread, a
no ser que por meio de chamadas a mtodos definidos para esse propsito. A
classe thread possui variveis pblicas finais com valores de prioridade
predefinidos, como mostrado na tabela IX.4. No entanto, os sistemas
operacionais podem possuir um nmero maior ou menor de nveis de
prioridades. Vamos citar um exemplo: o MSWindows 95/98/NT. Este sistema
possui apenas sete nveis de prioridades e estes sete nveis devem ser mapeados
para os onze nveis de prioridades especificados em J ava. Cada mquina virtual
far este mapeamento de modo diferente, porm a implementao comum
mostrada na tabela IX.5.
Prioridades Java Prioridades MSWindows
0 THREAD_PRIORITY_IDLE
1(Thread.MIN_PRIORITY) THREAD_PRIORITY_LOWEST
2 THREAD_PRIORITY_LOWEST
3 THREAD_PRIORITY_BELOW_NORMAL
4 THREAD_PRIORITY_BELOW_NORMAL
5(Thread.NORM_PRIORITY) THREAD_PRIORITY_NORMAL
6 THREAD_PRIORITY_ABOVE_NORMAL
7 THREAD_PRIORITY_ABOVE_NORMAL
8 THREAD_PRIORITY_HIGHEST
9 THREAD_PRIORITY_HIGHEST
10(Thread.MAX_PRIORITY) THREAD_PRIORITY_TIME_CRITICAL
Tabela IX.5 Mapeamento das prioridades de Java para MSWindows.
Note que nesta implementao nveis de prioridades diferentes em J ava
sero mapeados para um mesmo nvel de prioridade em MSWindows. Isto pode
levar a resultados inesperados caso o programador projete uma aplicao
esperando, por exemplo, que um thread de prioridade 4 ir interromper um
thread de prioridade 3. Para evitar este tipo de problema o programador pode
adotar dois tipos de abordagem:
1) utilizar, se for possvel, apenas as prioridades Thread.MIN_PRIORITY,
Thread.NORM_PRIORITY e Thread.MAX_PRIORITY para atribuir prioridades
aos threads; ou
2) no se basear em nveis de prioridades para definir o escalonamento de
threads, utilizando, alternativamente, primitivas de sincronizao que sero
abordadas na prxima seo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
275
Compartilhamento de Memria e Sincronizao
Como j foi dito, mais de um thread pode ser criado sobre um mesmo
objeto. Neste caso cuidado especiais devem ser tomados, uma vez que os threads
compartilham as mesmas variveis e problemas podem surgir se um thread est
atualizando uma varivel enquanto outro thread est lendo ou atualizando a
mesma varivel. Este problema pode ocorrer mesmo em threads que executam
sobre objetos distintos, j que os objetos podem possuir referncias para um
mesmo objeto. O exemplo IX.8 mostra a execuo de dois threads sobre um
mesmo objeto. O nome do thread usado para que o thread decida que ao
tomar. O thread de nome um ontem um nmero de 0 a 1000 gerado
aleatoriamente e o coloca na posio inicial de um array de dez posies. As
outras posies do array so preenchidas com os nove nmeros inteiros
seguintes ao nmero inicial. O thread de nome dois imprime o contedo do
vetor. Obviamente o programa apenas ilustrativo, no possuindo aplicao
prtica. A inteno inicial do projetista obter na tela sequncias de dez
nmeros inteiros consecutivos iniciados aleatoriamente. No entanto, como os
dois threads compartilham o mesmo objeto e no existe qualquer sincronismo
entre s, pouco provvel que o projetista obtenha o resultado esperado.
public class CalcDez implements Runnable
{
private int vetInt[];
public CalcDez () {vetInt=new int[10]; }
public void run()
{
if (Thread.currentThread().getName().equals(um))
for (;;)
{
vetInt[0] = (int)(Math.random() * 1000);
for (int i=1;i<10;i++) vetInt[i]= vetInt[0]+i;
}
else
for (;;)
{
System.out.println(Serie iniciada por+
vetInt[0]);
for (int i=1;i<10;i++)
System.out.println(vetInt[i]+ );
}
}
public static void main(String args[])
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
276
CalcDez ob = new CalcDez();
Thread t1 = new Thread(ob,um);
Thread t2 = new Thread(ob,dois);
t1.start();
t2.start();
}
}
Exemplo IX.8 Dois threads executando sobre o mesmo objeto.
Se a mquina virtual no implementar um escalonamento Round-Robin
apenas um thread ser executado, visto que os dois threads possuem a mesma
prioridade.
J no caso da mquina virtual implementar um escalonamento Round-
Robin a alternncia da execuo dos threads produzir resultados imprevisveis.
Um trecho de uma das sadas possveis pode ser visto na figura IX.4. Ele foi
obtido em Pentium 100MHz executando a mquina virtual da Sun, verso 1.2,
sob o sistema operacional MSWindows 95.
258
259
Serie iniciada por573
574
575
576
577
578
579
580
581
582
Serie iniciada por80
81
82
Figura IX.4 Sada do exemplo IX.8.
Podemos notar as sequncias esto misturadas, mostrando que cada
thread interrompe o outro no meio da execuo da tarefa especificada. O mesmo
problema pode mesmo em threads que executam sobre objetos diferentes,
bastando que cada thread possua referncia para um mesmo objeto. O exemplo
IX.9 mostra a execuo de dois threads sobre objetos distintos.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
277
class Compartilhada
{
private int vetInt[];
public Compartilhada() {vetInt=new int[10];}
public void setVal()
{
for (;;)
{
vetInt[0] = (int)(Math.random() * 1000);
for (int i=1;i<10;i++) vetInt[i]= vetInt[0]+i;
}
}
public int getVal(int i) {return vetInt [i];}
}
public class CalcDez2 extends Thread
{
private Compartilhada obj;
private int tipo;
public CalcDez2 (Compartilhada aObj, int aTipo)
{ obj = aObj; tipo = aTipo;}
public void run()
{
for (;;)
if (tipo==1) obj.setVal();
else
{
System.out.println(Serie iniciada por+
obj.getVal(0));
for (int i=1;i<10;i++)
System.out.println(obj.getVal(i)+ );
}
}
public static void main(String args[])
{
Compartilhada obj = new Compartilhada();
CalcDez2 t1 = new CalcDez2(obj,1);
CalcDez2 t2 = new CalcDez2(obj,2);
t1.start();
t2.start();
}
}
Exemplo IX.9 Dois threads executando sobre objetos distintos.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
278
importante que o leitor no confunda o exemplo IX.9 com o exemplo
IX.8 achando que nos dois exemplos os dois threads executam sobre o mesmo
objeto, uma vez que a etapa da criao dos threads bem parecida. No entanto,
no exemplo IX.9 foi declarada uma subclasse da classe Thread e no uma
classe que implementa a interface Runnable. Apesar de parecer que no
exemplo IX.9 ambos os threads executaram sobre um mesmo objeto da classe
Compartilhada que passado como argumento, na verdade cada thread
executar sobre sua prpria instncia da classe CalcDez2, sendo que o objeto
da classe Compartilhada referenciado pelos dois threads. O
comportamento do cdigo do exemplo IX.9 semelhante ao do exemplo IX.8,
com a diferena que no primeiro a sequncia de inteiros encapsulado pelo
objeto da classe Compartilhada.
Este tipo de situao, onde o resultado de uma computao depende da
forma como os threads so escalonados, chamada de condies de corrida
(Race Conditions). um problema a ser evitado uma vez que o programa passa
a ter um comportamento no determinstico.
Atomicidade de Instrues e Sincronizao do Acesso Sesses
Crticas
A condio de corrida ocorre porque os acesso reas de memria
compartilhada no feita de forma atmica, e nem de forma exclusiva. Por
forma atmica queremos dizer que o acesso feito por meio de vrias instrues
e pode ser interrompido por outro thread antes que toda as instrues que
compem o acesso sejam executadas. Por forma exclusiva queremos dizer que
um thread podem consultar/atualizar um objeto durante a consulta/atualizao do
mesmo objeto por outros threads. Poucas operaes so atmicas em J ava. Em
geral, as atribuies simples, com exceo dos tipos long e double, so
atmicas, de forma que o programador no precisa se preocupar em ser
interrompido no meio de uma operao de atribuio. No entanto, no caso de
operaes mais complexas sobre variveis compartilhadas preciso que o
programador garanta o acesso exclusivo a essas variveis. Os trechos de cdigo
onde feito o acesso s variveis compartilhadas so chamados de Sees
Crticas ou Regies Crticas.
Uma vez determinada uma regio crtica como garantir o acesso
exclusivo? A linguagem J ava permite que o programador garanta o acesso
exclusivo por meio utilizando o conceito de monitor. O conceito de monitor foi
proposto por C. A. R. Hoare em 1974 e pode ser encarado como um objeto que
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
279
garante a excluso mtua na execuo dos procedimentos a ele associados. Ou
seja, apenas um procedimento associado ao monitor pode ser executado em um
determinado momento. Por exemplo, suponha que dois procedimentos A e B
esto associados a um monitor. Se no momento da invocao do procedimento A
algum o procedimento B estiver sendo executando o processo ou thread que
invocou o procedimento A fica suspenso at o trmino da execuo do
procedimento B. Ao trmino do procedimento B o processo que invocou o
procedimento A acordado e sua execuo retomada.
O uso de monitores em J ava uma variao do proposto por Hoare. na
linguagem J ava todo objeto possui um monitor associado. Para facilitar o
entendimento podemos encarar o monitor como um detentor de um passe.
Todo thread pode pedir emprestado o passe ao monitor de um objeto antes de
realizar alguma computao. Como o monitor possui apenas um passe, apenas
um thread pode adquirir o passe em um determinado instante. O passe tem que
ser devolvido para o monitor para possibilitar o emprstimo do passe a outro
thread. A figura IX.5 ilustra essa analogia.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
280
Instante 1: o thread t1 solicita Instante 2: o thread t2 solicita
o passe ao monitor o passe ao monitor
do objeto x. do objeto x e
bloqueado.
Instante 3: o thread t1 libera Instante 4: o thread t2 recebe
o passe. o passe do monitor
do objeto x.
Figura IX.5 Uma possvel sequncia na disputa de dois threads pela
autorizao de um monitor.
Nos resta saber como solicitar o passe ao monitor. Isto feito por meio
da palavra chave synchronized. Existem duas formas de se usar a palavra
chave synchronized: na declarao de mtodos e no incio de blocos. O
exemplo IX.10 mostra duas verses da classe FilaCirc que implementa uma
fila circular de valores inteiros: uma com mtodos synchronized e outra
com blocos synchronized. Um objeto desta classe pode ser compartilhado
por dois ou mais threads para implementar o exemplo clssico de concorrncia
do tipo produtor/consumidor.
Objeto x
Monitor de x
$ passe
thread t1
$
$
thread t2
Monitor de x
$
Monitor de x
Monitor de x
Objeto x
Objeto x
Objeto x
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
281
a) Verso com mtodos
synchronized
b) Verso com blocos
synchronized
class FilaCirc
{
private final int TAM = 10;
private int vetInt[];
private int inicio, total;
public FilaCirc()
{
vetInt=new int[TAM];
inicio=0;
total =0;
}
public synchronized void
addElement(int v) throws Exception
{
if (total == TAM) throw new
Exception("Fila cheia!");
vetInt[(inicio+total)%TAM] = v;
total++;
}
public synchronized int getElement()
throws Exception
{
if (total == 0 ) throw new
Exception("Fila vazia!");
int temp = vetInt[inicio];
inicio = (++inicio)%TAM;
total--;
return temp;
}
}
class FilaCirc
{
private final int TAM = 10;
private int vetInt[];
private int inicio, total;
public FilaCirc()
{
vetInt=new int[TAM];
inicio=0;
total =0;
}
public void addElement(int v)
throws Exception
{
synchronized(this) {
if (total == TAM) throw new
Exception("Fila cheia!");
vetInt[(inicio+total)%TAM] = v;
total++;
}
}
public int getElement()
throws Exception
{
synchronized(this) {
if (total == 0 ) throw new
Exception("Fila vazia!");
int temp = vetInt[inicio];
inicio = (++inicio)%TAM;
total--;
}
return temp;
}
}
Exemplo IX.10 Duas verses de uma classe que implementa uma fila circular
de inteiros.
A palavra chave synchronized na frente dos mtodos de instncia
significa que o mtodo ser executado se puder adquirir o monitor do objeto a
quem pertence o mtodo
4
. Caso contrrio o thread que invocou o mtodo ser
suspenso at que possa adquirir o monitor. Este forma de sincronizao
abordada no exemplo IX.10.a. Portanto, se algum thread chamar algum mtodo
de um objeto da classe FilaCirc nenhum outro thread que compartilha o
mesmo objeto poder executar um mtodo do objeto at que o mtodo chamado

4
No usaremos mais a analogia com a aquisio do passe do monitor. Ela foi usada apenas para
facilitar o entendimento do leitor. Quando se trata de monitores os termos mais usados so:
adquirir o monitor e liberar o monitor.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
282
pelo primeiro thread termine. Caso outro thread invoque um mtodo do mesmo
objeto ficar bloqueado at que possa adquirir o monitor.
O leitor pode estar se perguntando sobre a necessidade de sincronizar os
mtodos da classe FilaCirc uma vez que ocorrem apenas atribuies simples
a elementos individuais de um vetor e as atribuies de inteiros so atmicas. De
fato o problema ocorre no na atribuio dos elementos e sim na indexao do
array. Por exemplo, a instruo
inicio = (++inicio)%TAM;
do mtodo getElement() no atmica. Suponha que a os mtodos da
classe FilaCirc no so sincronizados e que as variveis inicio e total
possuem os valores 9 e 1 respectivamente. Suponha tambm que thread invocou
o mtodo getElement() e foi interrompido na linha de cdigo mostrada
acima aps o incremento da varivel inicio mas antes da concluso da linha
de cdigo. Nesse caso o valor de inicio 10. Se neste instante outro thread
executar o mtodo getElement() do mesmo objeto ocorrer uma exceo
IndexOutOfBoundsException ao atingir a linha de cdigo
int temp = vetInt[inicio];
Se alterarmos a linha de cdigo para
inicio = (inicio+1)%TAM;
evitaremos a exceo, mas no evitaremos o problema de retornar mais de uma
vez o mesmo elemento. Por exemplo, se um thread for interrompido no mesmo
local do caso anterior, outro thread pode obter o mesmo elemento, uma vez que
os valores de inicio e total no foram alterados. Na verdade o nmero de
situaes problemticas, mesmo para esse exemplo pequeno, enorme e
perderamos muito tempo se tentssemos descreve-las em sua totalidade.
Em alguns casos pode ser indesejvel sincronizar todo um mtodo, ou
pode-se desejar adquirir o monitor de outro objeto, diferente daquele a quem
pertence o mtodo. Isto pode ser feito usando a palavra chave synchronized
na frente de blocos. Este forma de sincronizao mostrada no exemplo
IX.10.b. Neste modo de usar a palavra-chave synchronized necessrio
indicar o objeto do qual tentara-se adquirir o monitor. Caso o monitor seja
adquirido o bloco executado, caso contrrio o thread suspenso at que possa
adquirir o monitor. O monitor liberado no final do bloco.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
283
No exemplo IX.10.b o monitor usado na sincronizao o do prprio
objeto do mtodo, indicado pela palavra chave this. Qualquer outro objeto
referencivel no contexto poderia ser usado. O que importa que os grupos de
threads que possuem reas de cdigo que necessitam de excluso mtua usem o
mesmo objeto.
No exemplo IX.10 no existe vantagem da forma de implementao a)
sobre a forma de implementao b) ou vice-versa. Isso ocorre principalmente
quando os mtodos so muito pequenos ou no realizam computaes muito
complexas. No entanto, se o mtodo for muito longo ou levar muito tempo para
ser executado, sincronizar todo o mtodo pode travar em demasia a execuo
da aplicao. Nesses casos, a sincronizao somente das sees crticas mais
indicada. Outra vantagem da segunda forma de sincronizao a liberdade no
uso de monitores qualquer objeto referencivel. Isto permite a implementao
sincronizaes mais complexas como veremos mais adiante.
O exemplo IX.11 mostra como pode ser usado um objeto da classe
FilaCirc.
public class TestaFilaCirc extends Thread {
private FilaCirc obj;
private int tipo;
public TestaFilaCirc (FilaCirc aObj, int aTipo)
{ obj = aObj; tipo = aTipo;}
public void run() {
for (;;)
try {
if (tipo==1){
int i = (int)(Math.random() * 1000);
System.out.println("Elemento gerado:"+i);
obj.addElement(i);
}
else System.out.println("Elemento obtido:"+obj.getElement());
} catch(Exception e) {System.out.println(e.getMessage());}
}
public static void main(String args[]) {
FilaCirc obj = new FilaCirc();
TestaFilaCirc t1 = new TestaFilaCirc(obj,1);
TestaFilaCirc t2 = new TestaFilaCirc(obj,2);
t1.start();
t2.start();
}
}
Exemplo IX.11 Uso da fila circular de inteiros.
Um trecho possvel da sada obtida na execuo do programa do exemplo
IX.11 seria o seguinte:
...
Elemento obtido:154
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
284
Elemento gerado:725
Fila vazia!
Elemento gerado:801
Elemento obtido:725
Elemento gerado:204
Elemento obtido:801
...
importante observar que o monitor em J ava por si s no implementa a
excluso mtua. Ele apenas um recurso que pode ser usado pelo programador
para implementar o acesso exclusivo variveis compartilhadas. Cabe ao
programador a responsabilidade pela uso adequado deste recurso. Por exemplo
se o programador esquecer de sincronizar um bloco ou mtodo que necessita de
excluso mtua, de nada adianta ter sincronizado os outros mtodos ou blocos.
O thread que executar o trecho no sincronizado no tentar adquirir o monitor,
e portanto de nada adianta os outros threads terem o adquirido.
Outro ponto que importante chamar a ateno ter o cuidado de usar a
palavra chave synchronized com muito cuidado. A sincronizao custa
muito caro em se tratando de ciclos de CPU. A chamada de um mtodo
sincronizado por volta de 10 vezes mais lenta do que a chamada de um mtodo
no sincronizado. Por essa razo use sempre a seguinte regra: no sincronize o
que no for preciso.
Comunicao entre Threads: wait() e notify()
O exemplo IX.10 no um modelo de uma boa implementao de
programa. O thread que adiciona elementos fila tenta adicionar um elemento
cada volta do lao de iterao mesmo que a fila esteja cheia. Por outro lado, o
thread que retira os elementos da fila tenta obter um elemento a cada volta do
lao de iterao mesmo que a fila esteja vazia. Isto um desperdcio de tempo
de processador e pode tornar o programa bastante ineficiente.
Algum poderia pensar em uma soluo onde o thread testaria se a
condio desejada para o processamento ocorre. Caso a condio no ocorra o
thread poderia executar o mtodo sleep() para ficar suspenso por algum
tempo para depois testar novamente a condio. O thread procederia desta forma
at que a condio fosse satisfeita. Este tipo de procedimento economizaria
alguns ciclos de CPU, evitando que a tentativa incessante de executar o
procedimento mesmo quando no h condies. O nome desta forma de ao,
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
285
onde o procedimento a cada intervalo de tempo pr-determinado testa se uma
condio satisfeita chamado de espera ocupada (pooling ou busy wait).
No entanto, existem alguns problemas com este tipo de abordagem.
Primeiramente, apesar da economia de ciclos de CPU ainda existe a
possibilidade de ineficincia, principalmente se o tempo no for bem ajustado.
Se o tempo for muito curto ocorrer vrios testes inteis. Se for muito longo, o
thread ficar suspenso alm do tempo necessrio. Porm, mais grave que isto
que o mtodo sleep() faz com que o thread libere o monitor. Portanto, se o
trecho de cdigo for uma regio sincronizada, como o caso do exemplo IX.10,
de nada adiantar o thread ser suspenso. O thread que capaz de realizar a
computao que satisfaz a condio esperada pelo primeiro thread ficar
impedido de entrar na regio crtica, ocorrendo assim um deadlock: o thread que
detm o monitor espera que a condio seja satisfeita e o thread que pode
satisfazer a condio no pode prossegui porque no pode adquirir o monitor.
O que precisamos um tipo de comunicao entre threads que
comunique que certas condies foram satisfeitas. Alm disso, preciso que, ao
esperar por determinada condio, o thread libere o monitor. Esta forma de
interao entre threads obtido em J ava com o uso dos mtodos de instncia
wait(), notify() e notifyAll(). Como vimos anteriormente, esses
mtodos pertencem classe Object e no classe Thread. Isto ocorre porque
esses mtodos atuam sobre os monitores, que so objetos relacionados a cada
instncia de uma classe J ava e no sobre os threads.
Ao invocar o mtodo wait() de um objeto o thread suspenso e
inserido em uma fila do monitor do objeto, permanecendo na fila at receber
uma notificao. Cada monitor possui sua prpria fila. Ao invocar o mtodo
notify() de um objeto, um thread que est na fila do monitor do objeto
notificado. Ao invocar o mtodo notifyAll() de um objeto, todos os threads
que esto na fila do monitor do objeto so notificados.
A nica exigncia que esses mtodos sejam invocados em um thread
que detenham a posse do monitor do objeto a que pertencem. Essa exigncia faz
sentido uma vez que eles sinalizam a threads que esperam na fila desses
monitores. Devido a essa exigncia a invocao desses mtodos ocorre em
mtodos ou blocos sincronizados. O exemplo IX.12 mostra as formas mais
comuns de chamadas desses mtodos.
Note que o thread deve possuir o monitor do objeto ao qual pertence o
mtodo. Por isso, nos exemplo IX.12 b e c, o objeto sincronizado no bloco o
mesmo que invoca os mtodos notify() e notifyAll().
a) b)
class X class Y
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
286
{
...
public synchronized int ma()
{
...
// Espera uma condio
while(!cond) wait();
// Prossegue com a
// condio satisfeita
...
}
...
}
{
X ob;
...
public int mb()
{
...
synchronized (ob)
{
// Notifica algum thread
ob.notify();
...
}
...
}
c)
class Z
{
X ob;
...
public int mc()
{
...
synchronized (ob)
{
// Notifica todos os threads que esperam na fila
// do monitor de ob
ob.notifyAll();
...
}
...
}
Exemplo IX.12 Exemplos de chamadas dos mtodos wait(), notify() e
notifyAll().
Outra observao importante que o thread que invoca o mtodo
wait() o faz dentro de um lao sobre a condio de espera. Isto ocorre porque
apesar de ter sido notificado isto no assegura que a condio est satisfeita. O
thread pode ter sido notificado por outra razo ou entre a notificao e a
retomada da execuo do thread a condio pode ter sido novamente alterada.
Uma vez notificado o thread no retoma imediatamente a execuo.
preciso primeiro retomar a posse do monitor que no momento da notificao
pertence ao thread que notificou. Mesmo aps a liberao do monitor nada
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
287
garante que o thread notificado ganhe a posse do monitor. Outros threads podem
ter solicitado a posse do monitor e terem preferncia na sua obteno.
O exemplo IX.12 mostra apenas um esquema para uso dos mtodos para
notificao. O exemplo IX.13 uma verso do exemplo IX.10a que usa os
mtodos de notificao para evitar problemas como a espera ocupada. O
exemplo IX.11 pode ser usado sem modificaes para testar essa verso.
class FilaCirc
{
private final int TAM = 10;
private int vetInt[];
private int inicio, total;
public FilaCirc()
{
vetInt=new int[TAM];
inicio=0;
total =0;
}
public synchronized void addElement(int v) throws Exception
{
while (total == TAM) wait();
vetInt[(inicio+total)%TAM] = v;
total++;
notify();
}
public synchronized int getElement() throws Exception
{
while (total == 0 ) wait();
int temp = vetInt[inicio];
inicio = (++inicio)%TAM;
total--;
notify();
return temp;
}
}
Exemplo IX.13 Classe que implementa uma fila circular de inteiros com
notificao.
A necessidade de se testar a condio em loop pode ser observada na
figura IX.6 que mostra a evoluo da execuo de trs threads sobre objetos que
compartilham uma instncia da classe FilaCirc. O thread 3 executa o mtodo
addElement(), no entanto, em virtude da condio total==TAM
obrigado a invocar o mtodo wait() e esperar uma notificao. O prximo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
288
thread a assumir a CPU o thread 1 que executa o mtodo getElement(), que
estabelece a condio total<TAM e executa um notify(). No entanto, o
prximo thread a assumir a CPU o thread 2 e no o thread 3. O thread 2
executa o mtodo addElement(), o qual estabelece novamente a condio
total==TAM. Quando o thread 3 assumi novamente a CPU, uma vez que foi
notificado, testa a condio e invoca novamente o mtodo wait() para esperar
a condio favorvel execuo. Caso no testasse a condio em um loop o
thread 3 tentaria inserir um elemento em uma fila cheia.
O mtodo notify() no indica que evento ocorreu. No caso do
exemplo IX.13 existem dois tipos de eventos (a fila no est cheia e a fila no
est vazia), no entanto, podemos observar que no existe a possibilidade de um
thread ser notificado em decorrncia de um evento diferente do que est
aguardando.
Tempo
Figura IX.6 Uma possvel sequncia na execuo de trs threads.
Porm, existem alguns casos mais complexos onde podem existir vrios
threads aguardando em um mesmo monitor mas esperando por evento diferentes.
Neste caso podemos usar o notifyAll() para notificar todos os threads que
esperam em um nico monitor que um evento ocorreu. Cada thread, a medida
que fosse escalado, testaria se ocorreu condio para a execuo e em caso
positivo prosseguiria na execuo e em caso contrrio voltaria a aguardar no
monitor.
O exemplo IX.14 mostra o cdigo de um gerenciador de mensagens. Ele
responsvel por receber mensagens destinadas vrios threads. As mensagens
thread 3
thread 2
thread 1
Mtodo: addElement()
condio: total == TAM
Mtodo: getElement()
Mtodo: addElement()
condio: total < TAM
Executando Esperando CPU Esperando notificao
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
289
de cada thread so colocadas em uma fila implementada por um objeto da classe
Vector. Cada fila por sua vez colocada em uma tabela hash onde a chave
um nome associado ao thread a que as mensagens se destinam. As filas so
criadas na primeira tentativa de acesso, tanto na leitura quanto no
armazenamento. No existe bloqueio devido fila cheia, uma vez que as filas
so implementadas por objetos da classe Vector que crescem conforme a
necessidade. Portanto, o nico evento que necessita ser notificado a chegada de
alguma mensagem. Como todos os threads aguardam sobre o mesmo monitor
usado o mtodo notifyAll() para notificar todos os threads.
import java.util.*;
class GerenteMen {
private Hashtable tamMen;
public GerenteMen() {tamMen=new Hashtable(); }
// Mtodo para adicionar uma mensagem fila de
// um destinatrio
public synchronized void addMen(String dest, String men){
if (dest==null || men==null) return;
Vector listaMen = (Vector) tamMen.get(dest);
if (listaMen==null) listaMen = new Vector();
listaMen.addElement(men);
tamMen.put(dest, listaMen);
notifyAll();
}
// Mtodo para obteno da mensagem
public synchronized String getMen(String dest)
throws Exception
{
if (dest==null) return null;
Vector listaMen = (Vector) tamMen.get(dest);
// Se no existe a fila para esse thread cria uma vazia
if (listaMen==null)
{
listaMen = new Vector();
tamMen.put(dest, listaMen);
}
// A fila est vazia, portanto thread deve esperar
// a chegada de mensagens
while(listaMen.size()==0) wait();
String temp = (String) listaMen.firstElement();
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
290
// A mensagem removida da fila
listaMen.removeElementAt(0);
return temp;
}
}
Exemplo IX.14 Gerenciador de mensagens.
O exemplo IX.15 mostra como pode ser usado o gerente de filas do
exemplo IX.14. Devido o uso da classe ThreadGroup assim como vrios de
seus mtodos, resolvemos numerar as linhas de cdigo do exemplo IX.15 para
melhor podermos explicar o seu funcionamento.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Receptor extends Thread
{
private GerenteMen ger;
public Receptor(ThreadGroup tg, String nome, GerenteMen aGer)
{
super(tg,nome);
ger = aGer;
}
public void run() {
String nome = Thread.currentThread().getName();
for (;;)
try {
String men = ger.getMen(nome);
if (men.equals("fim")) return;
System.out.println(nome+">Mensagem recebida:"+men);
} catch(Exception e) {System.out.println(e.getMessage());}
}
}
class Gerador extends Thread
{
private GerenteMen ger;
public Gerador(ThreadGroup tg, String nome, GerenteMen aGer)
{
super(tg,nome);
ger = aGer;
}
public void run() {
String nome = Thread.currentThread().getName();
ThreadGroup tg = Thread.currentThread().getThreadGroup();
Thread[] tl=null;
for (int i=0;i<100;i++)
{
if (tl==null || tl.length!=tg.activeCount())
tl= new Thread[tg.activeCount()];
tg.enumerate(tl);
int n = (int)(Math.random() * 1000)%tl.length;
if (tl[n]!= Thread.currentThread())
{
System.out.println(nome+">Mensagem enviada para "+
tl[n].getName()+":mensagem "+i);
ger.addMen(tl[n].getName(),"mensagem "+i);
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
291
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
}
tl= new Thread[tg.activeCount()];
tg.enumerate(tl);
for (int i=0;i<tl.length;i++)
if (tl[i]!= Thread.currentThread())
ger.addMen(tl[i].getName(),"fim");
}
}
public class TestaGerenteMen {
public static void main(String args[])throws Exception {
GerenteMen ger = new GerenteMen();
ThreadGroup tg = new ThreadGroup("tg");
Receptor r1 = new Receptor(tg,"r_um",ger);
Receptor r2 = new Receptor(tg,"r_dois",ger);
Gerador g = new Gerador(tg,"g",ger);
r1.start();
r2.start();
g.start();
}
}
Exemplo IX.15 Uso do gerenciador de filas.
Um objeto da classe ThreadGroup agrupa um conjunto de threads.
Um ThreadGroup pode possuir como membros outros objetos da
ThreadGroup formando assim uma rvore onde todos os grupos, exceto o
primeiro possui um grupo pai. O objetivo de se agrupar os threads em conjuntos
facilitar a sua manipulao. No caso do exemplo IX.15 usaremos esse
agrupamento para poder acessar cada thread.
As linhas 1 a 18 definem a classe que ser usada para criao de objetos
receptores de mensagens. Na linha 3 declarada a varivel que ir referenciar
um objeto do tipo GerenteMen. As linhas 4 a 8 contm o cdigo do nico
construtor da classe. Ele recebe uma referncia para o grupo de threads ao qual
deve se associar, o nome que deve ser atribudo ao thread e a referncia ao
gerente de filas. Na linha 6 os primeiros dois parmetros so passados ao
construtor da superclasse. Na linha 7 a referncia ao gerente de filas atribuda
varivel da instncia. As linhas 9 a 17 contm o cdigo do mtodo run() que
o mtodo de entrada do thread. Na linha 10 invocado o mtodo
Thread.currentThread().getName();
para se obter o nome do thread corrente. O nome do thread usado para
referenciar a fila de mensagens do thread. Entre as linhas 11 e 16 executado
um lao infinito onde o thread recebe e imprime as mensagens recebidas. Na
linha 14 o thread testa se a mensagem recebida igual a fim. Neste caso o
thread encerra sua execuo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
292
As linhas 20 a 51 definem a classe que ser usada para criao do objeto
gerador de mensagens. Este exemplo foi projetado para lidar com apenas um
thread gerador de mensagem. Modificaes devem ser realizadas para tratar de
aplicaes com mais de um thread gerador de mensagens. Na linha 22
declarada a varivel que ir referenciar um objeto do tipo GerenteMen. As
linhas 23 a 27 contm o cdigo do nico construtor da classe. Ele recebe uma
referncia para o grupo de threads ao qual deve se associar, o nome que deve ser
atribudo ao thread e a referncia ao gerente de filas. Na linha 25 os primeiros
dois parmetros so passados ao construtor da superclasse. Na linha 26 a
referncia ao gerente de filas atribuda varivel da instncia. As linhas 28 a
50 contm o cdigo do mtodo run() que o mtodo de entrada do thread. Na
linha 29 obtido o nome do thread corrente que ser usado na impresso de
mensagens. Na linha 30 o mtodo
Thread.currentThread().getThreadGroup();
obtm uma referncia para o grupo de threads ao qual pertence o thread corrente.
Na linha 31 declarada uma varivel que ir referenciar um vetor contendo
referncias a todos os threads ativos do grupo. Entre as linhas 32 e 44
executado um lao com 100 iteraes que produz e armazena as mensagens. Na
linha 34 realizado um teste para a verificao da necessidade de criar o vetor
que ir conter as referncias para os threads ativos. Ele deve ser criado a
primeira vez e toda vez que a capacidade do vetor for diferente do nmero de
threads ativos do grupo. O tamanho do vetor determinado pelo mtodo de
instncia activeCount() da classe ThreadGroup. A linha 36 contm o
cdigo
tg.enumerate(tl);
que atribui as referencias aos threads no vetor. O comando
int n = (int)(Math.random()*1000)%tl.length;
da linha 37 calcula um nmero que ser usado para acessar o thread dentro do
vetor de referncias. O teste da linha 38 impede que seja enviada uma mensagem
para o prprio gerador. Essas mensagens so descartadas. As linhas 40 a 42
tratam da impresso e envio da mensagem construda. J fora da iterao, as
linhas 45 a 49 tratam da do envio da mensagem fim para todos os threads
receptores, o que far com que encerrem sua execuo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
293
As linhas 53 a 64 definem a classe que ser usada como ponto de entrada
da aplicao. Ela responsvel pela criao dos objetos e disparos dos threads.
No exemplo, alm do thread gerador apenas dois threads receptores so criados.
interessante notar que no preciso indicara para o thread gerador as
referncias para os threads receptores. Elas so obtidas dinamicamente por meio
do grupo de threads.
Um trecho possvel da sada obtida na execuo do programa do exemplo
IX.15 seria o seguinte:
...
g>Mensagem enviada para r_dois:mensagem 88
r_um>Mensagem recebida:mensagem 87
g>Mensagem enviada para r_dois:mensagem 90
r_dois>Mensagem recebida:mensagem 88
g>Mensagem enviada para r_um:mensagem 91
r_dois>Mensagem recebida:mensagem 90
g>Mensagem enviada para r_um:mensagem 93
r_um>Mensagem recebida:mensagem 91
g>Mensagem enviada para r_um:mensagem 95
r_um>Mensagem recebida:mensagem 93
g>Mensagem enviada para r_um:mensagem 96
r_um>Mensagem recebida:mensagem 95
g>Mensagem enviada para r_um:mensagem 97
r_um>Mensagem recebida:mensagem 96
g>Mensagem enviada para r_dois:mensagem 99
r_um>Mensagem recebida:mensagem 97
r_dois>Mensagem recebida:mensagem 99
Pressione qualquer tecla para continuar . . .
Otimizando a Programao Multithread
Existe um problema bvio com a abordagem do exemplo IX.14: a
mensagem dirigida a apenas um thread mas todos sero notificados,
sobrecarregando o sistema, uma vez que todos os threads precisaram testar se a
mensagem destinada a eles. Para contornar esses problema necessrio
vislumbrar uma forma de notificar apenas o thread destinatrio.
Essa soluo pode ser obtida se cada thread esperar em um monitor de
um objeto diferente. No importa o tipo do objeto desde que seja referencivel
pelo thread receptor e pelo thread que ir armazenar a mensagem. Um candidato
natural a fila de mensagem de cada thread. Existe uma fila para cada thread e o
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
294
thread que armazena a mensagem tem acesso a todas a filas por meio da tabela
hash. O exemplo IX.16 mostra uma verso do exemplo IX.14 que utiliza esta
tcnica para criar uma aplicao multi-thread mais otimizada.
import java.util.*;
class GerenteMen {
private Hashtable tamMen;
public GerenteMen() {tamMen=new Hashtable(); }
// Mtodo para adicionar uma mensagem fila de
// um destinatrio
public void addMen(String dest, String men){
if (dest==null || men==null) return;
Vector listaMen = (Vector) tamMen.get(dest);
if (listaMen==null) listaMen = new Vector();
synchronized (listaMen)
{
listaMen.addElement(men);
tamMen.put(dest, listaMen);
listaMen.notify();
};
}
// Mtodo para obteno da mensagem
public String getMen(String dest)
throws Exception
{
if (dest==null) return null;
Vector listaMen = (Vector) tamMen.get(dest);
// Se no existe a fila para esse thread cria uma vazia
if (listaMen==null)
{
listaMen = new Vector();
tamMen.put(dest, listaMen);
}
// A fila est vazia, portanto thread deve esperar
while(listaMen.size()==0)
synchronized (listaMen) {listaMen.wait();}
String temp = (String) listaMen.firstElement();
// A mensagem removida da fila
listaMen.removeElementAt(0);
return temp;
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
295
Exemplo IX.16 Gerenciador de mensagens otimizado.
Note que os mtodos wait() e notify() invocados pertencem fila
relacionada com cada thread. O exemplo IX.15 pode ser usado sem
modificaes para testar essa verso.
Criando outros mecanismos de sincronizao
Existem vrias propostas de primitivas de sincronizao. Dentre as mais
comuns podemos citar os semforos, mutex, variveis condicionais, monitores e
encontros (rendevouz). Cada uma dessas primitivas mais adequada a um
determinado propsito. A implementao de monitores na linguagem J ava,
juntamente com os mtodos wait() e notify() que formam um tipo de
variveis condicionais podem ser combinadas para implementar muitas dessas
outras primitivas, de modo a atender objetivos especficos. Para exemplificar
essa possibilidade mostraremos como implementar um semforo usando as
primitivas de sincronizao da linguagem J ava.
Um semforo uma varivel inteira sobre a qual pode-se realizar as
seguintes operaes:
Operao Descrio
inicializar Um valor inteiro maior ou igual a zero atribudo ao semforo.
P Se o semforo maior que zero, o semforo decrementado. Caso
contrrio, o thread suspenso at que o semforo contenha um
valor maior que zero.
V Incrementa o semforo e acorda os threads que estiverem
bloqueados na fila de espera do semforo.
Tabela IX.6 Operaes sobre um semforo.
Semforo um mecanismo de sincronizao muito utilizado quando
existe a necessidade de comunicao entre dois ou mais processos, como no caso
de sistemas do tipo produtor/consumidor. Por exemplo, suponha dois processos
onde um coloca mensagens em buffer e outro retira as mensagens. Os processos
podem usar dois semforos para sincronizar o acesso ao buffer de mensagens:
um para controlar a entrada na regio crtica e outro para contar o nmero de
mensagens. A figura IX.xx mostra os esquemas dos processos. A implementao
dos semforos em J ava pode ser visto no exemplo IX.xx e o uso dos semforos
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
296
em uma situao como a ilustrada pela figura IX.xx pode ser visto no exemplo
IX.xx.
Produtor Consumidor
s=1; n=0;
incio loop incio loop
Produz mensagem P(n) // Verifica se existe mensagens
P(s) // Verifica se pode entrar na regio
// crtica
P(s) // Verifica se pode entrar na regio
//crtica
Coloca mensagem no buffer Retira mensagem
V(n) // incrementa no, de mensagens V(s) // sai da regio crtica
V(s) // sai da regio crtica Consome Mensagem
fim loop fim loop
Figura IX.xx Comunicao entre processos usando semforos.
public class Semaforo
{
private int cont;
public Semaforo(){cont =0;}
public Semaforo(int i){cont =i;}
public synchronized void P() throws InterruptedException
{
while(cont <=0) this.wait();
cont--;
}
public synchronized void V()
{
cont++;
notifyAll();
}
}
Exemplo IX.XX Implementao de um Semforo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
297
import java.util.Vector;
class Consumidor extends Thread
{
private Vector buff;
private Semaforo s,n;
public Consumidor(Vector aBuff, Semaforo as, Semaforo an)
{
super();
buff = aBuff; s = as; n = an;
}
public void run()
{
for (;;)
try
{
n.p(); // Verifica se existe mensagens
s.p(); // Verifica se pode entrar na regio crtica
String men = (String)buff.firstElement();
buff.removeElementAt(0);
s.v();
if (men.equals("fim")) return;
System.out.println("Mensagem recebida:"+men);
} catch(Exception e)
{System.out.println(e.getMessage());}
}
}
class Produtor extends Thread
{
private Vector buff;
private Semaforo s,n;
public Produtor(Vector aBuff, Semaforo as, Semaforo an)
{
super();
buff = aBuff; s = as; n = an;
}
public void run()
{
for (int i=0;i<11;i++)
{
try
{
s.p();// Verifica se pode entrar na regio crtica
if (i<10)
{
buff.addElement(""+i);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
298
System.out.println("Mensagem enviada: "+ i);
}
else buff.addElement("fim");
n.v(); // incrementa o nmero de mensagens
s.v(); // abandona a regio crtica
Thread.yield();
} catch(Exception e)
{System.out.println(e.getMessage());}
}
}
}
public class TestaSemaforo
{
public static void main(String args[])throws Exception
{
Vector buff = new Vector();
Semaforo s = new Semaforo(1);
Semaforo n = new Semaforo(0);
Produtor t1 = new Produtor(buff,s,n);
Consumidor t2 = new Consumidor (buff,s,n);
t1.start();
t2.start();
}
}
Exemplo IX.XX Uso de semforos por dois threads.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
299
Captulo XII - Animao
Animao exibir uma figura que muda com o tempo. No momento o
suporte a animao da API central do J ava limitado. Espera-se para o final de
1997 uma API que d suporte avanado para animao. A animao pode ser
controlado por um thread que executado em um certo intervalo pr-definido.
Exemplo bsico de animao in-place.
import java.awt.*; import java.applet.Applet;
public class exemplo10 extends Applet implements Runnable
{
Image imgs[];
int ind=0;
Thread t1;
public void init()
{imgs = initImgs(); t1=new Thread(this);
t1.start();}
public void paint(Graphics g)
{g.draw.Image(imgs[ind],0,0,this);}
public void start() {
if (t1 == null) { t1 = new Thread(this);
t1.start();}
}
public void stop() {
if (t1 != null) {t1.stop();t1 = null;}
}
public void run() {
while (true){
try {Thread.sleep(100};}
catch(InterruptedException ex){}
repaint();
ind=++ind % imgs.length;
}
}
}
Problemas com o exemplo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
300
Ele no permite interromper a animao. O repaint() chama o
update() default que repinta todo o fundo, o que causa flicker na animao.
Existe um problema relacionado com a integridade da varivel ind. A varivel
atualizada pelo Thread t1 (run) e lida pelo Thread update (paint).
permitir interromper a animao.
boolean pause = false;
public boolean mouseDown(Event e, int x, int y)
{
if (pause) {t1.resume();}
else {t1.suspend();}
pause = !pause;
return true;
}
Eliminar o flicker
Default
public void update(Graphics g)
{
g.setColor(getBackground());
g.fillRect(0,0,width, height);
g.setColor(getForeground());
paint(g);
}
Mudana
public void update(Graphics g) {paint(g);}
Eliminando conflitos
public synchronized void paint(Graphics g)
{
g.draw.Image(imgs[ind],0,0,this);
}
public synchronized void mudaInd()
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
301
{
ind = ++ind % imgs.length;
}
Copiando a figura
public void drawStickFigure (Graphics g, int nX, int nY)
{
g.drawOval (nX + 10, nY + 20, 20, 40);
g.drawLine (nX + 20, nY + 60, nX + 20, nY + 100);
g.drawLine (nX + 10, nY + 70, nX + 30, nY + 70);
g.drawLine (nX + 10, nY + 150, nX + 20, nY + 100);
g.drawLine (nX + 20, nY + 100, nX + 30, nY + 150);
}
public void paint (Graphics g, Applet Parent)
{
if (bFirstTime) {
bFirstTime = false;
drawStickFigure (g, nX, nY);
}
else { g.copyArea (nX, nY, 35, 155, 5, 0);}
}
Double-buffer
offScreenImage = createImage (nWidth, nHeight);
offScreenGraphic = offScreenImage.getGraphics();
...
offScreenGraphic.setColor (Color.lightGray);
offScreenGraphic.fillRect (0, 0,nWidth, nHeight);
offScreenGraphic.setColor (Color.black);
...
offScreenGraphic. drawOval(10,10,20,20);
...
g.drawImage (offScreenImage, 0, 0, this);
Ticker-Tape
class TextScrolling extends AnimationObject
{
String pcMessage; // The message
int nXPos; // The location of the message
int nYPos; // The location of the message
int nAppletWidth; // The width of the applet
int nMessageWidth; // The width of the message
public TextScrolling (String pcMsg, int nWide)
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
302
{
pcMessage = pcMsg;
nAppletWidth = nWide;
nMessageWidth = -1;
nYPos = -1;
nXPos = 0;
}
public void paint (Graphics g, Applet parent)
{
if (nYPos < 0)
{
nYPos = (g.getFontMetrics ()).getHeight ();
char pcChars [];
pcChars = new char [pcMessage.length() + 2];
pcMessage.getChars(0, pcMessage.length()- 1, pcChars, 0);
nMessageWidth = (g.getFontMetrics ()).charsWidth
(pcChars, 0, pcMessage.length());
}
g.drawString (pcMessage, nXPos, nYPos);
}
public void clockTick ()
{
if (nMessageWidth < 0) return;
// Move Right
nXPos -= 10;
if (nXPos < -nMessageWidth)
nXPos = nAppletWidth - 10;
}
public void run()
{
int ndx = 0;
Thread.currentThread().setPriority
(Thread.MIN_PRIORITY);
while (size().width > 0 && size().height > 0
&& kicker != null)
{
AnimatedObjects[0].clockTick ();
repaint();
try {Thread.sleep(nSpeed);}
catch (InterruptedException e){}
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
303
Captulo XIII - Programao em
rede
Diferentemente das linguagens mais populares atualmente, J ava foi
projetada na era da Internet, e por isso mesmo ferramentas para comunicao
dentro da Grande Rede foram incorporadas linguagem desde a sua concepo.
Classes para manipulao de URLs e dos protocolos que constituem a Internet
fazem parte do ncleo bsico da linguagem. Isto facilita muito a tarefa de
desenvolver aplicaes que para a Internet ou outras redes que fazem uso do
mesmo conjunto de protocolos. Esta uma das principais foras da linguagem
J ava. De modo a entendermos como desenvolver aplicaes em rede com J ava
importante o compreenso de alguns conceitos bsicos sobre protocolos de
comunicao.
Conceitos Sobre Protocolos Usados na Internet
Um protocolo de comunicao um conjunto de formatos e regras
usadas para transmitir informao. Computadores distintos devem obedecer
estas regras e formatos de modo que se possam comunicar. Podemos encarar o
protocolo como a definio de uma linguagem comum de modo a possibilitar a
comunicao entre diferentes entidades.
Visando diminuir a complexidade de implementao e uso do protocolo,
ele divido e organizado em forma de camadas de protocolos, onde a camada
relativamente inferior na pilha a outra estabelece as regras para a camada
superior sobre a utilizao de seus servios. As camadas inferiores fornecem
servios mais bsicos de transmisso de dados, enquanto que as camadas
superiores oferecem servios de mais alto nvel. Esta forma de organizao
hierrquica de protocolos tambm chamada de pilha de protocolos.
A principal pilha de protocolo sobre o qual a Internet se organiza o
TCP/IP. Por simplicidade chamaremos a pilha de protocolos TCP/IP apenas
como protocolo TCP/IP ou TCP/IP. A figura XI.1 mostra como se organizam
alguns dos protocolos que fazem parte do TCP/IP.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
304
A camada fsica a responsvel pela transporte efetivo dos dados sobre o
meio fsico. A camada de rede responsvel pela interface lgica entre os
computadores. A camada de transporte prov transferncia de dados a nvel de
servio, e a camada de aplicao prov comunicao a nvel de processos ou
aplicaes. Exemplos de protocolos a nvel de aplicao so: FTP, usado para
transferncia de arquivos; HTTP, usado para transmisso de pginas Web;
TELNET prov capacidade de log-on remoto; SMTP prov servios bsicos de
correio eletrnico; SNMP usado para gerncia da rede; e MIME que uma
extenso do SMTP para lidar com mensagens com contedos diversos.
Figura XI.1 Alguns protocolos da pilha TCP/IP.
No processo de transmisso de dados sobre uma rede TCP/IP os dados
so divididos em grupos chamados de pacotes. Cada camada adiciona um alguns
dados a mais no incio de cada pacote para permitir que o pacote chegue ao
destino. Os dados adicionados so chamados de headers.
Ethernet, X.25, Token Ring Camada fsica
IP Camada de rede
UDP TCP
Camada de Transporte
SNMP FTP HTTP SMTP TELNET
MIME
Camada de Aplicao
FTP - File Transfer Protocol SMTP - Simple Mail Transfer Protocol
HTTP - Hypertext Transfer Protocol SNMP - Simple Network Management Protocol
IP - Internet Protocol TCP - Transmission Control Protocol
MIME - Multi-purpose Internet Mail Extensions UDP - User DatagramProtocol
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
305
Figura XI.2 Headers adicionados a cada camada de protocolo.
Na camada de transporte existem dois protocolos que fazem uso do
protocolo IP: o protocolo TCP/IP e o UDP.
TCP
O protocolo TCP um protocolo orientado a conexo que prov um
fluxo confivel de dados entre dois computadores. Por protocolo orientado a
conexo queremos dizer que estabelecido um canal de comunicao ponto-a-
ponto onde os dados podem trafegar em ambas as direes. O TCP garante que
os dados enviados em uma ponta cheguem ao destino, na mesma ordem que
foram enviados. Caso contrrio, um erro reportado. Protocolos como HTTP,
FTP e TELNET exigem um canal de comunicao confivel e a ordem de
recebimento dos dados fundamental para o sucesso dessas aplicaes.
UDP
No entanto, nem todas as aplicaes necessitam destas caractersticas do
protocolo TCP e o processamento adicional exigido para garantir a
confiabilidade e a ordenao dos dados podem inviabiliz-las. Para esses casos
existe o protocolo de transporte UDP. UDP um protocolo para envio de
Dados TCP
Header
Dados
Dados
Aplicao
Dados TCP
Header
Transporte
TCP
Header
IP
Header
Rede
IP
Header
Ethernet
Header
Fsica
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
306
pacotes independentes de dados, chamados de datagramas, de um computador a
outro, sem garantias sobre a chegada dos pacotes. O protocolo UDP no
orientado a conexo.
IDENTIFICAO DE HOSTS (Nmero IP)
Cada computador conectado a uma rede TCP/IP chamado de Host e
identificado por um nico nmero de 32 bits, denominado de nmero IP. O
nmero IP representado por quatro grupos de 8 bits, limitando desta forma o
valor numrico de cada grupo ao valor mximo de 255. Um exemplo de nmero
IP 200.65.18.70. Uma vez que muito difcil lembrar e atribuir significado a
nmeros existe uma forma alternativa de identificar os computadores da rede por
meio de nomes. Um ou mais computadores da rede fazem o papel de
resolvedores de nomes, mantendo bases de dados que associam o nomes do
Hosts seus nmeros IP. Desta forma possvel um computador comunicar com
outro computador por meio do nome lgico e no por meio do nmero IP. A
figura XI.3 ilustra a comunicao entre dois computadores. A Internet
representada como uma nuvem devido a complexidade da rede.
Figura XI.3 Representao da comunicao entre dois computadores.
O representao dos nomes dos computadores na Internet feita por
substrings separadas por . e obedecem uma regra de nomeao que define que
o primeiro substring representa o nome da mquina, e os restantes representa o
domnio onde est inserida a mquina. Um domnio um agrupamento de
computadores que pertencem a uma instituio, rgo, empresa, ou uma
organizao qualquer. Assim, no exemplo da figura XI.3 o computador
meucomp pertence ao domnio com.br. No Brasil a FAPESP (Fundao de
Host meucomp.com.br
IP: 200.18.46.12
Host outrocomp.edu
IP: 205.50.30.75
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
307
Amparo Pesquisa do Estado de So Paulo) responsvel pela gerncia dos
nomes dos domnios na Internet.
Identificao de Processos (Portas)
A comunicao entre dois processos em uma rede TCP/IP assimtrica,
no sentido um processo faz o papel de servidor, oferecendo um servio e outro
faz o papel de cliente do servio. Em um nico Host vrios processos podem
estar fazendo o papel de servidor, oferecendo servios atravs de um nico meio
fsico. Portanto, preciso uma forma de identificar as servidores em um mesmo
Host. Isto feito por meio da associao de um nmero inteiro, chamado de
porta, ao processo servidor. Essa associao feita pelo processo assim que
carregado, por meio de uma chamada ao sistema. O nmero da porta pode variar
de 1 a 65535, no entanto os nmeros de 1 a 1023 so reservados para servios
conhecidos como FTP e HTTP. O programador no deve usar estas portas a no
ser que esteja implementando algum desses servios. Nos ambientes Unix as
portas que vo de 6000 a 6999 so usadas pelo gerenciador de Interfaces X
Windows e 2000 a 2999 por outros servios, como o NFS. Nestes ambientes,
estas faixas de nmeros de portas tambm devem ser evitadas. A tabela XI.1
mostra o nmero da porta de alguns dos servios mais conhecidos.
Protocolo Porta
HTTP 80
echo 7
FTP 20,21
SMTP 25
Finger 79
Daytime 13
pop3 110
Tabela XI.1 Nmero das portas dos principais servios.
Uma vez associado a uma porta o servio pode ser acessado por uma
aplicao cliente, bastando para isso que ela indique o nome do Host e o nmero
da porta ao se comunicar.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
308
Programao em Rede com Java
O pacote java.net contm as classes e interfaces usadas para
programao de sistemas em rede com J ava. As classes podem ser enquadradas
em trs categorias:
1. Classes para comunicao bsica em rede. Tratam da comunicao
em baixo nvel entre aplicaes. Outros protocolos podem ser
implementados usando como base esta comunicao bsica.
2. Classes para comunicao dentro da Web. Estas classes provem
facilidades para acessar contedos por meio de URLs.
3. Classes para tratamento dos formatos estendidos da Web. Utilizadas
para tratar novos protocolos e tipos MIME.
Comunicao Bsica Entre Aplicaes
As classes Socket, ServerSocket, DatagramSocket,
DatagramPacket e InetAddress, fornecem os mtodos necessrios para
a comunicao bsica entre dois processos. A tabela XI.2 descreve sucintamente
cada uma das classes.
Classe Descrio
Socket Prov um socket cliente para comunicao orientada
conexo via protocolo TCP.
ServerSocket Prov um socket servidor para comunicao orientada
conexo via protocolo TCP.
DatagramSocket Prov um socket UDP para comunicao no orientada
conexo.
DatagramPacket Representa um datagrama que pode ser enviado usando
DatagramSocket.
InetAddress Representa os dados de um Host (Nome e endereo IP)
Tabela XI.2 Classes para comunicao bsica.
As classes Socket e ServerSocket so utilizadas para comunicao
orientada conexo, enquanto que as classes DatagramSocket e
DatagramPacket so utilizadas para comunicao no orientada conexo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
309
Comunicao orientada conexo (cliente)
Para comunicar via protocolo TCP preciso que a aplicao cliente crie
um objeto Socket. preciso passar o nome ou nmero IP do Host e o nmero
da porta onde o servidor est esperando as solicitaes de servio. A Classe
Socket possui os mtodos getInputStream() e
getOutputStream(), que so usados para obter Streams associados ao
Socket. Deste modo, a transmisso de dados via Socket idntica leitura e
escrita em arquivos via Streams. O exemplo XI.1 mostra o cdigo de um cliente
que acessa um servidor de Daytime. O servio de Daytime disponibilizado nas
plataformas UNIX e acessado via porta 13. Sua funo enviar, aos processos
clientes, uma linha de texto contendo a data e a hora corrente .
import java.io.*;
import java.net.*;
public class ClienteData {
public static void main(String[] args) throws IOException
{
Socket socket = null;
BufferedReader in = null;
try {
socket = new Socket(args[0], 13);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
}catch (UnknownHostException e)
{System.err.println("No achou o host:"+args[0]);
System.exit(1);}
catch (IOException e)
{System.err.println("Erro de I/O."+e.getMessage());
System.exit(1);}
System.out.println("Data: " + in.readLine());
}
in.close();
socket.close();
}
}
Exemplo XI.1 Cliente para o servio de Daytime.
No programa do exemplo XI.1 o usurio precisa passar o nome do Host
servidor pela linha de comando. Voc pode testar este programa mesmo que seu
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
310
computador no esteja conectado em uma rede, desde que o protocolo TCP/IP
esteja instalado. que voc pode passar como parmetro o nome do seu
computador ou, alternativamente, o nome localhost, ainda o nmero IP
127.0.0.0. O nome localhost e o nmero IP127.0.0.0 sempre identificam o
computador local. Note que aps a criao do objeto Socket, o mtodo
getInputStream() chamado e o objeto retornado envolvido por um
objeto BufferedReader de modo a comunicar dados via rede da mesma forma
que realizada uma operao de E/S. Ao se terminar a operao preciso fechar
tanto a instncia BufferedReader quanto o objeto Socket. A instncia da Classe
de E/S sempre deve ser fechada primeiro.
Os Hosts que utilizam as variaes do sistema operacional UNIX
possuem o servio de Daytime, no entanto, outros sistemas operacionais podem
no implementar este servio. O programador pode resolver este problema
implentando ele mesmo um servidor de Daytime. A prxima seo mostrar
como isto pode ser feito.
Comunicao orientada conexo (servidor)
Para criar um processo servidor preciso associ-lo uma porta. Isto
feito ao se criar uma instncia da classe ServerSocket. Se estamos criando um
novo servio preciso associar a uma porta com valor maior que 1023. Se
estamos implementando um servio j estabelecido preciso obedecer as
especificaes definidas para o servio. O exemplo XI.2 mostra o cdigo de um
servidor do servio Daytime. Como no queremos substituir o servio padro de
Daytime utilizaremos o nmero de porta 5013 no lugar do nmero 13. Para se
testar este servidor com o programa cliente do exemplo X.1 preciso alterar o
nmero da porta no cdigo do cliente.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
311
import java.util.*;
import java.io.*;
import java.net.*;
public class ServerData {
public static void main(String[] args) throws IOException
{
SeverSocket ssocket = null;
Socket socket = null;
BufferedWriter out = null;
ssocket = new SeverSocket (5013,5);
for(;;)
{
socket = ssocket.accept();
out = new BufferedWriter (new OuputStreamWriter (
socket.getOuputStream()));
out.write((new Date()).toString()+\n);
}
out.close();
socket.close();
}
}
Exemplo XI.2 Servidor de Daytime.
Ao criar uma instncia da classe ServerSocket o programador pode
indicar o tamanho da fila de solicitaes de conexo. As conexes so colocadas
na fila at que o servidor possa atende-las. Se chegar alguma conexo e no
houver espao na fila a conexo ser recusada. No nosso exemplo passamos
como parmetro o valor 5. Aps criar o objeto ServerSocket o servidor deve
indicar que est disposto a receber conexes. Isto feito por meio da execuo
do mtodo accept() do objeto ServerSocket. Ao executar este mtodo o
processo passa para o estado bloqueado at que alguma conexo seja solicitada.
Quando a conexo solicitada o mtodo accept() retorna um objeto Socket
igual ao do processo cliente, que ser usado para obter os Streams onde ser
efetuada a comunicao. O Stream obtido do objeto Socket encapsulado em
objeto BufferedWriter que ser encarregado de enviar a cadeia de caracteres
contendo a data e a hora para o cliente. O Servidor em implementa um lao
infinito, recebendo e tratando solicitaes de servios.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
312
O servidor implementado acima trata uma solicitao de servio por vez.
Isto pode ser problemtico quando existem vrios clientes solicitando servios
ao mesmo tempo e o servidor leva um longo tempo tratando cada solicitao.
Nesta situao o cliente pode ficar um longo tempo a espera de atendimento. Isto
pode ser remediado por meio da implementao de servidores Multithreaded.
Apesar do servio implementado pelo exemplo XI.2 no exigir um servidor
Multithreaded, uma vez que o cliente atendido rapidamente, o servidor
Daytime foi alterado para exemplificar a implementao de um servidor
Multithreaded. O exemplo XI.3 mostra o cdigo da verso Multithreaded do
servidor.
import java.util.*;
import java.net.*;
import java.io.*;
public class ServerData
{
public static void main(String args[])
{
ServerSocket ssocket=null;
try { ssocket = new ServerSocket(pt); }
catch(Exception e) {System.err.println(e);
System.exit(1);}
while(true)
{
try
{
Socket socket = ssocket.accept();
(new serversec(socket)).start();
}
catch(Exception e) {System.err.println(e);}
}
}
}
class serversec extends Thread
{
Socket socket;
public serversec(Socket aSocket) {socket = aSocket;}
public void run()
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
313
try
{
BufferedWriter out = new BufferedWriter (new
OuputStreamWriter (
socket.getOuputStream()));
out.write((new Date()).toString()+\n);
out.flush();
out.close();
socket.close();
}
catch(Exception e) {System.err.println(e);}
}
}
Exemplo XI.3 Servidor de Daytime Multithreaded.
No exemplo XI.3, ao receber uma conexo o servidor cria um Thread
para atender o cliente e fica disponvel para receber novas solicitaes. Esse
exemplo pode ser usado como esqueleto para desenvolvimento de servidores
mais complexos, porm, neste caso necessrio limitar o nmero de Threads
que podem ser criados.
Comunicao Sem Conexo (UDP)
Como j dissemos na seo anterior, nem sempre necessrio um canal
de comunicao confivel entre duas aplicaes. Para estes casos existe o
protocolo UDP, que prov uma forma de comunicao onde a aplicao envia
pacotes de dados, chamados de datagramas, para outra aplicao, sem garantias
se e quando a mensagem vai chegar, nem se o contedo est preservado.
As portas do protocolo UDP obedecem a mesma distribuio das TCP
porm so distintas uma da outra, de modo que o programador pode associar
uma porta TCP de um determinado nmero uma aplicao em um host e o
mesmo nmero de porta UDP a outra aplicao no mesmo host.
As classes DatagramPacket e DatagramSocket contm os
mtodos necessrios para realizar este tipo de comunicao. Para ilustrar o uso
destas classes modificaremos os exemplos XI.1 e XI.2 para implementarmos
uma aplicao Cliente/Servidor Daytime que usa o protocolo UDP. O Exemplo
XI.4 mostra o cdigo fonte do cliente e o Exemplo XI.5 mostra o cdigo do
servidor.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
314
Analisando o cdigo da aplicao cliente podemos notar que necessrio
criar um objeto da classe DatagramPacket para representar os Datagrama onde
os dados so armazenados. No nosso exemplo colocamos tambm os dados do
Host e a porta, porm estes dados poderiam ser omitidos na construo do
Datagrama e serem passados somente no envio/recepo do pacote ou na
construo do DatagramSocket. O Datagrama dever armazenar os dados
enviados pelo servidor e foi dimensionado para conter 64 bytes. O mtodo
receive() do objeto DatagramSocket aguarda o recebimento do pacote,
tendo como argumento o objeto da classe DatagramPacket. Aps o recebimento
do pacote os dados so convertidos para String e exibidos na sada padro.
O servidor, diferentemente do servidor TCP, precisa saber a quem deve
enviar os pacotes, uma vez que no estabelecida uma conexo. Podamos
simplesmente passar o nome do host pela linha de comando, mas resolvemos
adotar uma estratgia de Broadcasting. Nesta abordagem os datagramas so
enviados a vrios computadores e no apenas um. Isto feito passando-se como
argumento para o mtodo InetAddress.getByName() o endereo de
Broadcast da rede.
import java.io.*;
import java.net.*;
public class DataClienteUDP
{
public static void main(String args[]) throws Exception
{
if (args.length != 1)
{
System.err.println("Uso: java DataClienteUDP host");
System.exit(1);
}
byte [] buff = new byte[64];
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp = new DatagramPacket(buff, buff.length,
InetAddress.getByName(args[0]),5013);
ds.receive(dp);
String s = new String(dp.getData());
System.out.println("Data e hora recebida
de+dp.getAddress()+
" : "+s);
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
315
Exemplo XI.4 Cliente Daytime UDP.
import java.io.*;
import java.net.*;
public class DataServerUDP
{
public static void main(String args[]) throws Exception
{
DatagramSocket ds;
DatagramPacket dp;
InetAddress addr = InetAddress.getByName(255.255.255.0);
ds = new DatagramSocket();
byte [] buff;
for (;;)
{
Thread.sleep(1000);
String s = (new Date()).toString();
buff = s.getBytes();
dp = new DatagramPacket(buff, buff.length, addr, 5013);
ds.send(dp);
}
}
}
Exemplo XI.5 Servidor Daytime UDP.
O tipo de endereo de Broadcast depende da classe de endereamento IP
da rede. O endereo usado no exemplo IX.5 funciona para a classe de
endereamento C. Para descobrir que tipo de classe pertence a rede onde est seu
computador olhe o primeiro byte do endereo IP de sua mquina e verifique
junto a tabela XI.3.
Primeiro byte do endereo IP Classe Endereo de Broadcast
0 a 126 A 255.0.0.0
128 a 191 B 255.255.0.0
192 a 223 C 255.255.255.0
Tabela XI.3 Classes para comunicao bsica.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
316
O envio dos dados feito pelo mtodo send() do objeto
DatagramSocket, tendo como argumento um objeto da classe DatagramPacket.
Note que no necessrio um Socket servidor uma vez que o servidor envia
os pacotes independentemente de existir clientes solicitando-os.
Comunicao por meio de URL
URLs
Um URL (Uniform Resource Locator) uma referncia (um endereo) a
um recurso na Internet. O URL dividido em partes, sendo que apenas a
primeira parte obrigatria. A maioria das URLs dividida em trs partes:
Informao sobre o Host
http://dpi.ufv.br/professores.html
A parte do protocolo define o protocolo que deve ser usado para acessar
o recurso. Os protocolos mais comuns so FTP, HTTP e file, este ltimo
indicando que o recurso se encontra no sistema de arquivos local. O protocolo
seguido do caractere :.
A parte com informao sobre o Host fornece a informao necessria
para acessar o Host onde est localizado o recurso. Esta parte omitida caso o
recurso esteja no sistema de arquivos local. A informao sobre o Host
precedida por duas barras (//), no caso de aplicao na Internet e apenas por
uma barra (/), caso contrrio. A informao sobre o Host tambm pode ser
dividida em trs partes: a) o nome do domnio do Host; b) o nome e senha do
usurio para login; e c) o nmero da porta caso necessrio, aps o nome do host,
precedida pelo caractere :. Exemplos:
http://java.sun.com:80/doc/tutorial.html
http://infax.com.br."claudio"."1234"/base/vendas
1 11 12 22 23 33 3
6 66 67 77 78 88 8
123
endereo do recurso no Host
Protocolo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
317
A ltima parte de uma URL representa o caminho at o recurso no
sistema de arquivos do Host. Esta seo separada da seo anterior por uma
barra simples (/).
Manipulando URLs em Java
A linguagem J ava fornece as seguintes classes para manipulao de
URLs:
Classe Descrio
URL Representa um URL
URLConnection Classe abstrata que representa uma conexo entre uma
aplicao e um URL. Instncias desta classe podem ser
usadas para ler e escrever no recurso referenciado pela
URL.
URLEncoder Usada para lidar com o formato MIME.
Tabela XI.3 Classes para manipulao de URLs.
Um objeto URL criado passando como parmetro para o construtor o
URL na forma de String:
URL dpi = new URL("http://www.dpi.ufv.br");
Um objeto URL pode ser construdo passando como parmetro outro
URL para servir de endereo base. Por exemplo
URL profs = new URL (dpi,professores.html);
Isto tem o mesmo efeito que gerar uma instncia da classe URL com
primeiro construtor, passando como parmetro o endereo:
http://www.dpi.ufv.br/professores.html
Os construtores geram a exceo MalformedURLException, se o
URL invlido. Portanto, o programador deve providenciar o cdigo para a
captura e tratamento desta exceo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
318
De posse de um objeto URL possvel obter um objeto InputStream para
ler os dados endereados pelo URL, utilizando o mtodo openStream() do
objeto URL. O Exemplo XI.4 mostra o cdigo de um programa que pode ser
usado para listar na sada padro o contedo de um URL passado pela linha de
comando.
import java.net.*;
import java.io.*;
public class LeURL
{
public static void main(String[] args) throws Exception
{
if (args.length < 1)
{
System.err.println("uso: java LeURL <URL>...");
System.exit(1);
}
URL url = new URL(args[0]);
BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream()));
String linha;
while ((linha = in.readLine()) != null)
System.out.println(linha);
in.close();
}
}
Exemplo XI.4 Leitor de URL.
Comunicando por meio de URLConnection
O programador pode utilizar o mtodo openConnection() do objeto
URL para obter uma conexo entre a aplicao o recurso referenciado pelo o
URL. O mtodo openConnection() retorna um objeto URLConnection,
que permite que a aplicao escreva e leia atravs da conexo. Alguns URLs,
como os conectados scripts CGI
5
(Common-Gateway Interface), permitem que

5
Common-Gateway Interface (CGI) um mecanismo para gerar pginas Web dinamicamente.
Os dados so obtidos de frmulrios HTML e submetidos a um programa binrio no servidor
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
319
aplicao cliente escreva informao no URL. A sada do programa CGI pode
ser interceptada pelo programa J ava de modo que possa ser exibida para o
usurio. Esta forma de comunicao com scripts CGI melhor do que por meio
de formulrios HTML, uma vez que o usurio no precisa navegar entre pginas
para visualizar os formulrios e a resposta retornada. O Applet J ava se encarrega
de enviar os dados e exibir o resultado na mesma pgina. Para ilustrar esta forma
de comunicao mostraremos um programa que submete uma cadeia de
caracteres a um URL para que seja invertido e enviado de volta. O script CGI
utilizado, escrito em Perl exibido no exemplo XI.5 e foi escrito por Hassan
Schroeder, um membro da equipe de desenvolvimento da linguagem J ava. Este
CGI pode ser acessado no URL http://java.sun.com/cgi-
bin/backwards.
#!/opt/internet/bin/perl
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",
hex($1))/eg;
# Stop people from using subshells to execute commands
$value =~ s/~!/ ~!/g;
$FORM{$name} = $value;
}
print "Content-type: text/plain\n\n";
print "$FORM{'string'} reversed is: ";
$foo=reverse($FORM{'string'});
print "$foo\n";
exit 0;
Exemplo XI.5 Script backwards para inverter uma cadeia de caracteres.
O exemplo XI.6 contm o programa que envia uma cadeia de caracteres
ao URL e recebe de volta outra cadeia de caracteres que a inverso da
primeira. A ao necessria codificar a cadeia de caracteres por meio do
mtodo esttico encode() da classe URLEncoder:

que gera a resposta na forma de uma pgina Web. O programa pode ser escrito em uma
variadade delinguagens, como Perl e C.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
320
String string = URLEncoder.encode(args[0]);
Isto necessrio porque a string enviada a um URL necessita de uma
codificao particular, como por exemplo, os espaos em branco so
substitudos pelo caractere +, os campos so separados pelo caractere &e
valor do campo separado do nome do campo pelo caracteres =.
Em seguida o programa cria um objeto URL relacionado com o endereo
onde se encontra o script, abre uma conexo e define que ser usada para entrada
e sada.
URL url = new URL("http://java.sun.com/cgi-
bin/backwards");
URLConnection c = url.openConnection();
c.setDoOutput(true);
Neste momento o programa est preparado para trabalhar com o URL
como se fosse um Stream. O Stream para escrever no URL obtido do objeto
URLConnection por meio do mtodo getOutputStream() e o Stream
para ler do URL obtido do objeto URLConnection por meio do mtodo
getInputStream(). Primeiro o programa submete a cadeia de caracteres a
ser invertida precedida pelo nome do campo e pelo caractere =:
out.println("string=" + string);
import java.io.*;
import java.net.*;
public class Inverte
{
public static void main(String[] args) throws Exception
{
if (args.length != 1)
{
System.err.println("Uso: java Inverte string");
System.exit(1);
}
String string = URLEncoder.encode(args[0]);
URL url = new URL("http://java.sun.com/cgi-
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
321
bin/backwards");
URLConnection c = url.openConnection();
c.setDoOutput(true);
PrintWriter out = new PrintWriter(c.getOutputStream());
out.println("string=" + string);
out.close();
BufferedReader in = new BufferedReader(new
InputStreamReader(
c.getInputStream()));
String retorno;
while ((retorno = in.readLine()) != null)
System.out.println(retorno);
in.close();
}
}
Exemplo XI.6 Programa que escreve em um URL.
Aps isso o Stream de sada fechado e o Stream de entrada aberto. A
cadeia de caracteres invertida lida e exibida no dispositivo de sada padro.
No exemplo apresentado o script CGI usa o POST METHOD para ler
dados enviados pelo cliente. Alguns scripts CGI usam o GET METHOD para ler
dados do cliente, no entanto, este ltimo est ficando rapidamente obsoleto
devido a maior versatilidade do primeiro.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
322
Captulo XIV Computa o
Distribuda (RMI)
A RMI (Invocao de mtodos remotos) uma tecnologia que coloca a
programao com rede em um nvel mais alto. RMI torna possvel que objetos
distribudos em uma rede se comuniquem de forma transparente para o
programador utilizando chamadas de procedimentos remotos.
O principal objetivo da tecnologia RMI permitir que programadores
desenvolvam programas distribudos utilizando a mesma sintaxe e semntica de
programas J ava convencionais. Antes da introduo da RMI no mundo J ava, no
J DK 1.1, para fazer com que dois objetos em mquinas diferentes se
comunicassem o programador deveria definir um protocolo de comunicao e
escrever cdigo utilizando socket para implementar este protocolo. Com RMI a
maior parte do trabalho quem realiza a mquina virtual J ava.
Existem outras tecnologias, como CORBA (Common Object Request
Brocker Architecture), que tambm tem como objetivo fazer com que objetos
distribudos em uma rede se comuniquem. J ava tambm tem suporte a CORBA,
mas para projetos em um ambiente J ava puro, a RMI consideravelmente mais
simples que a CORBA.
Criando nossa agenda distribuda
De modo exemplificar o uso de RMI modificaremos a agenda distribuda
fazendo uso desta tecnologia. Os passos a serem seguidos so:
1. Escrever e compilar a interface que descreve a como sero as chamadas
do cliente ao servidor;
2. Escrever e compilar a classe que implementa a interface do passo 1
(objeto servidor);
3. Gerar Stubs e Skeleton do objeto distribudo;
4. Desenvolver o cdigo que disponibiliza o objeto;
5. Escrever e compilar o cdigo para o cliente RMI; e
6. Testar.
Implementar interface do objeto remoto
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
323
O primeiro passo quando se deseja criar um objeto Remoto com RMI
implementar uma interface para este Objeto. Essa interface deve herdar a
interface Remote. atravs dessa interface Remote, que no tem mtodos, que a
mquina virtual J ava sabe qual objeto pode ser disponibilizado para acesso
remoto. Abaixo temos o exemplo da interface do nosso objeto:
1
2
3
4
5
6
7
8
public interface Agenda extends java.rmi.Remote{
public void inserir(Pessoa p)
throws java.rmi.RemoteException;
public Pessoa getPessoa(String nome)
throws java.rmi.RemoteException;
public java.util.Enumeration getPessoas()
throws java.rmi.RemoteException;
}
Exemplo XX.XX Interface do objeto remoto.
A interface Remote deve ser herdada pela nossa interface Agenda.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
324
Captulo XV - Acesso a B anco de
Dados
No dias de hoje, uma linguagem sem recursos para acesso a sistemas de
Banco de Dados est fadada ao fracasso. Pensando nisso a Sun incluiu como
parte do ncleo de bibliotecas de classes da linguagem J ava uma API com o
objetivo de preencher esta funo, chamada de J DBC (segundo a Sun J DBC
apenas um acronismo, no entanto, muitas pessoas acreditam que uma sigla
para J ava Database Connectivity). J DBC uma API baseada no X/Open SQL
Call Level Interface, tendo sido desenvolvida originalmente como um pacote
separado, porm a partir do J DK1.1 passou a fazer parte do ncleo bsico de
pacotes. Utilizando a API J DBC possvel conectar um programa J ava com
servidores de Banco de Dados e executar comandos SQL (Structure Query
Language). Sendo uma API independente do Sistema Gerenciador de Banco de
Dados, no necessrio escrever uma aplicao para acessar um Banco de
Dados Oracle, outra para uma Base de Dados Sybase, outra para o DB2, e assim
por diante.
A idia de se usar uma camada intermediria entre o Banco de Dados e a
aplicao, com o objetivo de isol-la das particularidades do SGBD, no nova.
O exemplo mais popular deste enfoque a API ODBC (Open DataBase
Connectivity), proposta pela Microsoft. O leitor pode estar se perguntando
porque a Sun resolveu propor mais uma API em vez de adotar a ODBC. Existem
vrios motivos, porm o principal que a API ODBC simplesmente no
adequada para a linguagem J ava. Isto ocorre porque ODBC foi desenvolvida
para ser usada na linguagem C e baseada fortemente no uso de ponteiros,
estrutura que no existe em J ava.
Modelos de Acesso a Servidores
O modelo mais simples de aplicao Cliente/Servidor o chamado de
modelo de duas camadas, onde a aplicao acessa diretamente o Banco de
Dados. A figura XIII.1 mostra o esquema para uma aplicao que acessa um
Banco de Dados usando o modelo de duas camadas.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
325
Figura XIII.1 Modelo de acesso a Banco de Dados em duas camadas.
Figura XIII.2 Modelo de acesso a Banco de Dados em trs camadas.
Tipos de Drivers JDBC
Os drivers J DBC devem suportar o nvel de entrada do padro ANSI
SQL-2. No momento, os drivers J DBC existentes se encaixam em um dos quatro
tipos abaixo:
1. Ponte JDBC-ODBC com driver ODBC o driver J DBC acessa o banco de
dados via drivers ODBC. Como ODBC um cdigo binrio e, em alguns
casos, compe o cdigo do cliente, necessrio instalar em cada mquina
cliente que usa o driver. Essa uma soluo adequada somente para uma
Aplicao
J ava
DBMS
Aplicao J ava
ou Applet
DBMS
Aplicao Servidora
J ava
J DBC
H HT TT TP P, , R RM MI I, , C CO OR RB BA A
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
326
interna corporativa, ou em aplicaes que adotam o modelo de trs camadas
sendo a camada intermediria um servidor J ava.
SGBD1
Cliente Ponte SGBD2
J ava J DBC-ODBC
SGBD3
2. Driver Java parcial e Api Nativa neste caso as chamadas J DBC so
convertidas para as chamadas s APIs nativas do SGBD. Como o driver
possui uma parte em cdigo binrio necessrio instalar algum cdigo na
mquina cliente, como feito nos drivers do tipo 1.
Protocolo do SGBD
Cliente J DBC J ava & SGBD
J ava Cdigo Binrio
3. Driver puro Java e protocolo de rede neste caso as chamadas J DBC so
convertidas para um protocolo de rede independente do SGBD que depois
traduzido para as chamadas s APIs nativas do SGBD por um servidor. Esta
uma arquitetura em trs camadas, onde o servidor middleware capaz de
conectar seus clientes J ava puros com vrios SGBDs. Esta soluo permite o
desenvolvimento de clientes 100% J ava, tendo como consequncia a no
necessidade de instalao de qualquer cdigo na mquina cliente.
SGBD1
Cliente Servidor de SGBD2
J ava acesso SGBD3
4. Driver Java Puro e protocolo nativo - neste caso as chamadas J DBC so
convertidas para as chamadas s APIs nativas do SGBD pelo driver, que foi
escrito totalmente em J ava.
Protocolo do SGBD
Cliente J DBC J ava SGBD
J ava (100% J ava)
J DBC DRIVER (100% Java)
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
327
Atualmente existe uma maior disponibilidade dos drivers tipo 1 e 2, mas a
tendncia que estes desapaream, sendo substitudos pelos drivers do tipo 3 e
4.
Obtendo os Drivers JDBC
Informaes sobre como obter drivers J DBC podem ser obtidas no site
http://www.javasoft.com/products/jdbc. Outra alternativa
acessar as pginas dos fabricantes de SGBD, para verificar se existe driver
disponvel.
Preparando um Banco de Dados
Os exemplos deste livro usam a ponte J DBC-ODBC para conectar com o
Banco de Dados. Isto facilita para os usurios que possuem um gerenciador
Banco de Dados pessoal como o Access, Paradox, e outros semelhantes. Alm
disso, como driver J DBC-ODBC est incorporado ao SDK, o usurio no
necessita procurar um driver para testar os exemplos. O lado negativo desta
abordagem est na necessidade de configurar o ODBC e no fato de que as
aplicaes remotas devero ser desenvolvidas em trs camadas. No entanto,
nada impede que o leitor use outro driver para rodar os exemplos, bastando para
isso alterar a chamada da carga do driver.
Primeiramente necessrio criar uma base de dados em algum SGBD.
Nos exemplos deste livro ser usada uma base contendo dados sobre livros,
alunos e emprstimos de livros aos alunos. No trataremos neste livro dos
conceitos relacionados com banco de dados relacionais nem sobre a linguagem
de consulta SQL. Existem vrios textos sobre o assunto onde o leitor pode
buscar informao.
As figuras XIII.3 a XII.5 mostram as tabelas que formam a base de dados
usada nos exemplos. O banco de dados formado por trs tabelas. Uma para
armazenar os dados dos alunos, outra para receber os dados dos livros e uma
terceira para conter os dados dos emprstimos.
alunos
matricula nome
1 Railer Costa Freire
2 Alexandre Alto
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
328
3 Andr M. A. Landro
4 Ana Maria Freitas
5 Claudia Maria
6 Alexandra Moreira
Figura XIII.3 Tabela de alunos
livros
codlivro titulo volume
1 Curso Pratico de J ava 1
2 Curso Pratico de J ava 2
3 Introduo a Compiladores 1
4 Fundamentos de Banco de Dados 1
5 Redes de Computadores 1
6 Redes de Computadores Fcil 2
7 Lgica matemtica 1
8 Engenharia de Software para Leigos 1
9 Aprenda Computao Grfica em duas 1
10 Aprenda Inteligncia Artificial em 5 1
Figura XIII.4 Tabela de livros.
emprestimos
codlivr matricu data_empresti data_devoluc
1 1 01/01/99 10/01/99
7 3 03/01/99 13/01/99
9 6 12/01/99 22/01/99
1 3 20/01/99 30/01/99
4 2 03/02/99 13/02/99
10 2 12/02/99 22/02/99
Figura XIII.5 Tabela de emprstimos.
Em um Banco de Dados Relacional cada tabela representa um conjunto
de entidades ou relacionamentos entre entidades, e cada linha da tabela
representa uma entidade particular ou um relacionamento entre entidades.
Assim, cada linha das tabelas alunos e livros representa um aluno e um livro
respectivamente. J na tabela emprstimos cada linha representa o
relacionamento por emprstimo de um livro a um aluno. Para estabelecer este
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
329
tipo de relacionamento em um Banco de Dados Relacional preciso colocar na
tabela que representa o relacionamento os atributos chaves de cada entidade que
participa da relao. Atributos chaves so os atributos que identificam cada
entidade. No caso dos alunos seu nmero de matrcula, uma vez que pode
existir dois alunos com o mesmo nome. J no caso de um livro o seu atributo
chave o cdigo do livro. Um Banco de Dados Relacional pode ser representado
pelo diagrama de classes da UML, como mostrado pela figura XIII.6, onde cada
tabela vista como uma classe.
Figura XIII.6 Diagrama de Classes do Banco de Dados.
Para criao das tabelas em banco de dados relacional deve-se usar
comandos DDL (Data Definition Language). O exemplo XX.XX mostra os
comandos em DDL para a criao das tabelas do exemplo:
CREATE TABLE ALUNOS (MATRICULA INT PRIMARY KEY,
NOME VARCHAR(50) NOT NULL);
CREATE TABLE LIVROS (CODLIVRO INT PRIMARY KEY,
TITULO VARCHAR(50) NOT NULL,
VOLUME INT NOT NULL);
CREATE TABLE EMPRESTIMOS (
CODLIVRO INT NOT NULL,
MATRICULA INT NOT NULL,
DATAEMP DATE NOT NULL,
DATADEV DATE NOT NULL,
CONSTRAINT PK_EMP PRIMARY KEY
(CODLIVRO, MATRICULA, DATAEMP),
CONSTRAINT FK_EMP1 FOREIGN KEY (CODLIVRO )
REFERENCES LIVROS (CODLIVRO ),
Alunos
matricula
nome
livros
codlivro
titulo
volume
emprestimos
data_emprestimo
data_devoluo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
330
CONSTRAINT FK_EMP2 FOREIGN KEY (MATRICULA)
REFERENCES ALUNOS (MATRICULA ));
Exemplo XX.XX Comandos em DDL para criao das tabelas em um SGBD
relacional.
Configurando o ODBC
Como utilizamos nos exemplos a ponte J DBC-ODBC necessrio
configurar o ODBC para acessar a base de dados acima. Na plataforma
Windows 98 isso feito da seguinte forma:
1. Execute o programa de configurao do ODBC por meio do cone
ODBC de 32bits do painel de controle.
2. Clique na pasta NFD do sistema e em seguida no boto de
adicionar.... O NFD do sistema escolhido no lugar da opo
NFD do usurio porque permite o compartilhado base de dados.
3. Selecione o driver do banco de dados e pressione o boto de concluir.
Por exemplo, se voc estiver usando o Access selecione a opo
Driver para o Microsoft Access (*.mdb).
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
331
Figura XIII.7 Seleo do driver ODBC no Windows.
4. Ao surgir a tela para a entrada seleo do Banco de Dados, utilize a
tecla Selecionar... localizar o arquivo onde est a base de dados e
preencha a janela de texto Nome da fonte de dados com o nome
que ser usado para referenciar a base.
5. Feche o programa de configurao.
A configurao de uma base de dados para ser acessada via ODBC
possui vrios outros detalhes que consideramos no ser relevantes para os
propsitos deste livro. A configurao como apresentada acima a suficiente
para se executar os exemplos deste livro.
Exemplo Inicial
O pacote java.sql fornece as classes e interfaces necessrias para a
conexo com uma base de dados e a posterior manipulao dos dados. As etapas
para se criar uma aplicao cliente de um SGBD em J ava so as seguintes:
1. Carregar o driver J DBC.
2. Estabelecer a conexo.
3. Criar um objeto Statement.
4. Executar o comando SQL por meio de um mtodo do objeto
Statement.
5. Receber o resultado, se for o caso.
Para comentar cada uma destas etapas utilizaremos o exemplo XII.1 que
mostra o cdigo de uma aplicao que lista no dispositivo de sada padro o
nome de todos os alunos.
import java.sql.*;
import java.net.URL;
class jdbc
{
public static void main(String a[])
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
332
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con =
DriverManager.getConnection("jdbc:odbc:biblioteca");
Statement stmt = con.createStatement();
ResultSet rs =
stmt.executeQuery("SELECT NOME FROM alunos");
System.out.println("Nome");
while(rs.next())
System.out.println(rs.getString("nome"));
stmt.close();
con.close();
} catch(Exception e)
{System.out.println(e.getMessage());
e.printStackTrace();}
}
}
Exemplo XX.XX Cdigo para listar o nome dos alunos.
Carregando o Driver
A primeira etapa carregar o driver J DBC. Para isso usado o mtodo
esttico forName() da classe Class. Em caso de erro este mtodo lana a
exceo ClassNotFoundException. O mtodo cria uma instncia do
driver e o registra junto ao DriverManager. No exemplo XIII.1 carregado o
driver J DBC-ODBC que vem junto com o SDK.
Estabelecendo a conexo
A segunda etapa realizada por meio do mtodo esttico
getConnection() da classe DriverManager. Este mtodo, na sua forma mais
simples, recebe como parmetro um URL que faz referncia a base de dados e
retorna um objeto da classe Connection, que representa a conexo com a base de
dados. J discutimos sobre URLs no captulo XI. No entanto, existem algumas
particularidades no que refere a URLs que fazem referncia Banco de Dados.
O formato padro deste tipo de URL o seguinte:
jdbc:<subprotocolo>:<identificador>
onde:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
333
1. jdbc representa o protocolo;
2. <subprotocolo>se refere ao driver ou ao mecanismo de conexo com
o Banco de Dados, que pode ser suportado por um ou mais drivers.
No exemplo XII.1 o nome utilizada a ponte J DBC-ODBC,
representada pela palavra odbc no subprotocolo.
3. <identificador> a parte onde se identifica o Banco de Dados. A
forma de identificao varia de acordo com o subprotocolo. No nosso
exemplo colocado o mesmo nome usado para identificar a fonte de
dados na configurao do ODBC. A sintaxe para o subprotocolo odbc
a seguinte:
jdbc:odbc:<fonte de dados>[;<atributo>=<valor>]*
onde <atributo>e <valor>representam parmetros a serem passados
para o gerente de conexo do Banco de Dados.
Um banco de dados acessado remotamente requer maiores informaes,
como o nome do host e a porta. Tanto o uso local como remoto pode requerer a
identificao do usurio, assim como uma senha. Estes dados podem ser
passados como parmetro no mtodo getConnection():
getConnection("jdbc:odbc:contas",ana,sght);
ou como parte do URL. Alguns exemplos de URLs esto descritos na tabela
XIII.1
URL Descrio
jdbc:odbc:biblioteca Referencia fonte de dados biblioteca via
ponte J DBC-ODBC.
jdbc:odbc:bd1;CacheSize=20 Referencia fonte de dados bd1 via ponte
J DBC-ODBC. definido o tamanho do
cache.
jdbc:odbc:contas;UID=ana;PWD=sght Referencia fonte de dados contas via
ponte J DBC-ODBC. passado tambm o
nome do usurio e a senha.
jdbc:oracle:thin:@sap.dpi.ufv.br:1521:agenda Referencia fonte de dados agenda no host
remoto sap.dpi.ufv.br via subprotocolo
oracle. passado tambm o nmero da
porta usada no acesso.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
334
Tabela.1 Exemplos de URLs JDBC.
Criando e Executando Comandos
necessrio cria um ou mais objetos da classe Statement, que possui os
mtodos necessrios para manipular a base de dados. Este objeto criado por
meio do mtodo createStatement() do objeto da classe Connection.
Statement stmt = con.createStatement();
Podemos ento usar o objeto Statement para executar comandos de
manipulao do Banco de Dados. No exemplo XIII.1 o objetivo recuperar s
nomes dos alunos. Este objetivo atingido por meio da execuo do comando
SQL
SELECT nome FROM alunos
passado como parmetro para o mtodo executeQuery() do objeto
Statement. Este mtodo retorna um objeto que implementa a interface
ResultSet, e que fornece os meios de acesso ao resultado da consulta. Muitas
vezes, como no exemplo, o resultado de uma consulta uma tabela com vrias
linhas. O programador pode utilizar o objeto ResultSet para acessar cada linha
da tabela resultante em sequncia. Para isso o objeto mantm um apontador para
a linha corrente, chamado de cursor. Inicialmente o cursor posicionado antes
da primeira linha, movimentado para prxima linha por meio de chamadas ao
mtodo next() do objeto ResultSet.
O mtodo executeQuery() usado apenas para consultas. Alm
desse mtodo, a classe Statement possui o mtodo execute() que retorna
mltiplos ResultSets e o mtodo executeUpdate(), para atualizao
(comandos INSERT, DELETE e UPDATE da linguagem SQL), criao de
tabelas (comandos CREATE TABLE) e remoo (DROP TABLE). O valor de
retorno do mtodo executeUpdate() um valor inteiro indicando o
nmero de linhas afetadas ou zero no caso do DROP TABLE. Um exemplo de
um comando para inserir um uma novo aluno na tabela seria:
stmt.executeUpdate("INSERT INTO alunos VALUES(7, 'Ana
mia')");
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
335
Recuperando Valores
O objeto ResultSet possui os mtodos necessrios para recuperar os
valores de cada coluna da tabela, bastando passar o nome da coluna como
parmetro. No exemplo XIII.1 utilizado mtodo getString() para
recuperar o valor da coluna nome. Os mtodos para recuperao possuem o
formato geral getXXX(), onde XXX o nome de um tipo. A tabela XIII.2
mostra qual o mtodo mais indicado para cada tipo SQL.
T
I
N
Y
I
N
T
S
M
A
L
L
I
N
T
I
N
T
E
G
E
R
B
I
G
I
N
T
R
E
A
L
F
L
O
A
T
D
O
U
B
L
E
D
E
C
I
M
A
L
N
U
M
E
R
I
C
B
I
T
C
H
A
R
V
A
R
C
H
A
R
L
O
N
G
V
A
R
C
H
A
R
B
I
N
A
R
Y
V
A
R
B
I
N
A
R
Y
L
O
N
G
V
A
R
B
I
N
A
R
Y
D
A
T
E
T
I
M
E
T
I
M
E
S
T
A
M
P
getByte X x x x x x x x x x x x x
getShort x X x x x x x x x x x x x
getInt x x X x x x x x x x x x x
getLong x x x X x x x x x x x x x
getFloat x x x x X x x x x x x x x
getDouble x x x x x X X x x x x x x
getBigDecimal x x x x x x x X X x x x x
getBoolean x x x x x x x x x X x x x
getString x x x x x x x x x x X X x x x x x x x
getBytes X X x
getDate x x x X x
getTime x x x X x
getTimestamp x x x x X
getAsciiStream x x X x x x
getUnicodeStre
am
x x X x x x
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
336
getBinaryStrea
m
x x X
getObject x x x x x x x x x x x x x x x x x x x
x indica que o mtodo pode ser usado para recuperar o valor no tipo SQL especificado.
X indica que o mtodo recomendado para ser usado na recuperao do valor no tipo SQL especificado
Tabela XIII.2 Tabelas com os mtodos indicados para recuperao de
valores.
possvel recuperar o valor da coluna passando como parmetro o
nmero da coluna no lugar de seu nome. Neste caso a recuperao no nome do
aluno no exemplo XIII.1 ficaria na seguinte forma:
rs.getString(1);
Transaes e Nvel de Isolamento
Transao
Uma Transao um conjunto de operaes realizadas sobre um banco
de dados tratadas atomicamente, em outras palavras, ou todas operaes so
realizadas e o seu resultado registrado permanentemente na base de dados ou
nenhuma operao realizada. Por default, o banco de dados trata cada operao
como uma transao, realizando implicitamente uma operao de commit ao fim
de cada uma delas. A operao de commit registra permanentemente o resultado
da transao na tabela.
No entanto, existem situaes onde necessrio tratar como uma
transao um conjunto de operaes, e no apenas uma transao. Por exemplo,
suponha que em um Banco de Dados de uma agncia bancria exista uma tabela
com informaes sobre a conta de corrente e outra com informaes sobre
contas de poupana. Suponha tambm que um cliente deseje transferir o dinheiro
da conta corrente para uma conta de poupana. Essa transao constituda
pelas seguintes operaes:
1. Caso exista saldo suficiente, subtrao do montante da transferncia
do saldo da conta corrente.
2. Adio do montante da transferncia ao saldo da conta de poupana.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
337
As operaes acima precisam ocorrer totalmente ou o efeito de nenhuma
delas deve ser registrado na base de dados. Caso contrrio podemos ter uma
situao onde o dinheiro sai da conta corrente mas no entra na conta da
poupana. Este estado, onde as informaes do banco de dados no reflete a
realidade, chamado de estado inconsistente.
De modo a obter esse controle sobre as transaes necessrio
desabilitar o modo de auto-commit. Isto feito por meio mtodo
setAutoCommit() do objeto Connection.
con.setAutoCommit(false);
A partir do momento em que executado o comando acima, o
programador responsvel pela indicao do final da transao, por meio da
execuo do mtodo commit() do objeto Connection.
con.commit();
Se alguma exceo for levantada durante a execuo de qualquer
operao da transao, o programador pode usar o mtodo rollback() para
desfazer as operaes j realizadas aps o ltimo commit().
con.setAutoCommit(false);
try
{
Statement stmt = con.createStatement();
stmt.executeUpdate(UPDATE ... );
stmt.executeUpdate(UPDATE ... );
con.commit();
stmt.close();
}
catch(Exception e){con.rollback();}
finally
{
try{ con.setAutoCommit(true);}
catch(SQLException sqle)
{System.out.prinln(sql.getMessage());}
}
Exemplo XX.X Uso dos mtodos commit() e rollback().
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
338
Nveis de isolamento
Alm da atomicidade outra propriedade desejvel em uma transao o
isolamento. A propriedade de isolamento implica que uma transao no
afetada pelas operaes realizadas por outras transaes que esto sendo
realizadas concorrentemente.
O isolamento completo entre transaes prejudica muito a execuo
concorrente de transaes e pode ser desnecessrio em determinados tipos de
aplicaes. Por isso os SGBDs permitem que o programador defina o nvel de
isolamento entre as transaes. De acordo com o relaxamento do isolamento
certos problemas devido a interferncia entre as transaes podem ocorrer e o
programador deve estar ciente disso.
O nmero de nveis de isolamento, sua nomenclatura e caractersticas
depende do SGBD utilizado. Descreveremos os nveis de isolamento definidos
no pacote java.sql. Para exemplificar os problemas que podem ocorrer
devido a interferncia entre transaes utilizaremos um banco de dados exemplo
com a seguinte tabela:
NumCC Saldo
10189-9
20645-7
200,00
300,00
Read uncommitted - o nvel menos restritivo. Pode ocorrer leituras de
registros no committed (Dirty reads). Usados em onde no existe
concorrncia ou no existem alteraes em registros ou quando essas
alteraes no so relevantes. Exemplo de problema: Uma transao deve
transferir R$50,00 da conta 10189-9 para a conta 20645-7 e uma segunda
transao deve somar R$70,00 conta 10189-9. A figura abaixo mostra o
estado inicial e o estado final desejado da tabela:
NumCC Saldo NumCC Saldo
10189-9
20645-7
200,00
300,00
10189-9
20645-7
220,00
350,00
Estado desejado aps as
transaes
Estado antes das
transaes
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
339
Cada transao divida em operaes de leitura e escrita. Suponha que o
intercalamento das operaes seja feito como mostrado abaixo:
Transao 1 Transao 2
leitura do saldo 10189
Escrita do Saldo-50,00
leitura do saldo 20645
(falha na transao,
realizado rollback)
leitura do saldo 10189
Escrita do Saldo+70,00
Como a transao 1 falhou o valor lido pela transao 2 um valor que no
foi tornado permanente na tabela. Isto faz com que a transao 2 opere sobre
um resultado desfeito. A tabela resultante, mostrada abaixo estar em um
estado inconsistente.
NumCC Saldo
10189-9
20645-7
220,00
300,00
Read committed - Somente registros committed podem ser lidos. Evita o
problema de Dirty reads, no entanto duas leituras de um mesmo item em
uma mesma transao podem possuir valores diferentes, uma vez que o valor
pode ser mudado por outra transao entre duas leituras.
Repeatable Read - Somente registros committed podem ser lidos, alm
disso impede a alterao de um item lido pela transao. Evita o problema de
Dirty reads e o problema do non-repeatable Read .
Serializable - o nvel mais restritivo. Impede Dirty reads e non-repeatable
reads. Alm disso impede o problema de phantom reads onde um conjunto
de registros satisfazendo a condio WHERE lido enquanto outra transao
insere novos registros que satisfazem a condio.
Para se definir o nvel de isolamento na linguagem J ava usa-se um objeto
DatabaseMetaData que obtido por meio do objeto getMetaData() do
Connection. Primeiro preciso saber se o SGBD suporta o nvel de
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
340
isolamento desejado para depois definir o nvel. O exemplo XX.X mostra uma
sequncia tpica comandos.
DatabaseMetaData meta=con.getMetaData();
if(meta.supportsTransactionIsolationLevel(
con.TRANSACTION_READ_COMMITTED)) {
con.setTransactionIsolation(
con.TRANSACTION_READ_COMMITTED);
}
else return;
Exemplo XX.X Exemplo do estabelecimento do nvel de isolamento.
A tabela abaixo mostra as constantes relacionadas com os nveis de
isolamento da linguagem J ava:
Constante
TRANSACTION_NONE
TRANSACTION_READ_UNCOMMITTED
TRANSACTION_READ_COMMITTED
TRANSACTION_REPEATABLE_READ
TRANSACTION_SERIALIZABLE
Tabela XX.X Tabela com as constantes dos nveis de isolamento.
Prepared Statements
Cada vez que se executa um comando SQL passado por meio de uma
String. Este String deve ser analisado pelo processador de SQL do SGBD que
ir, no caso da String estar sintaticamente correta, gerar um cdigo binrio que
ser executado para atender solicitao. Todo esse processo caro e sua
execuo repetidas vezes ter um impacto significativo sobre o desempenho da
aplicao e do SGBD como um todo.
Existem duas abordagens para tentar solucionar esse problema:
Comandos preparados (prepared statements) e procedimentos armazenados
(stored procedures). Discutiremos primeiramente os prepared statements.
Prepared Statement indicado nos casos onde um comando ser
executado vrias vezes em uma aplicao. Neste caso melhor compilar o
comando uma nica vez e toda vez que for necessrio execut-lo basta enviar o
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
341
comando compilado. Alm disso, o comando pr-compilado pode ser
parametrizado, tornando-o mais genrico e, portanto, apto a expressar um maior
nmero de consultas.
Para criar um Prepared Statement necessrio obter um objeto
PreparedStatement por meio do mtodo prepareStatement() do
objeto Connection, passando como argumento um comando SQL.
PreparedStatement pstmt = con.prepareStatement(
INSERT INTO alunos(matricula,nome) VALUES(?, ? ));
O comando anterior insere uma nova linha na tabela alunos com os
valores das colunas matricula e nome passados por parmetro. O caractere ?
representa o parmetro. Este tipo de comando s possui valor tendo parmetros,
caso contrrio teria pouca chance de ser reutilizado. Para executar o comando
devemos especificar o valor dos parmetros e executar o comando, como
mostrado no exemplo abaixo:
pstmt.clearParameters();
pstmt.setInt(1,8);
pstmt.setString(2,Clara Maria);
pstmt.executeUpdate();
Antes de especificar os parmetros necessrio limpar qualquer outro
parmetro previamente especificado. Para especificar os parmetros so
utilizados um conjunto de mtodos com o nome no formato setXXX(), onde
XXX o tipo sendo passado. O primeiro parmetro do mtodo setXXX() o
ndice da ocorrncia do caractere ? que ser substitudo pelo valor. O segundo
parmetro o valor que ser transmitido.
Procedimentos Armazenados (Stored Procedures)
A maioria dos SGBDs possuem algum tipo de linguagem de
programao interna, como por exemplo a PL/SQL do Oracle ou mesmo J ava e
C/C++. Estas linguagens permitem que os desenvolvedores insiram parte do
cdigo da aplicao diretamente no banco de dados e invoquem este cdigo a
partir da aplicao. Esta abordagem possui as seguintes vantagens:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
342
Reuso de cdigo o cdigo precisa ser escrito apenas uma vez e usado
em vrias aplicaes, comunicando com vrias linguagens.
Independencia entre a aplicao e o esquema do BD se o esquema
mudar, provavelmente apenas os procedimentos armazenados.
Desempenho os procedimentos so previamente compilados,
eliminando esta etapa.
Segurana as aplicaes possuem privilgio apenas para execuo de
procedimentos armazenados, evitando assim acessos no autorizados.
A sintaxe dos procedimentos armazenados depende do SGBD em
questo. Utilizaremos um exemplo em PL/SQL. No exemplo abaixo o
procedimento retorna o nome do aluno a partir de sua matricula.
CREATE OR REPLACE PROCEDURE sp_obtem_nome
(id IN INTEGER, Nome_aluno out VARCHAR2)IS
BEGIN
SELECT nome INTO Nome_aluno
FROM alunos
WHERE matricula = id;
END;
/
Para invocar o procedimento anterior de dentro de uma aplicao J ava
necessrio obter um objeto CallableStatement por meio do mtodo
prepareCall() do objeto Connection, passando como argumento um
comando SQL.
CallableStatement cstmt =
con.prepareCall("{ CALL sp_obtem_nome(?,?)}");
cstmt.registerOutParameter(2, Types.VARCHAR);
cstmt.setInt(1, 3);
cstmt.execute();
System.out.prinln(O nome do aluno numero 3 :
+cstmt.getString(2);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
343
Agenda Eletrnica verso JDBC
Pessoa
import java.io.*;
public class pessoa implements Serializable
{
String Nome;
String Tel;
// Construtor
public pessoa(String n, String t) {Nome = n; Tel = t;}
public String getNome(){return Nome;}
public String getTel(){return Tel;}
}
agenda
import java.util.*;
import java.io.*;
import java.sql.*;
import java.net.URL;
public class agenda
{
Connection con=null;
// Construtor
public agenda()throws Exception
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con=DriverManager.getConnection("jdbc:odbc:agenda");
}
/**
CloseAgenda
*/
public void CloseAgenda()
{
if (con != null) try{con.close();}catch(Exception e){};
}
/**
inserir
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
344
*/
public void inserir(pessoa p)
{
if (con == null) return;
try
{
Statement stmt = con.createStatement();
stmt.executeUpdate("INSERT INTO pessoas(nome,telefone)
"+
"values('"+p.getNome()+"','"+p.getTel()+"')");
stmt.close();
}catch(Exception e) {System.err.println(e);}
}
/**
Consultar
*/
/**
listar
*/
public Enumeration getLista()
{
if (con == null) return null;
Vector pessoas = new Vector();
try {
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery
("SELECT Nome, Telefone FROM pessoas");
while(rs.next())
pessoas.addElement(new
pessoa(rs.getString("Nome"),
rs.getString("Telefone")));
stmt.close();
} catch(Exception e) {System.out.println(e.getMessage());
e.printStackTrace();}
return pessoas.elements();
}
}
Servidor
import java.util.*;
import java.net.*;
import java.io.*;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
345
/**
CLASS server
*/
class server
{
public static void main(String args[])
{
String oHost="localhost";
ServerSocket ssocket=null;
serversec oServersec;
int pt = 4444;
agenda ag;
try {ag = new agenda();}
catch(Exception e){System.err.println(e); return;};
if (args.length > 0) pt = Integer.parseInt(args[0]);
try
{
ssocket = new ServerSocket(pt);
pt = ssocket.getLocalPort();
oHost =
ssocket.getInetAddress().getHostName().trim();
}
catch(Exception e) {System.err.println(e);
System.exit(1);}
System.out.println("Porta:"+pt+" Host: "+oHost);
while(true)
{
try
{
Socket clisocket = ssocket.accept();
oServersec = new serversec(ag,clisocket);
oServersec.start();
} catch(Exception e) {System.err.println(e);}
}
}
}
/**
CLASS serversec
*/
class serversec extends Thread
{
Socket oSocket;
BufferedWriter soutput;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
346
BufferedReader cinput;
agenda ag;
public serversec(agenda ag, Socket aoSocket)
{
this.ag = ag;
oSocket = aoSocket;
}
public void run()
{
try
{
soutput = new BufferedWriter(new
OutputStreamWriter(oSocket.getOutputStream()));
cinput = new BufferedReader(new
InputStreamReader(oSocket.getInputStream()));
String losLinha = cinput.readLine();
switch(losLinha.charAt(0))
{
case 'i': String Nome = cinput.readLine();
String Tel = cinput.readLine();
ag.inserir(new pessoa(Nome,Tel));
soutput.write("OK\n#\n");
break;
case 'l': pessoa p;
for (Enumeration e = ag.getLista();
e.hasMoreElements() ;)
{
p = (pessoa) e.nextElement();
soutput.write(p.getNome()+"\n"+p.getTel()+"\n");
}
soutput.write("#\n");
break;
}
soutput.flush();
Thread.yield();
soutput.close();
oSocket.close();
}
catch(Exception e) {System.err.println(e);}
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
347
Applet
import java.awt.*;
import java.applet.*;
import java.util.*;
import java.net.*;
import java.io.*;
public class agendaapplet extends Applet
{
int port = 4444;
TextField txtNome = new TextField();
TextField txtTel = new TextField();
Label label1 = new Label();
Label label2 = new Label();
Button btIns = new Button();
Button btList = new Button();
Button btCons = new Button();
Button btSair = new Button();
TextArea Saida = new TextArea();
Button btLimpar = new Button();
public void init()
{
setLayout(null);
setSize(376,224);
add(txtNome);
txtNome.setBounds(108,48,232,24);
add(txtTel);
txtTel.setBounds(108,84,232,24);
label1.setText("Nome");
add(label1);
label1.setBounds(24,48,60,26);
label2.setText("Telefone");
add(label2);
label2.setBounds(24,84,60,26);
btIns.setActionCommand("button");
btIns.setLabel("Inserir");
add(btIns);
btIns.setBackground(java.awt.Color.lightGray);
btIns.setBounds(12,12,49,23);
btList.setActionCommand("button");
btList.setLabel("Listar");
add(btList);
btList.setBackground(java.awt.Color.lightGray);
btList.setBounds(149,12,60,23);
btCons.setActionCommand("button");
btCons.setLabel("Consultar");
add(btCons);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
348
btCons.setBackground(java.awt.Color.lightGray);
btCons.setBounds(75,12,60,23);
btSair.setActionCommand("button");
btSair.setLabel("Sair");
add(btSair);
btSair.setBackground(java.awt.Color.lightGray);
btSair.setBounds(297,12,60,23);
add(Saida);
Saida.setBounds(24,120,338,90);
btLimpar.setActionCommand("button");
btLimpar.setLabel("Limpar");
add(btLimpar);
btLimpar.setBackground(java.awt.Color.lightGray);
btLimpar.setBounds(223,12,60,23);
SymMouse aSymMouse = new SymMouse();
btSair.addMouseListener(aSymMouse);
btIns.addMouseListener(aSymMouse);
btList.addMouseListener(aSymMouse);
btLimpar.addMouseListener(aSymMouse);
}
public void transmit(int port,String mensagem)
{
BufferedWriter soutput;
BufferedReader cinput;
Socket clisoc=null;
try
{
if (clisoc != null) clisoc.close();
clisoc = new
Socket(InetAddress.getByName(getCodeBase().getHost()),port);
soutput = new BufferedWriter (new
OutputStreamWriter(clisoc.getOutputStream()));
cinput = new BufferedReader(new
InputStreamReader(clisoc.getInputStream()));
soutput.write(mensagem+"\n");
soutput.flush();
String losRet = cinput.readLine();
while (losRet.charAt(0)!='#')
{
Saida.setText(Saida.getText()+losRet+"\n");
losRet = cinput.readLine();
}
Thread.sleep(500);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
349
soutput.close();
clisoc.close();
}
catch(Exception e) {System.err.println(e);}
}
class SymMouse extends java.awt.event.MouseAdapter
{
public void mouseClicked(java.awt.event.MouseEvent event)
{
Object object = event.getSource();
if (object == btSair) btSair_MouseClick(event);
else if (object == btIns) btIns_MouseClick(event);
else if (object == btList) btList_MouseClick(event);
else if (object == btLimpar)
btLimpar_MouseClick(event);
}
}
void btSair_MouseClick(java.awt.event.MouseEvent event)
{
System.exit(0);
}
void btIns_MouseClick(java.awt.event.MouseEvent event)
{
String nome = txtNome.getText();
String tel = txtTel.getText();
if (nome.length()>0 && tel.length()>0)
transmit(port,"i\n"+nome+"\n"+tel+"\n");
}
void btList_MouseClick(java.awt.event.MouseEvent event)
{
transmit(port,"l\n");
}
void btLimpar_MouseClick(java.awt.event.MouseEvent event)
{
Saida.setText("");
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
350
Captulo XVI Servlets e JSP
Servlets e J SP so duas tecnologias desenvolvidas pela Sun para
desenvolvimento de aplicaes na Web a partir de componentes J ava que
executem no lado servidor. Essas duas tecnologias fazem parte da plataforma
J 2EE (J ava 2 Platform Enterprise Edition) que fornece um conjunto de
tecnologias para o desenvolvimento de solues escalveis e robustas para a
Web. Neste livro abordaremos apenas as tecnologias Servlets e J SP, sendo o
suficiente para o desenvolvimento de sites dinmicos de razovel complexidade.
Se a aplicao exigir uma grande robustez e escalabilidade o leitor deve
considerar o uso em conjunto de outras tecnologias da plataforma J 2EE.
Servlets
Servlets so classes J ava que so instanciadas e executadas em
associao com servidores Web, atendendo requisies realizadas por meio do
protocolo HTTP. Ao serem acionados, os objetos Servlets podem enviar a
resposta na forma de uma pgina HTML ou qualquer outro contedo MIME. Na
verdade os Servlets podem trabalhar com vrios tipos de servidores e no s
servidores Web, uma vez que a API dos Servlets no assume nada a respeito do
ambiente do servidor, sendo independentes de protocolos e plataformas. Em
outras palavras Servlets uma API para construo de componentes do lado
servidor com o objetivo de fornecer um padro para comunicao entre clientes
e servidores. Os Servlets so tipicamente usados no desenvolvimento de sites
dinmicos. Sites dinmicos so sites onde algumas de suas pginas so
construdas no momento do atendimento de uma requisio HTTP. Assim
possvel criar pginas com contedo varivel, de acordo com o usurio, tempo,
ou informaes armazenadas em um banco de dados.
Servlets no possuem interface grfica e suas instncias so executadas
dentro de um ambiente J ava denominado de Container. O container gerencia as
instncias dos Servlets e prov os servios de rede necessrios para as
requisies e respostas. O container atua em associao com servidores Web
recebendo as requisies reencaminhada por eles. Tipicamente existe apenas
uma instncia de cada Servlet, no entanto, o container pode criar vrios threads
de modo a permitir que uma nica instncia Servlet atenda mais de uma
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
351
requisio simultaneamente A figura XX fornece uma viso do relacionamento
destes componentes.
Figura XVI-1. Relacionamento entre Servlets, container e servidor Web
Servlets provem uma soluo interessante para o relacionamento
cliente/servidor na Internet, tornando-se uma alternativa para a implantao de
sistemas para a Web. Antes de entrarmos em detalhes na construo de Servlets,
compararemos esta soluo com outras duas solues possveis para implantao
de aplicaes na Internet.
Applets X Servlets
Apesar de ser uma soluo robusta existem problemas no uso de Applets para
validao de dados e envio para o servidor. O programador precisa contar com o
fato do usurio possuir um navegador com suporte a J ava e na verso
apropriada. Voc no pode contar com isso na Internet, principalmente se voc
deseja estender a um grande nmero de usurio o acesso s suas pginas. Em se
tratando de Servlets, no lado do cliente pode existir apenas pginas HTML,
evitando restries de acesso s pginas. Em resumo, o uso de Applets no
recomendado para ambientes com mltiplos navegadores ou quando a semntica
da aplicao possa ser expressa por componentes HTML.
Servidor
Web
Requisies
Mquina Virtual J ava
Container
Instncias de Servlets
Respostas
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
352
CGI X Servlets
Como visto no Captulo IX, scripts CGI (Common Gateway Interface),
acionam programas no servidor. O uso de CGI sobrecarrega o servidor uma vez
cada requisio de servio acarreta a execuo de um programa executvel (que
pode ser escrito em com qualquer linguagem que suporte o padro CGI) no
servidor, alm disso, todo o processamento realizado pelo CGI no servidor. Se
houver algum erro na entrada de dados o CGI tem que produzir uma pgina
HTML explicando o problema. J os Servlets so carregados apenas uma vez e
como so executados de forma multi-thread podem atender mais de uma mesma
solicitao por simultaneamente. Verses posteriores de CGI contornam este
tipo de problema, mas permanecem outros como a falta de portabilidade e a
insegurana na execuo de cdigo escrito em uma linguagem como C/C++.
A API Servlet
A API Servlet composta por um conjunto de interfaces e Classes. O
componente mais bsico da API interface Servlet. Ela define o
comportamento bsico de um Servlet. A figura XX.XX mostra a interface
Servlet.
public interface Servlet {
public void init(ServletConfig config)
throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req,
ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
Figura XV.XX. Interface Servlet.
O mtodo service() responsvel pelo tratamento de todas das
requisies dos clientes. J os mtodos init() e destroy() so chamados
quando o Servlet carregado e descarregado do container, respectivamente. O
mtodo getServletConfig() retorna um objeto ServletConfig que
contm os parmetros de inicializao do Servlet. O mtodo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
353
getServletInfo() retorna um String contendo informaes sobre o
Servlet, como verso e autor.
Tendo como base a interface Servlet o restante da API Servlet se
organiza hierarquicamente como mostra a figura XV.XX.
Figura XV.XX. Hierarquia de classes da API Servlet.
A classe GenericServlet implementa um servidor genrico e
geralmente no usada. A classe HttpServlet a mais utilizada e foi
especialmente projetada para lidar com o protocolo HTTP. A figura XX.XX
mostra a definio da classe interface HttpServlet.
HttpServlet
public abstract class HttpServlet
extends GenericServlet
implements java.io.Serializable
Figura XV.XX. Definio da classe HttpServlet.
Note que a classe HttpServlet uma classe abstrata. Para criar um
Servlet que atenda requisies HTTP o programador deve criar uma classe
derivada da HttpServlet e sobrescrever pelo menos um dos mtodos
abaixo:
Servlet
GenericServlet
HttpServlet
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
354
doGet Trata as requisies HTTP GET.
doPost Trata as requisies HTTP POST.
doPut Trata as requisies HTTP PUT.
doDelete Trata as requisies HTTP DELETE.
Tabela XV.XX. Mtodos da classe HttpServlet que devem ser
sobrescritos para tratar requisies HTTP.
Todos esses mtodos so invocados pelo servidor por meio do mtodo
service(). O mtodo doGet() trata as requisies GET. Este tipo de
requisio pode ser enviada vrias vezes, permitindo que seja colocada em um
bookmark. O mtodo doPost() trata as requisies POST que permitem que o
cliente envie dados de tamanho ilimitado para o servidor Web uma nica vez,
sendo til para enviar informaes tais como o nmero do carto de crdito. O
mtodo doPut() trata as requisies PUT. Este tipo de requisio permite que
o cliente envie um arquivo para o servidor semelhana de como feito via
FTP. O mtodo doPut() trata as requisies DELETE, permitindo que o
cliente remova um documento ou uma pgina do servidor. O mtodo
service(), que recebe todas as requisies, em geral no sobrescrito, sendo
sua tarefa direcionar a requisio para o mtodo adequado.
Exemplo de Servlet
Para entendermos o que um Servlet nada melhor que um exemplo
simples. O exemplo XV.XX gera uma pgina HTML em resposta a uma
requisio GET. A pgina HTML gerada contm simplesmente a frase Ola
mundo!!!. Este um Servlet bem simples que ilustra as funcionalidades bsicas
da classe.
import javax.servlet.*;
import javax.servlet.http.*;
public class Ola extends HttpServlet
{
public String getServletInfo() {return "Ola verso 0.1";}
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
355
res.setContentType("text/html");
java.io.PrintWriter out =res.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet</title>");
out.println("</head>");
out.println("<body>Ola mundo!!!");
out.println("</body>");
out.println("</html>");
out.close();
}
}
Exemplo XV.XX. Servlet Ola.
O mtodo doGet() recebe dois objetos: um da classe
HttpServletRequest e outro da classe HttpServletResponse. O
HttpServletRequest responsvel pela comunicao do cliente para o
servidor e o HttpServletResponse responsvel pela comunicao do
servidor para o cliente. Sendo o exemplo XV.XX apenas um exemplo simples
ele ignora o que foi enviado pelo cliente, tratando apenas de enviar uma pgina
HTML como resposta. Para isso utilizado o objeto da classe
HttpServletResponse. Primeiramente usado o mtodo
setContentType() para definir o tipo do contedo a ser enviado ao cliente.
Esse mtodo deve ser usado apenas uma vez e antes de se obter um objeto do
tipo PrintWriter ou ServletOutputStream para a resposta. Aps isso
usado o mtodo getWriter() para se obter um objeto do tipo
PrintWriter que usado para escrever a resposta. Neste caso os dados da
resposta so baseados em caracteres. Se o programador desejar enviar a resposta
em bytes deve usar o mtodo getOutputStream() para obter um objeto
OutputStream. A partir de ento o programa passa usar o objeto
PrintWriter para enviar a pgina HTML.
Compilando o Servlet
A API Servlet ainda no foi incorporado ao SDK, portanto, para compilar
um Servlet preciso adicionar a API Servlet ao pacote SDK. Existem vrias
formas de se fazer isso. A Sun fornece a especificao da API e diversos
produtores de software executam a implementao. Atualmente, a especificao
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
356
da API Servlet est na verso 2.XX. Uma das implementaes da API que pode
ser baixada gratuitamente pela Internet a fornecida pelo projeto J akarta
(http://jakarta.apache.org) denominada de Tomcat. A
implementao da API Servlet feita pelo projeto J akarta a implementao de
referncia indicada pela Sun. Ou seja, a implementao que os outros
fabricantes devem seguir para garantir a conformidade com a especificao da
API. No entanto, uma vez que o Tomcat a implementao mais atualizada da
API, tambm a menos testada e, por consequncia, pode no ser a mais estvel
e com melhor desempenho.
Instalando o Tomcat
Assim como para se executar um Applet era preciso de um navegador
Web com J ava habilitado no caso de Servlets preciso de servidor Web que
execute J ava ou que passe as requisies feitas a Servlets para programas que
executem os Servlets. O Tomcat tanto a implementao da API Servlet como a
implementao de um container, que pode trabalhar em associao com um
servidor Web como o Apache ou o IIS, ou pode tambm trabalhar isoladamente,
desempenhando tambm o papel de um servidor Web. Nos exemplos aqui
mostrados usaremos o Tomcat isoladamente. Em um ambiente de produo esta
configurao no a mais adequada, uma vez que os servidores Web possuem
um melhor desempenho no despacho de pginas estticas. As instrues para
configurar o Tomcat para trabalhar em conjunto com um servidor Web podem
ser encontradas junto s instrues gerais do programa. As figuras XV.XX
ilustram essas duas situaes.
Figura XV.XX. Servidor Web habilitado para Servlet.
Servidor Web
Servlet habilitado
Internet
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
357
Figura XV.XX. Servidor Web reencaminhando as requisies para o Servlet
container.
A verso estvel do Tomcat a 3.2.3.XX aps baix-la do site do
projeto J akarta o usurio deve descomprimir o arquivo. Por exemplo, no
ambiente Windows o usurio pode descomprimir o arquivo na raiz do disco C:,
o que gerar a seguinte rvore de diretrios:
C:\ jakarta-tomcat-3.2.3
|
|______bin
|______conf
|______doc
|______lib
|______logs
|______src
|______webapps
No diretrio bin encontram-se os programas execuo e interrupo do
container Tomcat. No diretrio conf encontram-se os arquivos de configurao.
No diretrio doc encontram-se os arquivos de documentao. No diretrio lib
encontram-se os bytecodes do container e da implementao da API. No
diretrio logs so registradas as mensagens da geradas durante a execuo do
sistema. No diretrio src encontram-se os arquivos fontes do container e da
implementao da API de configurao. Finalmente, No diretrio webapps
encontram-se as pginas e cdigos das aplicaes dos usurios.
No ambiente MS-Windows aconselhamos usar um nome dentro do
formato 8.3 (oito caracteres para o nome e trs para o tipo). Assim o diretrio
jakarta-tomcat-3.2.3 poderia ser mudado para simplesmente tomcat.
Internet Servidor Web
Servlet Container
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
358
Antes de executar o Tomcat necessrio definir duas variveis de
ambiente. Por exemplo, supondo que no MS-Windows o Tomcat foi instalado no
diretrio c:\tomcat e que o SDK est instalado no diretrio c:\jdk1.3
ento as seguintes variveis de ambiente devem ser definidas:
set JAVA_HOME=C:\jdk1.3
set TOMCAT_HOME=C:\tomcat
Agora possvel executar o Tomcat por meio do seguinte comando:
C:\tomcat\bin\startup.bat
Para interromper a execuo servidor basta executar o arquivo
c:\tomcat\bin\shutdown.bat
Falta de espao para variveis de ambiente
Caso ao iniciar o servidor aparea a mensagem sem espao de ambiente
clique com o boto direito do mouse no arquivo .bat e edite as propriedades definindo o
ambiente inicial com 4096. Feche o arquivo execute novamente.
Ao entrar em execuo o servidor l as configuraes constantes no
arquivo server.xml e, por default, se anexa porta 8080. Para verificar se o
programa est funcionando corretamente execute um navegador como o
Netscape ou o Internet Explorer e digite a seguinte URL:
http://127.0.0.1:8080/index.html
A figura XX.XX mostra a tela principal do Tomcat.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
359
Figura XV.XX. Tela inicial do Tomcat.
A nmero porta default para recebimento das requisies HTTP pode ser
alterada por meio da edio do arquivo server.xml do diretrio conf como
mostrado abaixo:
<Connector className="org.apache.tomcat.service.PoolTcpConnector">
<Parameter name="handler"
value="org.apache.tomcat.service.http.HttpConnectionHandler"/>
<Parameter name="port" value="Nmero da porta"/>
</Connector>
No entanto, caso o Tomcat esteja operando em conjunto com um
servidor, o ideal que o Tomcat no responda requisies diretamente.
Preparando para executar o Servlet
Compilando o Servlet
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
360
Antes de executar o Servlet e preciso compil-lo. Para compil-lo
preciso que as classes que implementam a API Servlet estejam no classpath.
Para isso preciso definir a varivel de ambiente. No ambiente MS-Windows
seria
set CLASSPATH=%CLASSPATH%;%TOMCAT_HOME%\lib\servlet.jar
e no ambiente Unix seria
CLASSPATH=${CLASSPATH}:${TOMCAT_HOME}/lib/servlet.jar
Alternativamente, possvel indicar o classpath na prpria linha de
execuo do compilador J ava. Por exemplo, No ambiente MS-Windows ficaria
na seguinte forma:
javac -classpath "%CLASSPATH%;c:\tomcat\lib\servlet.jar Ola.java
Criando uma aplicao no Tomcat
Agora preciso definir onde deve ser colocado o arquivo compilado.
Para isso preciso criar uma aplicao no Tomcat ou usar uma das aplicaes j
existentes. Vamos aprender como criar uma aplicao no Tomcat. Para isso
preciso cria a seguinte estrutura de diretrios abaixo do diretrio webapps do
Tomcat:
webapps
|_____ Nome aplicao
|_____ Web-inf
|_____classes
Diretrio de Aplicaes
Na verdade possvel definir outro diretrio para colocar as aplicaes do Tomcat. Para
indicar outro diretrio preciso editar o arquivo server.xml e indicar o diretrio por meio da
diretiva home do tag ContextManager.
O diretrio de uma aplicao denominado de contexto da aplicao.
preciso tambm editar o arquivo server.xml do diretrio conf, incluindo as
linhas:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
361
<Context path="/nome aplicao"
docBase="webapps/ nome aplicao" debug="0
reloadable="true" >
</Context>
Finalmente, preciso criar (ou copiar de outra aplicao) um arquivo
web.xml no diretrio Web-inf com o seguinte contedo:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
<web-app>
</web-app>
Copie ento o arquivo compilado Ola.class para o subdiretrio
/webapps/nome aplicao/Web-inf/classes do Tomcat.
Executando o Servlet
Invocando diretamente pelo Navegador
Podemos executar um Servlet diretamente digitando a URL do Servlet no
navegador. A URL em geral possui o seguinte formato:
http://mquina:porta/nome aplicao/servlet/nome servlet
A palavra servlet que aparece na URL no indica um subdiretrio no
servidor. Ela indica que esta uma requisio para um Servlet. Por exemplo,
suponha que o nome da aplicao criada no Tomcat seja teste. Ento a URL
para a invocao do Servlet do exemplo XX.XX teria a seguinte forma:
http://localhost:8080/teste/servlet/Ola
A URL para a chamada do Servlet pode ser alterada de modo a ocultar
qualquer referncia diretrios ou a tecnologias de implementao. No caso do
Tomcat essa configurao no arquivo web.xml do diretrio Web-inf da
aplicao. Por exemplo, para eliminar a palavra servlet da URL poderamos
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
362
inserir as seguintes linhas no arquivo web.xml entre os tags <web-app> e
</web-app>:
<servlet>
<servlet-name>
Ola
</servlet-name>
<servlet-class>
Ola
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>
Ola
</servlet-name>
<url-pattern>
/Ola
</url-pattern>
</servlet-mapping>
Invocando em uma pgina HTML
No caso de uma pgina HTML basta colocar a URL na forma de link.
Por exemplo,
<a href="http://localhost:8080/teste/servlet/Ola>Servlet Ola</a>
Neste caso o Servlet Ola ser solicitado quando o link associado ao texto
Servlet Ola for acionado.
Diferenas entre as requisies GET e POST
Os dois mtodos mais comuns, definidos pelo protocolo HTTP, de se
enviar uma requisies a um servidor Web so os mtodos POST e GET. Apesar
de aparentemente cumprirem a mesma funo, existem diferenas importantes
entre estes dois mtodos. O mtodo GET tem por objetivo enviar uma requisio
por um recurso. As informaes necessrias para a obteno do recurso (como
informaes digitadas em formulrios HTML) so adicionadas URL e, por
consequncia, no so permitidos caracteres invlidos na formao de URLs,
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
363
como por espaos em branco e caracteres especiais. J na requisio POST os
dados so enviados no corpo da mensagem.
O mtodo GET possui a vantagem de ser idempotente, ou seja, os
servidores Web podem assumir que a requisio pode ser repetida, sendo
possvel adicionar URL ao bookmark. Isto muito til quando o usurio deseja
manter a URL resultante de uma pesquisa. Como desvantagem as informaes
passadas via GET no podem ser muito longas, um vez o nmero de caracteres
permitidos por volta de 2K.
J as requisies POST a princpio podem ter tamanho ilimitado. No
entanto, elas no so idempotente, o que as tornam ideais para formulrios onde
os usurios precisam digitar informaes confidenciais, como nmero de carto
de crdito. Desta forma o usurio obrigado a digitar a informao toda vez que
for enviar a requisio, no sendo possvel registrar a requisio em um
bookmark.
Concorrncia
Uma vez carregado o Servlet no mais descarregado, a no ser que o
servidor Web tenha sua execuo interrompida. De modo geral, cada requisio
que deve ser direcionada a determinada instncia de Servlet tratada por um
thread sobre a instncia de Servlet. Isto significa que se existirem duas
requisies simultneas que devem ser direcionadas para um mesmo objeto o
container criar dois threads sobre o mesmo objeto Servlet para tratar as
requisies. A figura XX.XX ilustra esta situao.
Figura XV.XX. Relacionamento entre as instncias dos Servlets e os threads.
Servlet2
thread1
Servlet1
thread2
thread1
usurio
1
usurio
2
usurio
3
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
364
Em conseqncia disto temos o benefcios de uma sobrecarga para
servidor, uma vez que a criao de threads menos onerosa do que a criao de
processos, e uma aparente melhora no tempo de resposta.
Por outro lado, o fato dos Servlets operarem em modo multi-thread
aumenta a complexidade das aplicaes e cuidados especiais, como visto no
captulo sobre concorrncia, devem tomados para evitar comportamentos
errticos. Por exemplo, suponha um Servlet que receba um conjunto de nmeros
inteiros e retorne uma pgina contendo a soma dos nmeros. A exemplo XX.XX
mostra o cdigo do Servlet. O leitor pode imaginar um cdigo muito mais
eficiente para computar a soma de nmeros, mas o objetivo do cdigo do
exemplo ilustrar o problema da concorrncia em Servlets. O exemplo contm
tambm um trecho de cdigo para recebimento de valores de formulrios, o que
ser discutido mais adiante.
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Soma extends HttpServlet {
Vector v =new Vector(5);
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, java.io.IOException {
v.clear();
Enumeration e =req.getParameterNames();
while (e.hasMoreElements()) {
String name =(String)e.nextElement();
String value =req.getParameter(name);
if (value !=null) v.add(value);
}
res.setContentType("text/html");
java.io.PrintWriter out =res.getWriter();
out.println("<html>");
out.println("<head><title>Servlet</title></head>");
out.println("<body>");
out.println("<h1>A soma e'");
int soma =0;
for(int i =0; i<v.size() ; i++) {
soma +=Integer.parseInt((String)v.get(i));
}
out.println(soma);
out.println("<h1>");
out.println("</body>");
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
365
out.println("</html>");
out.close();
}
}
Exemplo XX.XX- Servlet com problemas de concorrncia.
Note que o Servlet utiliza uma varivel de instncia para referenciar o
Vector que armazena os valores. Se no forem usadas primitivas de
sincronizao (como no cdigo do exemplo) e duas requisies simultneas
chegarem ao Servlet o resultado pode ser inconsistente, uma vez que o Vector
poder conter parte dos valores de uma requisio e parte dos valores de outra
requisio. Neste caso, para corrigir esse problema basta declarar a varivel
como local ao mtodo doPost() ou usar primitivas de sincronizao.
Obtendo Informaes sobre a Requisio
O objeto HttpServletRequest passado para o Servlet contm
vrias informaes importantes relacionadas com a requisio, como por
exemplo o mtodo empregado (POST ou GET), o protocolo utilizado, o
endereo remoto, informaes contidas no cabealho e muitas outras. O Servlet
do exemplo XX.XX retorna uma pgina contendo informaes sobre a
requisio e sobre o cabealho da requisio.
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestInfo extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
res.setContentType("text/html");
PrintWriter out =res.getWriter();
out.println("<html><head>");
out.println("<title>Exemplo sobre Requisicao de Info </title>");
out.println("</head><body>");
out.println("<h3>Exemplo sobre Requisicao de Info </h3>");
out.println("Metodo: " +req.getMethod()+<br>);
out.println("Request URI: " +req.getRequestURI()+<br>);
out.println("Protocolo: " +req.getProtocol()+<br>);
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
366
out.println("PathInfo: " +req.getPathInfo()+<br>);
out.println("Endereco remoto: " +req.getRemoteAddr()+<br><br>);
Enumeration e =req.getHeaderNames();
while (e.hasMoreElements())
{
String name =(String)e.nextElement();
String value =req.getHeader(name);
out.println(name +" =" +value+"<br>");
}
out.println("</body></html>");
}
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
doGet(req, res);
}
}
Exemplo XX.XX- Servlet que retorna as informaes sobre a requisio.
Note que o mtodo doPost() chama o mtodo doGet(), de modo
que o Servlet pode receber os dois tipos de requisio. A figura XX.XX mostra o
resultado de uma execuo do Servlet do exemplo XX.XX.
Exemplo sobre Requisicao de Info
Metodo: GET
Request URI: /servlet/RequestInfo
Protocolo: HTTP/1.0
PathInfo: null
Endereco remoto: 127.0.0.1
Connection =Keep-Alive
User-Agent =Mozilla/4.7 [en] (Win95; I)
Pragma =no-cache
Host =localhost:8080
Accept =image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding =gzip
Accept-Language =en
Accept-Charset =iso-8859-1,*,utf-8
Figura XX.XX- Sada da execuo do Servlet que exibe as informaes sobre a
requisio.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
367
Lidando com Formulrios
Ser capaz de lidar com as informaes contidas em formulrios HTML
fundamental para qualquer tecnologia de desenvolvimento de aplicaes para
Web. por meio de formulrios que os usurios fornecem dados, preenchem
pedidos de compra e (ainda mais importante) digitam o nmero do carto de
crdito. As informaes digitadas no formulrio chegam at o Servlet por meio
do objeto HttpServletRequest e so recuperadas por meio do mtodo
getParameter() deste objeto. Todo item de formulrio HTML possui um
nome e esse nome passado como argumento para o mtodo
getParameter() que retorna na forma de String o valor do item de
formulrio.
O Servlet do exemplo XX.XX exibe o valor de dois itens de formulrios
do tipo text. Um denominado nome e o outro denominado de sobrenome.
Em seguida o Servlet cria um formulrio contendo os mesmos itens de
formulrio. Note que um formulrio criado por meio do tag <form>. Como
parmetros opcionais deste tag temos mtodo da requisio (method), a URL
para onde ser submetida a requisio (action). No caso do exemplo, o
mtodo adotado o POST e a requisio ser submetida ao prprio Servlet
Form.
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Form extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
res.setContentType("text/html");
PrintWriter out =res.getWriter();
out.println("<html>");
out.println("<head><title>Trata formulario</title></head>");
out.println("<body bgcolor=\"white\">");
out.println("<h3>Trata formulario</h3>");
String nome =req.getParameter("nome");
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
368
String sobreNome =req.getParameter("sobrenome");
if (nome !=null || sobreNome !=null)
{
out.println("Nome =" +nome +"<br>");
out.println("Sobrenome =" +sobreNome);
}
out.println("<P>");
out.print("<form action=\"Form\" method=POST>");
out.println("Nome : <input type=text size=20 name=nome><br>");
out.println("Sobrenome: <input type=text size=20 name=sobrenome><br>");
out.println("<input type=submit>");
out.println("</form>");
out.println("</body></html>");
}
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
doGet(req, res);
}
}
Exemplo XX.XX- Servlet para lidar com um formulrio simples.
Lidando com Cookies
Um cookie nada mais que um bloco de informao que enviado do
servidor para o navegador no cabealho pgina. A partir de ento, dependendo
do tempo de validade do cookie, o navegador reenvia essa informao para o
servidor a cada nova requisio. Dependo do caso o cookie tambm
armazenado no disco da mquina cliente e quando o site novamente visitado o
cookie enviado novamente para o servidor, fornecendo a informao desejada.
Os cookies foram a soluo adotada pelos desenvolvedores do Netscape
para implementar a identificao de clientes sobre um protocolo HTTP que no
orientado conexo. Esta soluo, apesar das controvrsias sobre a
possibilidade de quebra de privacidade, passou ser amplamente adotada e hoje
os cookies so parte integrante do padro Internet, normalizados pela norma
RFC 2109.
A necessidade da identificao do cliente de onde partiu a requisio e o
monitoramento de sua interao com o site (denominada de sesso) importante
para o desenvolvimento de sistemas para a Web pelas seguintes razes:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
369
necessrio associar os itens selecionados para compra com o
usurio que deseja adquiri-los. Na maioria da vezes a seleo dos
itens e compra feita por meio da navegao de vrias pginas do
site e a todo instante necessrio distinguir os usurios que esto
realizando as requisies.
necessrio acompanhar as interao do usurio com o site para
observar seu comportamento e, a partir dessas informaes, realizar
adaptaes no site para atrair um maior nmero de usurios ou
realizar campanhas de marketing.
necessrio saber que usurio est acessando o site para, de acordo
com o seu perfil, fornecer uma visualizao e um conjunto de
funcionalidades adequadas s suas preferncias.
Todas essas necessidades no podem ser atendidas com o uso bsico do
protocolo HTTP, uma vez que ele no orientado sesso ou conexo. Com os
cookies possvel contornar essa deficincia, uma vez que as informaes que
so neles armazenadas podem ser usadas para identificar os clientes. Existem
outras formas de contornar a deficincia do protocolo de HTTP, como a
codificao de URL e o uso de campos escondidos nas pginas HTML, mas o
uso de cookies a tcnica mais utiliza, por ser mais simples e padronizada. No
entanto, o usurio pode impedir que o navegador aceite cookies, o que torna o
ato de navegar pela Web muito desagradvel. Neste caso, necessrio utilizar as
outras tcnicas para controle de sesso.
A API Servlet permite a manipulao explicita de cookies. Para controle
de sesso o programador pode manipular diretamente os cookies, ou usar uma
abstrao de nvel mais alto, implementada por meio do objeto HttpSession.
Se o cliente no permitir o uso de cookies a API Servlet fornece mtodos para a
codificao de URL. O exemplo XX.XX mostra o uso de cookies para
armazenar as informaes digitadas em um formulrio.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CookieTeste extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse
res)
throws IOException, ServletException
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
370
res.setContentType("text/html");
PrintWriter out =res.getWriter();
out.println("<html>");
out.println("<body bgcolor=\"white\">");
out.println("<head><title>Teste de Cookies</title></head>");
out.println("<body>");
out.println("<h3>Teste de Cookies</h3>");
Cookie[] cookies =req.getCookies();
if (cookies.length >0)
{
for (int i =0; i <cookies.length; i++)
{
Cookie cookie =cookies[i];
out.print("Cookie Nome: " + cookie.getName() +
"<br>");
out.println(" Cookie Valor: " +cookie.getValue() +"<br><br>");
}
}
String cName =req.getParameter("cookienome");
String cValor =req.getParameter("cookievalor");
if (cName !=null && cValor !=null)
{
Cookie cookie =new Cookie(cName ,cValor);
res.addCookie(cookie);
out.println("<P>");
out.println("<br>");
out.print("Nome : "+cName +"<br>");
out.print("Valor : "+cValor);
}
out.println("<P>");
out.print("<form action=\"CookieTeste\" method=POST>");
out.println("Nome : <input type=text length=20 name=cookienome><br>");
out.println("Valor : <input type=text length=20 name=cookievalor><br>");
out.println("<input type=submit></form>");
out.println("</body>");
out.println("</html>");
}
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException
{
doGet(req, res);
}
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
371
Exemplo XX.XX- Servlet para lidar com Cookies.
Para se criar um cookie necessrio criar um objeto Cookie, passando
para o construtor um nome e um valor, sendo ambos instncias de String. O
cookie enviado para o navegador por meio do mtodo addCookie() do
objeto HttpServletResponse. Um vez que os cookies so enviados no
cabealho da pgina, o mtodo addCookie() deve ser chamado antes do
envio de qualquer contedo para o navegador. Para recuperar os cookies
enviados pelo navegador usa-se o mtodo getCookies() do objeto
HttpServletRequest que retorna um array de Cookie. Os mtodos
getName() e getvalue() do objeto Cookie so utilizados para recuperar
o nome o valor da informao associada ao cookie.
Os objetos da classe Cookie possuem vrios mtodos para controle do
uso de cookies. possvel definir tempo de vida mximo do cookie, os domnios
que devem receber o cookie (por default o domnio que deve receber o cookie
o que o criou), o diretrio da pgina que deve receber o cookie, se o cookie deve
ser enviado somente sob um protocolo seguro e etc. Por exemplo, para definir a
idade mxima de um cookie devemos utilizar o mtodo setMaxAge(),
passando um inteiro como parmetro. Se o inteiro for positivo indicar em
segundos o tempo mximo de vida do cookie. Um valor negativo indica que o
cookie deve apagado quando o navegador terminar. O valor zero indica que o
cookie deve ser apagado imediatamente. O trecho de cdigo exemplo XX.XX
mostra algumas alteraes no comportamento default de um cookie.
...
Cookie cookie =new Cookie(cName ,cValor);
cookie.setDomain(*.uvf.br); // todos os domnios como dpi.ufv.br mas no *.dpi.ufv.br
cookie.setMaxAge (3600); // uma hora de tempo de vida
...
Exemplo XX.XX- Mudanas no comportamento default do cookie.
Lidando com Sesses
A manipulao direta de cookies para controle de sesso um tanto baixo
nvel, uma vez que o usurio deve se preocupar com a identificao, tempo de
vida e outros detalhes. Por isso a API Servlet fornece um objeto com controles
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
372
de nvel mais alto para monitorar a sesso, o HttpSession. O objeto
HttpSession monitora a sesso utilizando cookies de forma transparente. No
entanto, se o cliente no aceitar o uso de cookies possvel utilizar como
alternativa a codificao de URL para adicionar o identificador da sesso. Essa
opo, apesar de ser mais genrica, no primeira opo devido a possibilidade
de criao de gargalos pela necessidade da anlise prvia de todas requisies
que chegam ao servidor. O exemplo XX.XX mostra o uso de um objeto
HttpSession para armazenar as informaes digitadas em um formulrio.
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SessionTeste extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException
{
resp.setContentType("text/html");
PrintWriter out =resp.getWriter();
out.println("<html><head>");
out.println("<title>Teste de Sessao</title>");
out.println("</head>");
out.println("<body>");
out.println("<h3>Teste de Sessao</h3>");
HttpSession session =req.getSession(true);
out.println("Identificador: " +session.getId());
out.println("<br>");
out.println("Data: ");
out.println(new Date(session.getCreationTime()) +"<br>");
out.println("Ultimo acesso: ");
out.println(new Date(session.getLastAccessedTime()));
String nomedado =req.getParameter("nomedado");
String valordado =req.getParameter("valordado");
if (nomedado !=null && valordado !=null)
{
session.setAttribute(nomedado, valordado);
}
out.println("<P>");
out.println("Dados da Sessao:" +"<br>");
Enumeration valueNames =session.getAttributeNames();
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
373
while (valueNames.hasMoreElements())
{
String name =(String)valueNames.nextElement();
String value =(String) session.getAttribute(name);
out.println(name +" =" +value+"<br>");
}
out.println("<P>");
out.print("<form action=\"SessionTeste\" method=POST>");
out.println("Nome: <input type=text size=20 name=nomedado><br>");
out.println("Valor: <input type=text size=20 name=valordado><br>");
out.println("<input type=submit>");
out.println("</form>");
out.println("</body></html>");
}
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException
{
doGet(req, resp);
}
}
Exemplo XX.XX- Servlet para lidar com Sesses.
Para controlar a sesso necessrio obter um objeto HttpSession por
meio do mtodo getSession() do objeto HttpServletRequest. Opcionalmente, o
mtodo getSession() recebe como argumento um valor booleano que indica se
para criar o objeto HttpSession se ele no existir (argumento true) ou se para
retorna null caso ele no exista (argumento false). Para se associar um objeto ou
informao sesso usa-se o mtodo setAttribute() do objeto HttpSession,
passando para o mtodo um String e um objeto que ser identificado pelo String.
Note que o mtodo aceita qualquer objeto e, portanto, qualquer objeto pode ser
associado sesso. Os objetos associados a uma sesso so recuperados com o
uso mtodo getAttribute() do objeto HttpSession, que recebe como argumento o
nome associado ao objeto. Para se obter uma enumerao do nomes associados
sesso usa-se o mtodo getAttributeNames() do objeto HttpSession.
A figura XX.XX mostra o resultado da execuo do exemplo XX.XX.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
374
Teste de Sessao
Identificador: session3
Data: Sun May 28 15:19:15 GMT-03:00 2000
Ultimo acesso: Sun May 28 15:19:43 GMT-03:00 2000
Dados da Sessao:
Alcione =4
Alexandra =6
Nome
Valor
Figura XVI-1 Sada resultante da execuo do Servlet que lida com Sesses.
Enviar Consulta
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
375
JSP
Servlets uma boa idia, mas voc se imaginou montando uma pgina
complexa usando println()? Muitas vezes o desenvolvimento de um site
uma tarefa complexa que envolve vrios profissionais. A tarefa de projeto do
layout da pgina fica a cargo do Web Designer, incluindo a diagramao dos
textos e imagens, aplicao de cores, tratamento das imagens, definio da
estrutura da informao apresentada no site e dos links para navegao pela
mesma. J o Desenvolvedor Web responsvel pela criao das aplicaes que
vo executar em um site. O trabalho destes dois profissionais somado na
criao de um nico produto, mas durante o desenvolvimento a interferncia
mutua deve ser a mnima possvel. Ou seja, um profissional no deve precisar
alterar o que foi feito pelo outro profissional para cumprir sua tarefa. A
tecnologia Servlet no nos permite atingir esse ideal. Por exemplo, suponha que
um Web Designer terminou o desenvolvimento de uma pgina e a entregou para
o Desenvolvedor Web codificar em um Servlet. Se aps a codificao o Web
Designer desejar realizar uma alterao na pgina ser necessrio que ele altere o
cdigo do Servlet (do qual ele nada entende) ou entregar uma nova pgina para o
Desenvolvedor Web para que ele a codifique totalmente mais uma vez. Qualquer
uma dessas alternativas so indesejveis e foi devido a esse problema a Sun
desenvolveu uma tecnologia baseada em Servlets chamada de J SP.
J ava Server Pages (J SP) so pginas HTML que incluem cdigo J ava e
outros tags especiais. Desta forma as partes estticas da pgina no precisam ser
geradas por println(). Elas so fixadas na prpria pgina. A parte dinmica
gerada pelo cdigo J SP. Assim a parte esttica da pgina pode ser projetada
por um Web Designer que nada sabe de J ava.
A primeira vez que uma pgina J SP carregada pelo container J SP o
cdigo J ava compilado gerando um Servlet que executado, gerando uma
pgina HTML que enviada para o navegador. As chamadas subsequentes so
enviadas diretamente ao Servlet gerado na primeira requisio, no ocorrendo
mais as etapas de gerao e compilao do Servlet.
A figura XX.XX mostra um esquema das etapas de execuo de uma
pgina J SP na primeira vez que requisitada. Na etapa (1) a requisio enviada
para um servidor Web que reencaminha a requisio (etapa 2) para o container
Servlet/J SP. Na etapa (3) o container verifica que no existe nenhuma instncia
de Servlet correspondente pgina J SP. Neste caso, a pgina J SP traduzida
para cdigo fonte de uma classe Servlet que ser usada na resposta requisio.
Na etapa (4) o cdigo fonte do Servlet compilado, e na etapa (5) criada uma
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
376
instncia da classe. Finalmente, na etapa (6) invocado o mtodo service()
da instncia Servlet para gerar a resposta requisio.
Figura XVI-1 Etapas da primeira execuo de uma pgina J SP.
A idia de se usar scripts de linguagens de programao em pginas
HTML que so processados no lado servidor para gerar contedo dinmico no
restrita linguagem J ava. Existem vrias solues desse tipo fornecida por
outros fabricantes. Abaixo segue uma comparao de duas das tecnologias mais
populares com J SP.
PHP X JSP
PHP (Personal Home Pages) uma linguagem script para ser executada
no lado servidor criada em 1994 como um projeto pessoal de Rasmus Lerdorf.
Atualmente encontra-se na verso 4. A sintaxe fortemente baseada em C mas
possui elementos de C++, J ava e Perl. Possui suporte programao OO por
meio de classes e objetos. Possui tambm suporte extensivo Banco de dados
ODBC, MySql, Sybase, Oracle e outros. PHP uma linguagem mais fcil no
desenvolvimento de pequenas aplicaes para Web em relao J SP, uma vez
Servidor
Http
(1)
Requisio de
pgina J SP
Container
Servlet/J SP
Pgina
jsp
Fonte
Servlet
(3)
Traduz
(2)
Encaminha a requisio
(5)
Instancia e
executa
(6)
Resposta
requisio
Navegador
Bytecode
Servlet
(4)
Compila
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
377
que uma linguagem mais simples e menos rgida do que J SP. No entanto, a
medida que passamos para aplicaes de maior porte, o uso de PHP no
indicado, uma vez que necessrio o uso de linguagens com checagem mais
rgidas e com maior suporte escalabilidade, como o caso de J ava.
ASP X JSP
ASP (Active Server Pages) a soluo desenvolvida pela Microsoft
para atender as requisies feitas servidores Web. Incorporada inicialmente
apenas ao Internet Information Server (IIS), no entanto, atualmente j
suportada por outros servidores populares, como o Apache. O desenvolvimento
de pginas que usam ASP envolve a produo de um script contendo HTML
misturado com blocos de cdigo de controle ASP. Este cdigo de controle pode
conter scripts em J avaScript ou VBScript. A primeira vantagem de J SP sobre
ASP que a parte dinmica escrita em J ava e no Visual Basic ou outra
linguagem proprietria da Microsoft, portanto J SP mais poderoso e fcil de
usar. Em segundo lugar J SP mais portvel para outros sistemas operacionais e
servidores WEB que no sejam Microsoft.
Primeiro exemplo em JSP
Para que o leitor possa ter uma idia geral da tecnologia J SP
apresentaremos agora a verso J SP do Ol mundo. O exemplo XX.XX mostra o
cdigo da pgina.
<html>
<head>
<title>Exemplo J SP</title>
</head>
<body>
<%
String x = " Ol&aacute; Mundo!" ;
%>
<%=x%>
</body>
</html>
Exemplo XX.XX- Verso J SP do Ol mundo.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
378
Quem est habituado aos tags HTML notar que se trata basicamente de
uma pgina HTML contendo cdigo J ava delimitado pelos smbolos <% e
%>. Para facilitar a visualizao destacamos os scripts J ava com negrito. No
primeiro trecho de script declarada uma varivel x com o valor Ol mundo
(a seqncia &acute; denota em HTML). No segundo trecho de script o
contedo da varivel x extrado e colocado na pgina resultante da execuo
do Servlet correspondente. Em seguida mostraremos como executar o exemplo
XX.XX.
Executando o arquivo JSP
Para executar o exemplo XX.XX salve-o com a extenso .jsp. Por
exemplo ola.jsp. Se voc estiver usando o servidor Tomcat, coloque-o
arquivo no subdiretrio /webapps/examples/jsp do Tomcat. Por exemplo
examples/jsp/teste. Para invocar o arquivo J SP basta embutir a URL em
uma pgina ou digitar diretamente a seguinte URL no navegador.
http://localhost:8080/examples/jsp/ola.jsp
Usamos o diretrio /webapps/examples/jsp para testar rapidamente
o exemplo. Para desenvolver uma aplicao aconselhvel criar um diretrio
apropriado como mostrado na seo que tratou de Servlets.
O Servlet criado a partir da pgina J SP colocado em um diretrio de
trabalho. No caso do Tomcat o Servlet colocado em subdiretrio associado
aplicao subordinado ao diretrio /work do Tomcat. O exemplo XX.XX
mostra os principais trechos do Servlet criado a partir da traduo do arquivo
ola.jsp pelo tradutor do Tomcat. Note que o Servlet subclasse de uma
classe HttpJspBase e no da HttpServlet. Alm disso, o mtodo que
executado em resposta requisio o mtodo _jspService() e no o
mtodo service(). Note tambm que todas as partes estticas da pgina J SP
so colocadas como argumentos do mtodo write() do objeto referenciado
out.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
379
public class _0002fjsp_0002fola_00032_0002ejspola_jsp_0 extends HttpJ spBase {
....
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
....
PageContext pageContext =null;
HttpSession session =null;
ServletContext application =null;
ServletConfig config =null;
J spWriter out =null;
...
try {
...
out.write("<html>\r\n <head>\r\n <title>Exemplo J SP</title>\r\n
</head>\r\n <body>\r\n");
String x ="Ol&aacute; Mundo!";
out.write("\r\n");
out.print(x);
out.write("\r\n </body>\r\n</html>\r\n");
...
}catch (Exception ex) {
...
}
}
}
Exemplo XX.XX- Servlet correspondente pgina J SP do Ol mundo.
Objetos implcitos
No exemplo XX.XX pode-se ver a declarao de variveis que
referenciam a alguns objetos importantes. Estas variveis esto disponveis para
o projetista da pgina J SP. As variveis mais importantes so:
Classe Varivel
HttpServletRequest
HttpServletResponse
PageContext
ServletContext
HttpSession
J spWriter
request
response
pageContext
application
session
out
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
380
Os objetos referenciados pelas variveis request e response j
tiveram seu uso esclarecido na seo sobre Servlets. O objeto do tipo
JspWriter tem a mesma funo do PrinterWriter do Servlet. Os outros
objetos tero sua funo esclarecida mais adiante.
Tags JSP
Os tags J SP possuem a seguinte forma geral:
<% Cdigo JSP %>
O primeiro caractere % pode ser seguido de outros caracteres que
determinam o significado preciso do cdigo dentro do tag. Os tags J SP possuem
correspondncia com os tags XML. Existem cinco categorias de tags J SP:
Expresses
Scriptlets
Declaraes
Diretivas
Comentrios
Em seguida comentaremos cada uma dessas categorias.
Expresses
<%= expresses %>
Expresses so avaliadas, convertidas para String e colocadas na
pgina enviada. A avaliao realizada em tempo de execuo, quando a pgina
requisitada.
Exemplos:
<%= new java.util.Date() %>
<%= request.getMethod() %>
No primeiro exemplo ser colocado na pgina a data corrente em
milsimo de segundos e no segundo ser colocado o mtodo usado na
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
381
requisio. Note que cada expresso contm apenas um comando J ava. Note
tambm que o comando J ava no terminado pelo caractere ;.
Scriptlets
<% cdigo Java %>
Quando necessrio mais de um comando J ava ou o resultado da
computao no para ser colocado na pgina de resposta preciso usar outra
categoria de tags J SP: os Scriptlets . Os Scriptlets permitem inserir trechos de
cdigo em J ava na pgina J SP. O exemplo XX.XX mostra uma pgina J SP
contendo um Scriptlet que transforma a temperatura digitada em celcius para o
equivalente em Fahrenheit.
<html>
<head><title>Conversao Celcius Fahrenheit </title></head>
<body>
<%
String valor = request.getParameter(" celcius" );
if (valor != null )
{
double f = Double.parseDouble(valor)*9/5 +32;
out.println(" <P>" );
out.println(" <h2>Valor em Fahrenheit:" +f +" <h2><br>" );
}
%>
<form action=conversao.jsp method=POST>
Celcius: <input type=text size=20 name=celcius><br>
<input type=submit>
</form>
</body>
</html>
Exemplo XX.XX- Pgina J SP que converte graus Celcius para Fahrenheit.
Note o uso das variveis request e out sem a necessidade de
declarao. Todo o cdigo digitado inserido no mtodo _jspService(). A
figura XX.XX mostra o resultado da requisio aps a digitao do valor 30 na
caixa de texto do formulrio.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
382
Figura XVI-XX Resultado da converso de 30 graus celcius.
O cdigo dentro do scriptlet inserido da mesma forma que escrito e
todo o texto HTML esttico antes e aps ou um scriptlet convertido para
comandos print(). Desta forma o scriptlets no precisa conter comandos para
cdigo esttico e blocos de controle abertos afetam o cdigo HTML envolvidos
por scriptlets. O exemplo XX.XX mostra dois formas de se produzir o mesmo
efeito. No cdigo da esquerda os Scriplets se intercalam com cdigo HTML. O
cdigo HTML, quando da traduo da pgina J SP para Servlet inserido como
argumentos de mtodos println() gerando o cdigo da direita. Ambas as
formas podem ser usadas em pginas J SP e produzem o mesmo efeito.
Previs&atilde;o do Tempo
<% if (Math.random() < 0.5) { %>
Hoje vai <B>fazer sol</B>!
<% } else { %>
Hoje vai <B>chover</B>!
<% } %>
out.println("Previs&atilde;o do Tempo");
if (Math.random() <0.5) {
out.println(" Hoje vai <B>fazer sol</B>!");
}else {
out.println(" Hoje vai <B>chover</B>!");
}
Exemplo XX.XX- Dois cdigos equivalentes.
Declaraes
<%! Cdigo Java %>
Valor em Fahrenheit:86.0
Celcius:
Enviar Consulta
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
383
Uma declarao J SP permite definir variveis ou mtodos que so
inseridos no corpo do Servlet. Como as declaraes no geram sada, elas so
normalmente usadas em combinao com expresses e scriptlets. O Exemplo
XX.XX mostra a declarao de uma varivel que usada para contar o nmero
de vezes que a pgina corrente foi requisitada desde que foi carregada.
<%! Private int numAcesso = 0; %>
Acessos desde carregada:
<%= ++ numAcesso %>
Exemplo XX.XX- Declarao de uma varivel usando o tag de declarao.
As variveis declaradas desta forma sero variveis de instncia. J as
variveis declaradas em Scriptlets so variveis locais ao mtodo
_jspService(). Por isso possvel contar o nmero de requisies com o
exemplo XX.XX. Se varivel fosse declarada em um Scriptlet a varivel seria
local ao mtodo _jspService() e, portanto, teria seu valor reinicializado a
cada chamada.
Como j foi dito, os tags de declaraes permitem a declarao de
mtodos. O Exemplo XX.XX mostra a declarao de um mtodo que converte
celcius para Fahrenheit.
<%!
private double converte(double c)
{
return c*9/5 +32;
}
%>
Exemplo XX.XX- Declarao de um mtodo para a converso de celcius para
Fahrenheit.
Comentrios
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
384
Existem dois tipos de comentrios utilizados em pginas J SP. O primeiro
exclui todo o bloco comentado da sada gerada pelo processamento da pgina. A
forma geral deste tipo de comentrio a seguinte:
<%--comentrio --%>
O segundo tipo de comentrio o utilizado em pginas HTML. Neste
caso o comentrio enviado dentro da pgina de resposta. A forma geral deste
tipo de comentrio a seguinte:
<!comentrio -->
Diretivas
Diretivas so mensagens para J SP container. Elas no enviam nada para a
pgina mas so importantes para definir atributos J SP e dependncias com o J SP
container. A forma geral da diretivas a seguinte:
<%@ Diretiva atributo="valor" %>
ou
<%@ Diretiva atributo
1
="valor
1
"
atributo
2
="valor
2
"
...
atributo
N
=" valor
N
" %>
Em seguida comentaremos as principais diretivas.
Diretiva page
<%@ page atributo
1
="valor
1
" ... atributo
N
=" valor
N
" %>
A diretiva page permite a definio dos seguintes atributos:
import
contentType
isThreadSafe
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
385
session
buffer
autoflush
info
errorPage
isErrorPage
language
Segue a descrio de cada um desses atributos.
Atributo e Forma Geral Descrio
import="package.class"
ou
import="package.class
1
,..
.,package.class
N
"
Permite especificar os pacotes que devem ser
importados para serem usados na pgina J SP.
Exemplo:
<%@ page import="java.util.*" %>
contentType="MIME-Type" Especifica o tipo MIME da sada. O default text/html.
Exemplo:
<%@ page contentType="text/plain" %>
possui o mesmo efeito do scriptlet
<%
response.setContentType("text/plain")
;
%>
isThreadSafe="true|false"
Um valor true (default) indica um processamento
normal do Servlet, onde mltiplas requisies so
processadas simultaneamente. Um valor false indica que
o processamento deve ser feito por instancias separadas
do Servlet ou serialmente.
session="true|false
Um valor true (default) indica que a varivel
predefinida session (HttpSession) deve ser
associada sesso, se existir, caso contrrio uma nova
sesso deve ser criada e associada a ela. Um valor false
indica que nenhuma sesso ser usada.
buffer="sizekb|none" Especifica o tamanho do buffer para escrita usado pelo
objeto J spWriter. O tamanho default no menor que
8k..
autoflush="true|false
Um valor true (default) indica que o buffer deve ser
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
386
esvaziado quando estiver cheio.
info="mensagem" Define uma cadeia de caracteres que pode ser
recuperada via getServletInfo().
errorPage="url Especifica a pgina J SP que deve ser processada em
caso de excees no capturadas.
isErrorPage="true|false Indica se a pgina corrente pode atuar como pgina de
erro para outra pgina J SP. O default false.
Language="java Possibilita definir a linguagem que est sendo usada. No
momento a nica possibilidade J ava.
Tabela XVI.XX Atributos da diretiva page.
Diretiva include
<%@ include file="relative url" %>
Permite incluir arquivos no momento em que a pgina J SP traduzida
em um Servlet.
Exemplo:
<%@ include file="/meuarq.html" %>
Extraindo Valores de Formulrios
Uma pgina J SP, da mesma forma que um Servlet, pode usar o objeto
referenciado pela varivel request para obter os valores dos parmetros de um
formulrio. O exemplo XX.XX usado para converter graus Celcius em
Fahrenheit fez uso deste recurso. O exemplo XX.XX mostra outra pgina J SP
com formulrio. Note que o scriptlet usado para obter o nome e os valores de
todos os parmetros contidos no formulrio. Como o mtodo
getParameterNames() retorna uma referncia a um objeto
Enumeration preciso importar o pacote java.util, por meio da diretiva
page.
<%@ page import="java.util.*" %>
<html><body>
<H1>Formulrio</H1>
<%
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
387
Enumeration campos = request.getParameterNames();
While(campos.hasMoreElements()) {
String campo = (String)campos.nextElement();
String valor = request.getParameter(campo); %>
<li><%= campo %> = <%= valor %></li>
<% } %>
<form method="POST" action="form.jsp">
Nome: <input type="text" size="20" name="nome" ><br>
Telefone: <input type="text" size="20" name="telefone"><br>
<INPUT TYPE=submit name=submit value="envie">
</form>
</body></html>
Exemplo XVI.XX Pgina JSP com formulrio.
A figura XX.XX mostra o resultado da requisio aps a digitao dos
valores Alcione e 333-3333 nas caixas de texto do formulrio.
Figura XVI.XX- Sada do exemplo XX.XX.
Criando e Modificando Cookies
Formulrio
telefone =333-3333
nome =Alcione
submit =envie
Nome:
Telefone:
envie
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
388
Da mesma for que em Servlets os cookies em J SP so tratados por meio
da classe Cookie. Para recuperar os cookies enviados pelo navegador usa-se o
mtodo getCookies() do objeto HttpServletRequest que retorna um
arranjo de Cookie. Os mtodos getName() e getvalue() do objeto
Cookie so utilizados para recuperar o nome o valor da informao associada
ao cookie. O cookie enviado para o navegador por meio do mtodo
addCookie() do objeto HttpServletResponse. O exemplo XX.XX
mostra uma pgina J SP que exibe todos os cookies recebidos em uma requisio
e adiciona mais um na resposta.
<html><body>
<H1>Session id: <%= session.getId() %></H1>
<%
Cookie[] cookies = request.getCookies();
For(int i = 0; i < cookies.length; i++) { %>
Cookie name: <%= cookies[i].getName() %> <br>
Value: <%= cookies[i].getValue() %><br>
antiga idade mxima em segundos:
<%= cookies[i].getMaxAge() %><br>
<% cookies[i].setMaxAge(5); %>
nova idade mxima em segundos:
<%= cookies[i].getMaxAge() %><br>
<% } %>
<%! Int count = 0; int dcount = 0; %>
<% response.addCookie(new Cookie(
Cookie " + count++, Valor " + dcount++)); %>
</body></html>
Exemplo XVI.XX Pgina JSP que exibe os cookies recebidos.
A figura XX.XX mostra o resultado aps trs acessos seguidos pgina
J SP. Note que existe um cookie a mais com o nome JSESSIONID e valor igual
sesso. Este cookie o usado pelo container para controlar a sesso.
Session id: 9ppfv0lsl1
Cookie name: Cookie 0
value: Valor 0
antiga idade mxima em segundos: -1
nova idade mxima em segundos: 5
Cookie name: Cookie 1
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
389
value: Valor 1
antiga idade mxima em segundos: -1
nova idade mxima em segundos: 5
Cookie name: J SESSIONID
value: 9ppfv0lsl1
antiga idade mxima em segundos: -1
nova idade mxima em segundos: 5
Figura XVI.XX- Sada do exemplo XX.XX aps trs acessos.
Lidando com sesses
O atributos de uma sesso so mantidos em um objeto HttpSession
referenciado pela varivel session. Pode-se armazenar valores em uma sesso
por meio do mtodo setAttribute() e recuper-los por meio do mtodo
getAttribute(). O tempo de durao default de uma sesso inativa (sem o
recebimento de requisies do usurio) 30 minutos mas esse valor pode ser
alterado por meio do mtodo setMaxInactiveInterval(). O exemplo
XX.XX mostra duas pginas J SP. A primeira apresenta um formulrio onde
podem ser digitados dois valores recebe dois valores de digitados em um
formulrio e define o intervalo mximo de inatividade de uma sesso em 10
segundos. A segunda pgina recebe a submisso do formulrio, insere os valores
na sesso e apresenta os valores relacionados com a sesso assim como a
identificao da sesso.
<%@ page import="java.util.*" %>
<html><body>
<H1>Formulrio</H1>
<H1>Id da sess&atilde;o: <%= session.getId() %></H1>
<H3><li>Essa sess&atilde;o foi criada em
<%= session.getCreationTime() %></li></H3>
<H3><li>Antigo intervalo de inatividade =
<%= session.getMaxInactiveInterval() %></li>
<% session.setMaxInactiveInterval(10); %>
<li>Novo intervalo de inatividade=
<%= session.getMaxInactiveInterval() %></li>
</H3>
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
390
<%
Enumeration atribs = session.getAttributeNames();
while(atribs.hasMoreElements()) {
String atrib = (String)atribs.nextElement();
String valor = (String)session.getAttribute(atrib); %>
<li><%= atrib %> = <%= valor %></li>
<% } %>
<form method="POST" action="sessao2.jsp">
Nome: <input type="text" size="20" name="nome" ><br>
Telefone: <input type="text" size="20" name="telefone" >
<br>
<INPUT TYPE=submit name=submit value="envie">
</form>
</body></html>
<html><body>
<H1>Id da sess&atilde;o: <%= session.getId() %></H1>
<%
String nome = request.getParameter("nome");
String telefone = request.getParameter("telefone");
if (nome !=null && nome.length()>0)
session.setAttribute("nome",nome);
if (telefone !=null &&telefone.length()>0)
session.setAttribute("telefone",telefone);
%>
<FORM TYPE=POST ACTION=sessao1.jsp>
<INPUT TYPE=submit name=submit Value="Retorna">
</FORM>
</body></html>
Exemplo XVI.XX Exemplo do uso de sesso.
O exemplo XX.XX mostra que a sesso mantida mesmo quando
o usurio muda de pgina. As figura XX.XX e XX.XX mostram o resultado da
requisio aps a digitao dos valores Alcione e 333-3333 nas caixas de
texto do formulrio, submisso para pgina sessao2.jsp e o retorno
pgina sessao1.jsp.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
391
Figura XVI.XX- Tela da pgina sessao1.jsp.
Figura XVI.XX- Tela da pgina sessao2.jsp.
O Uso de JavaBeans
Formulrio
Id da sesso: soo8utc4m1
Essa sesso foi criada em 1002202317590
Antigo intervalo de inatividade = 1800
Novo intervalo de inatividade= 10
telefone =333-3333
nome =Alcione
Nome:
Telefone:
envie
Id da sesso: soo8utc4m1
Retorna
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
392
A medida que o cdigo J ava dentro do HTML torna-se cada vez mais
complexo o desenvolvedor pode-se perguntar: J ava em HTML no o problema
invertido do HTML em Servlet? O resultado no ser to complexo quanto
produzir uma pgina usando println()? Em outras palavras, estou
novamente misturando contedo com forma?
Para solucionar esse problema a especificao de J SP permite o uso de
J avaBeans para manipular a parte dinmica em J ava. J avaBeans j foram
descritos detalhadamente em um captulo anterior, mas podemos encarar um
J avaBean como sendo apenas uma classe J ava que obedece a uma certa
padronizao de nomeao de mtodos, formando o que denominado de
propriedade. As propriedades de um bean so acessadas por meio de mtodos
que obedecem a conveno getXxxx e setXxxx. , onde Xxxx o nome da
propriedade. Por exemplo, getItem() o mtodo usado para retornar o valor
da propriedade item. A sintaxe para o uso de um bean em uma pgina J SP :
<jsp:useBean id="nome" class="package.class" />
Onde nome o identificador da varivel que conter uma referncia para
uma instncia do J avaBean. Voc tambm pode modificar o atributo scope
para estabelecer o escopo do bean alm da pgina corrente.
<jsp:useBean id="nome" scope="session" class="package.class" />
Para modificar as propriedades de um J avaBean voc pode usar o
jsp:setProperty ou chamar um mtodo explicitamente em um
scriptlet. Para recuperar o valor de uma propriedade de um J avaBean voc
pode usar o jsp:getProperty ou chamar um mtodo explicitamente em
um scriptlet. Quando dito que um bean tem uma propriedade prop do
tipo T significa que o bean deve prover um mtodo getProp() e um mtodo
do tipo setProp(T). O exemplo XX.XX mostra uma pgina J SP e um
J avaBean. A pgina instancia o J avaBean, altera a propriedade mensagem e
recupera o valor da propriedade, colocando-o na pgina.
Pgina bean.jsp
<HTML><HEAD>
<TITLE>Uso de beans</TITLE>
</HEAD><BODY><CENTER>
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
393
<TABLE BORDER=5><TR><TH CLASS="TITLE">Uso de J avaBeans </TABLE>
</CENTER><P>
<jsp:useBean id=" teste" cl ass= curso.BeanSimples" />
<jsp:setProperty name=" teste" property=" mensagem" value= Ola mundo!" />
<H1>Mensagem: <I>
<jsp:getProperty name=" teste" property=" mensagem" /> </I></H1>
</BODY></HTML>
Arquivo Curso/BeanSimples.java
package curso;
public class BeanSimples {
private String men = "Nenhuma mensagem";
public String getMensagem() {
return(men);
}
public void setMensagem(String men) {
this.men = men;
}
}
Exemplo XVI.XX Exemplo do uso de JavaBean.
A figura XX.XX mostra o resultado da requisio dirigida pgina
bean.jsp.
Figura XVI.XX- Resultado da requisio pgina bean.jsp.
Se no tag setProperty usarmos o valor * para o atributo
property ento todos os valores de elementos de formulrios que possurem
nomes iguais propriedades sero transferidos para as respectivas propriedades
Mensagem: Ola mundo!
Uso de JavaBeans
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
394
no momento do processamento da requisio. Por exemplo, seja uma pgina jsp
contendo um formulrio com uma caixa de texto com nome mensagem, como
mostrado no exemplo XX.XX. Note que, neste caso, a propriedade mensagem
do J avaBean tem seu valor atualizado para o valor digitado na caixa de texto,
sem a necessidade de uma chamada explcita no tag setProperty. Os
valores so automaticamente convertidos para o tipo correto no bean.
<HTML><HEAD><TITLE>Uso de beans</TITLE></HEAD>
<BODY><CENTER>
<TABLE BORDER=5><TR><TH CLASS="TITLE">Uso de J avaBeans </TABLE>
</CENTER><P>
<jsp:useBean id=" teste" cl ass=" curso.BeanSimpl es" />
<jsp:setProperty name=" teste" property=" *" />
<H1>Mensagem: <I>
<jsp:getProperty name=" teste" property=" mensagem" />
</I></H1>
<form method="POST" action="bean2.jsp">
Texto: <input type="text" size="20" name="mensagem" ><br>
<INPUT TYPE=submit name=submit value="envie">
</form>
</BODY></HTML>
Exemplo XVI.XX Exemplo de atualizao automtica da propriedade.
A figura XX.XX mostra o resultado da requisio dirigida pgina
bean2.jsp aps a digitao do texto Ol!
Figura XVI.XX- Resultado da requisio pgina bean2.jsp.
Mensagem: Ola!
Uso de JavaBeans
envie
Texto:
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
395
Escopo
Existem quatro valores possveis para o escopo de um objeto: page,
request, session e application. O default page. A tabela
XX.XX descreve cada tipo de escopo.
Escopo Descrio
page Objetos declarados com nesse escopo so vlidos at a
resposta ser enviada ou a requisio ser encaminhada
para outro programa no mesmo ambiente, ou seja, s
podem ser referenciados nas pginas onde forem
declarados. Objetos declarados com escopo page so
referenciados pelo objeto pagecontext.
request Objetos declarados com nesse escopo so vlidos durante
a requisio e so acessveis mesmo quando a requisio
encaminhada para outro programa no mesmo ambiente.
Objetos declarados com escopo request so
referenciados pelo objeto request.
session Objetos declarados com nesse escopo so vlidos durante
a sesso desde que a pgina seja definida para funcionar
em uma sesso. Objetos declarados com escopo
session so referenciados pelo objeto session.
application Objetos declarados com nesse escopo so acessveis por
pginas no mesmo servidor de aplicao. Objetos
declarados com escopo application so
referenciados pelo objeto application.
Tabela XVI.XX Escopo dos objetos nas pginas JSP.
Implementao de um Carrinho de compras
O exemplo abaixo ilustra o uso de J SP para implementar um carrinho de
compras virtual. O carrinho de compras virtual simula um carrinho de compras
de supermercado, onde o cliente vai colocando os produtos selecionados para
compra at se dirigir para o caixa para fazer o pagamento. No carrinho de
compras virtual os itens selecionados pelo usurio so armazenados em uma
estrutura de dados at que o usurio efetue o pagamento. Esse tipo de exemplo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
396
exige que a pgina J SP funcione com o escopo session para manter o
carrinho de compras durante a sesso. O exemplo XX.XX mostra um exemplo
simples de implementao de carrinho de compras. O exemplo composto por
dois arquivos: um para a pgina J SP e um para o JavaBean que armazena os
itens selecionados.
Pgina compras.jsp
<html>
<jsp:useBean id=" carrinho" scope=" session" cl ass=" compra.Carrinho" />
<jsp:setProperty name=" carrinho" property=" *" />
<body bgcolor="#FFFFFF">
<%
carrinho.processRequest(request);
String[] items = carrinho.getItems();
if (items.length>0) {
%>
<font size=+2 color="#3333FF">Voc&ecirc; comprou os seguintes itens:</font>
<ol>
<%
for (int i=0; i<items.length; i++) {
out.println(" <li >" +items[i]);
}
}
%>
</ol>
<hr>
<form type=POST action=compras.jsp>
<br><font color="#3333FF" size=+2>Entre um item para adicionar ou remover:
</font><br>
<select NAME="item">
<option>Televis&atilde;o
<option>R&aacute;dio
<option>Computador
<option>V&iacute;deo Cassete
</select>
<p><input TYPE=submit name="submit" value="adicione">
<input TYPE=submit name="submit" value="remova"></form>
</body>
</html>
J avaBean compra/Carrinho.java
package compra;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
397
import javax.servlet.http.*;
import java.util.Vector;
import java.util.Enumeration;
public class Carrinho {
Vector v =new Vector();
String submit =null;
String item =null;
private void addItem(String name) {v.addElement(name); }
private void removeItem(String name) {v.removeElement(name); }
public void setItem(String name) {item =name; }
public void setSubmit(String s) {submit =s; }
public String[] getItems() {
String[] s =new String[v.size()];
v.copyInto(s);
return s;
}
private void reset() {
submit =null;
item =null;
}
public void processRequest(HttpServletRequest request)
{
if (submit ==null) return;
if (submit.equals("adicione")) addItem(item);
el se if (submit.equals("remova")) removeItem(item);
reset();
}
}
Exemplo XVI.XX Implementao de um carrinho de compras Virtual.
O exemplo XX.XX implementa apenas o carrinho de compras, deixando
de fora o pagamento dos itens, uma vez que esta etapa depende de cada sistema.
Geralmente o que feito direcionar o usurio para outra pgina onde ele
digitar o nmero do carto de crdito que ser transmitido por meio de uma
conexo segura para o servidor. Existem outras formas de pagamento, como
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
398
boleto bancrio e dinheiro virtual. O prprio carrinho de compras geralmente
mais complexo, uma vez que os para compra devem ser obtidos dinamicamente
de um banco de dados. A figura XX.XX mostra a tela resultante de algumas
interaes com o carrinho de compras.
Figura XVI.XX- Carrinho de compras virtual.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
399
Reencaminhando ou Redirecionando requisies
Existem algumas situaes onde pode ser desejvel transferir uma
requisio para outra URL. Isto feito com frequncia em sistemas que
combinam o uso de Servlets juntamente com J SP. No entanto, a transferncia
pode ser para qualquer recurso. Assim, podemos transferir uma requisio de um
Servlet para uma pgina J SP, HTML ou um Servlet. Da mesma forma uma
pgina J SP pode transferir uma requisio para uma pgina J SP, HTML ou um
Servlet.
Existem dois tipos de transferncia de requisio: o redirecionamento e o
reencaminhamento. O redirecionamento obtido usando o mtodo
sendRedirect() de uma instncia HttpServletResponse, passando
como argumento a URL de destino. O exemplo XX.XX mostra o cdigo de um
Servlet redirecionando para uma pgina HTML.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class Redireciona extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
res.sendRedirect("/test/index.html");
}
}
Exemplo XVI.XX Redirecionamento de requisio.
Note pelo exemplo que preciso passar o contexto do recurso
(/teste). No caso de redirecionamento o a requisio corrente perdida e uma
nova requisio feita para a URL de destino. Por isso no se deve associar
nenhum objeto requisio, uma vez que o objeto HttpServletRequest
corrente ser perdido. O que ocorre na prtica que o servidor envia uma
mensagem HTTP 302 de volta para o cliente informando que o recurso foi
transferido para outra URL e o cliente envia uma nova requisio para a URL
informada.
J no caso de reencaminhamento a requisio encaminhada diretamente
para a nova URL mantendo todos os objetos associados e evitando uma nova ida
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
400
ao cliente. Portanto, o uso de reencaminhamento mais eficiente do que o uso
de redirecionamento. O reencaminhamento obtido usando o mtodo
forward() de uma instncia RequestDispatcher, passando como
argumento os objetos HttpServletRequest e HttpServletResponse
para a URL de destino. Uma instncia RequestDispatcher obtida por
meio do mtodo getRequestDispatcher()de uma instncia
ServletContext , que obtido, por sua vez, por meio do mtodo
getServletContext() do Servlet. O exemplo XX.XX mostra o cdigo de
um Servlet reencaminhando a requisio para uma pgina J SP.
import javax.servlet.*;
import javax.servlet.http.*;
public class Reencaminha extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
try
{
getServletContext().getRequestDispatcher("/index.html").
forward(request,response);
}catch (Exception e) {
System.out.println("Servlet falhou: ");
e.printStackTrace();
}
}
}
Exemplo XVI.XX Reencaminhamento de requisio.
Note que no necessrio passar o contexto na URL, como feito no
redirecionamento, uma vez que a requisio encaminhada no contexto
corrente.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
401
Uma Arquitetura para comrcio eletrnico
O projeto de uma soluo para comrcio eletrnico uma tarefa
complexa e deve atender diversos requisitos. Nesta seo mostraremos uma
modelo de arquitetura bsico para comrcio eletrnico que pode ser adaptado
para solues mais especficas. Este modelo implementa o padro de projeto
MVC, procurando, desta forma, isolar esses aspectos de um sistema de
computao.
Tipos de aplicaes na WEB
Podemos enquadra as aplicaes na Web em um dos seguintes tipos:
Business-to-consumer (B2C) entre empresa e consumidor. Exemplo: uma
pessoa compra um livro na Internet.
Business-to-business (B2B) Troca de informaes e servios entre
empresas. Exemplo: o sistema de estoque de uma empresa de automveis
detecta que um item de estoque precisa ser resposta e faz o pedido
diretamente ao sistema de produo do fornecedor de autopeas. Neste tipo
de aplicao a linguagem XML possui um papel muito importante, uma vez
que existe a necessidade de uma padronizao dos tags para comunicao de
contedo.
User-to-data acesso bases de informao. Exemplo: uma usurio
consulta uma base de informao.
User-to-user chat, e troca de informaes entre usurios (Morpheus).
O exemplo que mostraremos tipicamente um caso de User-to-data,
(agenda eletrnica na Web) mas possui a mesma estrutura de um B2C.
Arquitetura MVC para a Web
A figura XX.XX contm um diagrama de blocos que mostra a
participao de Servlets, J SP e J avaBeans na arquitetura proposta. A idia
isolar cada aspecto do modelo MVC com a tecnologia mais adequada. A pgina
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
402
J SP tima para fazer o papel da viso, uma vez que possui facilidades para a
insero de componentes visuais e para a apresentao de informao. No
entanto, um pouco estranho usar uma pgina J SP para receber e tratar uma
requisio. Esta tarefa, que se enquadra no aspecto de controle do modelo MVC
mais adequada a um Servlet, uma vez que neste momento componentes de
apresentao so indesejveis. Finalmente, desejvel que a modelagem do
negcio fique isolada dos aspectos de interao. A proposta que a modelagem
do negcio fique contida em classes de J avaBeans. Em aplicaes mais
sofisticadas a modelagem do negcio deve ser implementada por classes de
Enterprise J avaBeans (EJ B), no entanto esta forma de implementao foge ao
escopos deste livro. Cada componente participa da seguinte forma:
Servlets Atuam como controladores, recebendo as requisies dos
usurios. Aps a realizao das anlises necessria sobre a requisio,
instancia o J avaBean e o armazena no escopo adequado (ou no caso o bean
j tenha sido criado no escopo) e encaminha a requisio para a pgina J SP.
J avaBeans Atuam como o modelo da soluo, independente da requisio
e da forma de apresentao. Comunicam-se com a camada intermediria que
encapsula a lgica do problema.
J SP Atuam na camada de apresentao utilizando os J avaBeans para
obteno dos dados a serem exibidos, isolando-se assim de como os dados
so obtidos. O objetivo minimizar a quantidade de cdigo colocado na
pgina.
Camada Intermediria (Middleware) Incorporam a lgica de acesso aos
dados. Permitem isolar os outros mdulos de problemas como estratgias de
acesso aos dados e desempenho. O uso de EJ B (Enterprise J avaBeans)
recomendado para a implementao do Middleware, uma vez que os EJ Bs
possuem capacidades para gerncia de transaes e persistncia. Isto implica
na adoo de um servidor de aplicao habilitado para EJ B.
A figura XX.XX mostra a interao entre os componentes.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
403
Figura XV.XX. Arquitetura de uma aplicao para Comrcio Eletrnico.
Essa arquitetura possui as seguintes vantagens:
1. Facilidade de manuteno: a distribuio lgica das funes entre os
mdulos do sistema isola o impacto das modificaes.
2. Escalabilidade: Modificaes necessria para acompanhar o aumento da
demanda de servios (database pooling, clustering, etc) ficam concentradas
na camada intermediria.
A figura abaixo mostra a arquitetura fsica de uma aplicao de comrcio
eletrnico.
Navegador Web
JSP
(Apresentao)
Requisio
Servlet
(controlador)
Resposta
JavaBean
(modelo)
Cria uma instncia
Servidor de Aplicao
1
5
4
3
2
SGBD
J DBC
MiddleWare
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
404
Figura XV.XX. Arquitetura fsica de uma aplicao para Comrcio Eletrnico.
Demilitarized Zone (DMZ) onde os servidores HTTP so instalados. A
DMZ protegida da rede pbica por um firewall, tambm chamado de firewall
de protocolo. O firewall de protocolo deve ser configurado para permitir trfego
apenas atravs da porta 80. Um segundo firewall, tambm chamado de firewall
de domnio separa a DMZ da rede interna. O firewall de domnio deve ser
configurado para permitir comunicao apenas por meio das portas do servidor
de aplicao
Agenda Web: Um Exemplo de uma aplicao Web usando a
arquitetura MVC
O exemplo a seguir mostra o desenvolvimento da agenda eletrnica para
o funcionamento na Web. A arquitetura adotada uma implementao do
modelo MVC. Apenas, para simplificar a soluo, a camada intermediria foi
simplificada e implementada por um J avaBean que tem a funo de gerenciar a
conexo com o banco de dados. O banco de dados ser composto por duas
tabelas, uma para armazenar os usurios autorizados a usar a tabela e outra para
armazenar os itens da agenda. A figura XX.XX mostra o esquema conceitual do
banco de dados e a figura XX.XX mostra o comando para a criao das tabelas.
Note que existe um relacionamento entre a tabela USUARIO e a tabela PESSOA,
mostrando que os dados pessoais sobre o usurio ficam armazenados na agenda.
USUARIO PESSOA
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
405
Figura XV.XX. Esquema conceitual do banco de dados para a agenda.
As tabelas do BD devem ser criadas de acordo com o seguinte script:
CREATE TABLE PESSOA (ID INT PRIMARY KEY,
NOME VARCHAR(50) NOT NULL,
TELEFONE VARCHAR(50),
ENDERECO VARCHAR(80),
EMAIL VARCHAR(50),
HP VARCHAR(50),
CELULAR VARCHAR(20),
DESCRICAO VARCHAR(80));
CREATE TABLE USUARIO (ID INT PRIMARY KEY,
LOGIN VARCHAR(20) NOT NULL,
SENHA VARCHAR(20) NOT NULL,
CONSTRAINT FK_USU FOREIGN KEY (ID)
REFERENCES PESSOA(ID));
Figura XV.XX. Script para criao das tabelas.
Para se usar a agenda necessrio que exista pelo menos um usurio
cadastrado. Como no exemplo no vamos apresentar uma tela para cadastro de
usurios ser preciso cadastr-los por meio comandos SQL. Os comandos da
figura XX.XX mostram como cadastrar um usurio.
INSERT INTO PESSOA(ID,NOME,TELEFONE,ENDERECO,EMAIL)
VALUES(0,'Alcione de Paiva Oliveira','3899-1769',
'PH Rolfs','alcionepaiva@globo.com');
INSERT INTO USUARIO(ID,LOGIN,SENHA) VALUES(0,'Alcione','senha');
Figura XV.XX. Script para cadastra um usurio.
O sistema e-agenda composta pelos seguintes arquivos:
1:1 1:1
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
406
Arquivo Descrio
agenda.html
Pgina inicial do site, contendo o formulrio para a
entrada do login e senha para entrar no restante do
site.
principal.jsp
Pgina J SP contendo o formulrio para entrada de
dados para insero, remoo ou consulta de itens da
agenda.
LoginBean.java
J avaBean responsvel por verificar se o usurio est
autorizado a acessar a agenda.
AgendaServlet.java
Servlet responsvel pelo tratamento de requisies
sobre alguma funo da agenda (consulta, insero e
remoo)
AcaoBean.java
J avaBean responsvel pela execuo da ao
solicitada pelo usurio.
ConnectionBean.java
J avaBean responsvel pelo acesso ao DB e controle
das conexes.
Tabela XV.XX. Arquivos do sistema e-agenda.
O diagrama de colaborao abaixo mostra as interao entre os
componentes do sistema.
Figura XV.XX. Interao entre os componentes do sistema.
1 e 4 Requisies
2 e 6 instanciaes
4 reencaminhamento de
requisies
3,5,7 e 8 Chamadas de mtodos
agenda.html AgendaServlet
ConnectionBean LoginBean
AcaoBean
principal.jsp
1
2
4
5
7
8
3
6
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
407
Descreveremos agora cada componente da aplicao. O exemplo XX.XX
mostra cdigo HTML da pgina agenda.html. Esta a pgina inicial da
aplicao. Ela contm o formulrio para a entrada do login e senha para entrar
no restante do site.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
20
31
32
33
34
35
36
37
38
39
<HTML>
<HEAD>
<TITLE>Agenda</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<P align="center"><IMG src="tit.gif" width="350" height="100" border="0"></P>
<BR>
<CENTER>
<FORM method="POST" name="TesteSub" onsubmit="return TestaVal()"
action="/agenda/agenda"><BR>
Login:<INPUT size="20" type="text" name="login"><BR><BR>
Senha:<INPUT size="20" type="password" name="senha"><BR><BR><BR>
<INPUT type="submit" name="envia" value="Enviar">
<INPUT size="3" type="Hidden" name="corrente" value="0"><BR>
</FORM>
</CENTER>
<SCRIPT language="J avaScript">
<!--
function TestaVal()
{
if (document.TesteSub.login.value == " " )
{
alert (" Campo Login nao Preenchido...Form nao Submetido" )
return false
}
else if (document.TesteSub.senha.value == " " )
{
alert (" Campo Senha nao Preenchido...Form nao Submetido" )
return false
}
else
{
return true
}
}
//--></SCRIPT>
</BODY></HTML>
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
408
Exemplo XVI.XX agenda.html.
O formulrio est definido nas linha 11 a 17. Na linha 12 o parmetro
action indica a URL que dever receber a requisio. A URL virtual e sua
associao com o Servlet AgendaServlet ser definida no arquivo
web.xml. Na linha 16 definido um campo oculto (Hidden) como o nome de
corrente e valor 0. Ele ser usado pelo AgendaServlet reconhecer a
pgina de onde saiu a requisio. As linha 19 a 31 definem uma funo em
J avaScript que ser usada para verificar se o usurio digitou o nome e a senha
antes de enviar a requisio ao usurio. O uso de J avaScript no lado cliente para
criticar a entrada do usurio muito comum pois diminui a sobrecarga do
servidor.
O exemplo XX.XX mostra cdigo da pgina principal.jsp. Esta
pgina contm o formulrio para entrada de dados para insero, remoo ou
consulta de itens da agenda. Na linha 4 a diretiva page define que o servidor
deve acompanhar a sesso do usurio e importa o pacote agenda. Na linha 7
um objeto da classe agenda.LoginBean recuperado da sesso por meio do
mtodo getAttribute(). Para recuperar o objeto preciso passar para o
mtodo o nome que est associado ao objeto na sesso. De forma semelhante, na
linha 8 um objeto da classe agenda.AcaoBean recuperado da requisio
por meio do mtodo getAttribute(). Este objeto recuperado da
requisio porque cada requisio possui uma ao diferente associada. Na linha
9 verificado se objeto agenda.LoginBean foi recuperado e se o retorno do
mtodo getStatus() true. Se o objeto agenda.LoginBean no foi
recuperado significa que existe uma tentativa de acesso direto pgina
principal.jsp sem passar primeiro pela pgina agenda.html ou que a
sesso se esgotou. Se o mtodo getStatus() retornar false significa que o
usurio no est autorizado a acessar essa pgina. Nestes casos processado o
cdigo associado ao comando else da linha 51 que apaga a sesso por meio do
mtodo invalidate() do objeto HttpSession (linha 53) e mostra a
mensagem Usurio no autorizado (linha 55). Caso o objeto indique que o
usurio est autorizado os comandos internos ao if so executados. Na linha 11
mostrada uma mensagem com o nome do usurio obtido por meio do mtodo
getNome() do objeto agenda.LoginBean . Na linha 13 mostrado o
resultado da ao anterior por meio do mtodo toString() do objeto
agenda.AcaoBean. A ao pode ter sido de consulta, insero de um novo
item na agenda e remoo de um item na agenda. No primeiro caso mostrado
uma lista dos itens que satisfizeram a consulta. No segundo e terceiro casos
exibida uma mensagem indicado se a operao foi bem sucedida.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
409
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<HTML><HEAD>
<TITLE>Tela da Agenda </TITLE>
</HEAD><BODY bgcolor="#FFFFFF">
<%@ page session=" true" import=" agenda.*" %>
<%
agenda.LoginBean lb = (agenda.LoginBean) session.getAttribute(" loginbean" );
agenda.AcaoBean ab = (agenda.AcaoBean) request.getAttribute(" acaobean" );
if (lb != null && lb.getStatus())
{ %>
<H2>Sess&atilde;o do <%=lb.getNome() %></H2>
<%
if (ab!=null) out.println(ab.toString());
%>
<P><BR></P>
<FORM method="POST" name="formprin" onsubmit="return TestaVal()"
action="/agenda/agenda">
Nome: <INPUT size="50" type="text" name="nome"><BR>
Telefone: <INPUT size="20" type="text" name="telefone"><BR>
Endere&ccedil;o: <INPUT size="50" type="text" name="endereco"><BR>
Email: <INPUT size="50" type="text" name="email"><BR><BR>
P&aacute;gina: <INPUT size="50" type="text" name="pagina"><BR>
Celular: <INPUT size="20" type="text" name="celular"><BR>
Descri&ccedil;&atilde;o: <INPUT size="20" type="text" name="descricao">
<BR><CENTER>
<INPUT type="submit" name="acao" value="Consulta">
<INPUT type="submit" name="acao" value="Insere">
<INPUT type="submit" name="acao" value="Apaga"></CENTER>
<INPUT size="3" type="Hidden" name="corrente" value="1">
</FORM>
<SCRIPT language="J avaScript"><!--
function TestaVal()
{
if (document.formprin.nome.value == " " &&
document.formprin.descricao.value== " " )
{
alert (" Campo Nome ou Descricao devem ser Preenchidos!" )
return false
}
else
{
return true
}
}
//--></SCRIPT>
<%
}
else
{
session.invalidate();
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
410
54
55
56
57
58
59
%>
<H1>Usu&aacute;rio n&atilde;o autorizado</H1>
<%
}
%>
</BODY></HTML>
Exemplo XVI.XX principal.jsp.
As linhas 17 a 31 definem o cdigo do formulrio de entrada. Nas linhas
17 e 18 so definidos os atributos do formulrio. O atributo method indica a
requisio ser enviada por meio do mtodo POST. O atributo name define o
nome do formulrio como sendo formprin. O atributo onsubmit define que
a funo javaSript TestaVal() deve ser executada quando o formulrio for
submetido. Finalmente, o atributo action define a URL para onde a requisio
deve ser enviada. Neste caso a URL agenda/agenda que est mapeada para
o Servlet AgendaServlet. O mapeamento feito no arquivo web.xml do
diretrio web-inf do contexto agenda, como mostrado na figura XX.XX. As
linhas 19 a 25 definem os campos de texto para entrada dos valores. As linhas 27
a 29 definem os botes de submit. Todos possuem o mesmo nome, de forma que
o Servlet precisa apenas examinar o valor do parmetro acao para determinar
qual ao foi solicitada Na linha 30 definido um campo oculto (Hidden)
como o nome de corrente e valor 0. Ele ser usado pelo AgendaServlet
reconhecer a pgina de onde saiu a requisio. As linha 33 a 47 definem uma
funo em J avaScript que ser usada para verificar se o usurio entrou com
valores nos campos de texto nome ou decricao. No mnimo um desses
campos deve ser preenchido para que uma consulta possa ser realizada.
O exemplo XX.XX mostra cdigo do J avaBean usado para intermediar a
conexo com o banco de dados. O J avaBean ConnectionBean tem a
responsabilidade de abrir uma conexo com o banco de dados, retornar uma
referncia desta conexo quando solicitado e registrar se a conexo esta livre ou
ocupada. Neste exemplo o se encarrega apenas de obter a conexo e fech-la, no
entanto, em aplicao com maior nmero de acessos ao banco de dados pode ser
necessrio um maior controle sobre o uso das conexes, mantendo-as em uma
estrutura de dados denominada de pool de conexes. Na linha 12 podemos
observar que o construtor da classe foi declarado com o modificador de acesso
private. Isto significa que no possvel invocar o construtor por meio de um
objeto de outra classe. Isto feito para que se possa ter um controle sobre a
criao de instncias da classe. No nosso caso permitiremos apenas que uma
instncia da classe seja criada, de modo que todas as referncias apontem para
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
411
esse objeto. Esta tcnica de programao, onde se permite uma nica instncia
de uma classe denominada de padro de projeto Singleton. O objetivo de
utilizarmos este padro porque desejamos que apenas um objeto controle a
conexo com o banco de dados. Ma se o construtor no pode ser chamado
internamente como uma instncia da classe criada e sua referncia passada
para outros objetos? Esta a tarefa do mtodo esttico getInstance()
(linhas 14 a 19). Este mtodo verifica se j existe a instncia e retorna a
referncia. Caso a instncia no exista ela criada antes de se retornar a
referncia. O mtodo init() (linhas 21 a 27) chamado pelo construtor para
estabelecer a conexo com o SGBD. Ele carrega o driver J DBC do tipo 4 para
HSQLDB e obtm uma conexo com o SGBD. O mtodo
devolveConnection() (linhas 29 a 34) chamado quando se deseja
devolver a conexo. Finalmente, o mtodo getConnection() (linhas 36 a
46) chamado quando se deseja obter a conexo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package agenda;
import java.sql.*;
import java.lang.*;
import java.util.*;
public class ConnectionBean {
private Connection con=null;
private static int clients=0;
static private ConnectionBean instance=null;
private ConnectionBean() { init(); }
static synchronized public ConnectionBean getInstance() {
if (instance ==null) {
instance =new ConnectionBean();
}
return instance;
}
private void init() {
try {
Class.forName("org.hsqldb.jdbcDriver");
con=
DriverManager.getConnection("jdbc:hsqldb:hsql://localhost","sa","");
}catch(Exception e){System.out.println(e.getMessage());};
}
public synchronized void devolveConnection(Connection con) {
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
412
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
if (this.con==con) {
clients--;
notify();
}
}
public synchronized Connection getConnection() {
if(clients>0) {
try {
wait(5000);
}
catch (InterruptedException e) {};
if(clients>0) return null;
}
clients ++;
return con;
}
}
Exemplo XVI.XX ConnectionBean.java.
O exemplo XX.XX mostra cdigo do J avaBean usado para verificar se o
usurio est autorizado a usar a agenda. O J avaBean LoginBean recebe o
nome e a senha do usurio, obtm a conexo com o SGBD e verifica se o
usurio est autorizado, registrando o resultado da consulta na varivel status
(linha 10). Tudo isso feito no construtor da classe (linhas 12 a 35). Note que na
construo do comando SQL (linhas 17 a 20) inserido uma juno entre as
tabelas PESSOA e USUARIO de modo a ser possvel recuperar os dados
relacionados armazenados em ambas as tabelas. Os mtodos getLogin(),
getNome() e getStatus() (linhas 36 a 38) so responsveis pelo retorno
do login, nome e status da consulta respectivamente.
1
2
3
4
5
6
7
8
9
10
11
package agenda;
import java.sql.*;
import java.lang.*;
import java.util.*;
public class LoginBean {
protected String nome =null;
protected String login=null;
protected boolean status=false;
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
413
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public LoginBean(String login, String senha)
{
this.login =login;
Connection con=null;
Statement stmt =null;
String consulta ="SELECT NOME FROM PESSOA, USUARIO "+
"WHERE USUARIO.ID =PESSOA.ID AND "+
"USUARIO.SENHA ='"+senha+"' AND "+
"USUARIO.LOGIN ='"+login+"'";
try {
con=ConnectionBean.getInstance().getConnection();
stmt =con.createStatement();
ResultSet rs =stmt.executeQuery(consulta);
if(rs.next()) {
status =true;
nome =rs.getString("NOME");
}
}catch(Exception e){System.out.println(e.getMessage());}
finall y {
ConnectionBean.getInstance().devolveConnection(con);
try{stmt.close();}catch(Exception ee){};
}
}
public String getLogin(){return login;}
public String getNome(){return nome;}
public boolean getStatus(){return status;}
}
Exemplo XVI.XX LoginBean.java.
O exemplo XX.XX mostra cdigo do Servlet que implementa a camada
de controle do modelo MVC. O Servlet AgendaServlet recebe as
requisies e, de acordo com os parmetros, instncia os J avaBeans apropriados
e reencaminha as requisies para as pginas corretas. Tanto o mtodo
doGet() (linhas 9 a 12) quanto o mtodo doPost()(linhas 13 a 17) invocam
o mtodo performTask()(linhas 19 a 61) que realiza o tratamento da
requisio. Na linhas 24 a 26 do mtodo performTask() obtido o valor do
parmetro corrente que determina a pgina que originou a requisio. Se o
valor for nulo assumido o valor default zero. Na linha 30 executado um
comando switch sobre esse valor, de modo a desviar para bloco de comandos
adequado. O bloco que vai da linha 32 at a linha 43 trata a requisio originada
em uma pgina com a identificao 0 (pgina agenda.html). Nas linhas 32 e
33 so recuperados o valor de login e senha digitados pelo usurio. Se algum
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
414
desses valores for nulo ento a requisio deve ser reencaminhada para a pgina
de login (agenda.html) novamente (linha 35). Caso contrrio instanciado
um objeto LoginBean, inserido na sesso corrente e definida a pgina
principal.jsp como a pgina para o reencaminhamento da requisio
(linhas 38 a 41). J o bloco que vai da linha 44 at a linha 54 trata a requisio
originada em uma pgina com a identificao 1 (pgina principal.jsp). Na
linha 44 recuperado o objeto HttpSession corrente. O argumento false
utilizado para impedir a criao de um novo objeto HttpSession caso no
exista um corrente. Se o valor do objeto for null, ento a requisio deve ser
reencaminhada para a pgina de login (linha 47). Caso contrrio instanciado
um objeto AcaoBean, inserido na requisio corrente e definida a pgina
principal.jsp como a pgina para o reencaminhamento da requisio
(linhas 50 a 52). Na linha 56 a requisio reencaminhada para a pgina
definida (pgina agenda.html ou principal.jsp).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package agenda;
import javax.servlet.*;
import javax.servlet.http.*;
import agenda.*;
public class AgendaServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
performTask(request,response);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
{
performTask(request,response);
}
public void performTask(HttpServletRequest request,
HttpServletResponse response)
{
String url;
HttpSession sessao;
String corrente =request.getParameter("corrente");
int icorr=0;
if (corrente !=null) icorr =Integer.parseInt(corrente);
try
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
415
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{
switch(icorr)
{
case 0: String login =request.getParameter("login");
String senha =request.getParameter("senha");
if (login ==nul l||senha ==null)
url="/agenda.html";
el se
{
sessao =request.getSession(true);
sessao.setAttribute("loginbean",
new agenda.LoginBean(login,senha));
url="/principal.jsp";
};
break;
case 1:
sessao =request.getSession(false);
if (sessao ==null)
url="/agenda.html";
el se
{
request.setAttribute("acaobean",
new agenda.AcaoBean(request));
url="/principal.jsp";
};
break;
}
getServletContext().getRequestDispatcher(url).forward(request,response);
}catch (Exception e) {
System.out.println("AgendaServlet falhou: ");
e.printStackTrace();
}
}
}
Exemplo XVI.XX AgendaServlet.java.
O exemplo XX.XX mostra cdigo do J avaBean usado para realizar a
manuteno da agenda. O J avaBean AcaoBean responsvel pela consulta,
remoo e insero de novos itens na agenda. Um objeto StringBuffer
referenciado pela varivel retorno utilizado pelo J avaBean para montar o
resultado da execuo. O construtor (linhas 16 a 27) verifica o tipo de requisio
e invoca o mtodo apropriado.
O mtodo consulta() (linhas 29 a 77) responsvel pela realizao
de consultas. As consultas podem ser realizadas sobre o campo nome ou
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
416
descrio e os casamentos podem ser parciais, uma vez que usado o operador
LIKE. A consulta SQL montada nas linhas 40 a 47. Na linha 50 obtida uma
conexo com SGBD por meio do objeto ConnectionBean. Na linha 57 o
comando SQL executado e as linhas 59 a 72 montam o resultado da consulta.
O mtodo insere() (linhas 79 a 148) responsvel por inserir um
item na agenda. Na linha 95 obtida uma conexo com SGBD por meio do
objeto ConnectionBean. Para inserir um novo item preciso obter o nmero
do ltimo identificador usado, incrementar o identificador e inserir na base o
item com o identificador incrementado. Esta operao requer que no seja
acrescentado nenhum identificador entre a operao de leitura do ltimo
identificador e a insero de um novo item. Ou seja, necessrio que essas
operaes sejam tratadas como uma nica transao e o isolamento entre as
transaes sejam do nvel Repeatable Read. A definio do inicio da transao
feita no comando da linha 102. A mudana do nvel de isolamento feita pelos
comandos codificados nas linha 103 a 109. Na linha 112 invocado o mtodo
obtemUltimo() (linhas 150 a 171) para obter o ltimo identificador
utilizado. As linhas 114 a 128 montam o comando SQL para a execuo. O
comando SQL executado na linha 131. O fim da transao definido pelo
comando da linha 132. Ao fim da transao, de forma a no prejudicar a
concorrncia, o nvel de isolamento deve retornar para um valor mais baixo. Isto
feito pelos comandos das linhas 133 a 137.
O mtodo apaga() (linhas 173 a 201) responsvel por remover um
item da agenda. As linhas 175 a 180 contm o cdigo para verificar se o usurio
digitou o nome associado ao item que deve ser removido. A linha 181 montam o
comando SQL para a execuo. Na linha 184 obtida uma conexo com SGBD
por meio do objeto ConnectionBean. O comando SQL executado na linha
191.
1
2
3
4
5
6
7
8
9
10
11
12
13
package agenda;
import java.lang.*;
import java.util.*;
import java.sql.*;
public class AcaoBean
{
private Connection con=null;
private StringBuffer retorno =null;
private Statement stmt=null;
private String [] legenda={"C&oacute;digo","Nome","Telefone",
"Endere&ccedil;o", "email","hp",
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
417
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"celular","Descri&ccedil;&atilde;o"};
public AcaoBean(javax.servlet.http.HttpServletRequest request)
{
String acao =request.getParameter("acao");
if (acao.equals("Consulta"))
{
String nome =request.getParameter("nome");
String descri =request.getParameter("descricao");
consulta(nome,descri);
}
else if (acao.equals("Insere")) insere(request);
else if (acao.equals("Apaga")) apaga(request);
}
private void consulta(String nome,String descri)
{
String consulta =null;
if ((nome ==null||nome.length()<1) &&
(descri ==nul l|| descri.length()<1))
{
retorno =new StringBuffer("Digite o nome ou descricao!");
return;
}
if (descri ==null|| descri.length()<1)
consulta ="SELECT * FROM PESSOA WHERE NOME LIKE '%"+
nome+"%'"+" ORDER BY NOME";
else if (nome ==null|| nome.length()<1)
consulta ="SELECT * FROM PESSOA WHERE DESCRICAO LIKE '%"+
descri+"%'"+" ORDER BY NOME";
else consulta="SELECT * FROM PESSOA WHERE DESCRICAO LIKE '%"+
descri+"%' AND NOME LIKE '%"+nome+"%' ORDER BY NOME";
try
{
con=ConnectionBean.getInstance().getConnection();
if (con ==null)
{
retorno =new StringBuffer("Servidor ocupado. Tente mais tarde.!");
return;
}
stmt =con.createStatement();
ResultSet rs =stmt.executeQuery(consulta);
retorno =new StringBuffer();
retorno.append("<br><h3>Resultado</h3><br>");
while(rs.next())
{
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
418
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
retorno.append("ID:").append(rs.getString("id"));
retorno.append("<br>Nome:").append(rs.getString("Nome"));
retorno.append("<br>Telefone:").append(rs.getString("Telefone"));
retorno.append("<br>Endereco:").append(rs.getString("Endereco"));
retorno.append("<br>email:").append(rs.getString("email"));
retorno.append("<br>hp:").append(rs.getString("hp"));
retorno.append("<br>celular:").append(rs.getString("celular"));
retorno.append("<br>descricao:").append(rs.getString("descricao"));
retorno.append("<br><br>");
}
} catch(Exception e){System.out.println(e.getMessage());}
finall y {ConnectionBean.getInstance().devolveConnection(con);
try{stmt.close();}catch(Exception ee){};
}
}
private void insere(javax.servlet.http.HttpServletRequest request)
{
String[] par ={"telefone","endereco","email","hp","celular","descricao"};
StringBuffer comando =new StringBuffer("INSERT INTO PESSOA(");
StringBuffer values =new StringBuffer(" VALUES(");
String aux =request.getParameter("nome");
if (aux ==null || aux.length()<1)
{
retorno =new StringBuffer("<br><h3>Digite o nome!</h3><br>");
return;
}
try
{
con=ConnectionBean.getInstance().getConnection();
if (con ==null)
{
retorno =new StringBuffer("Servidor ocupado. Tente mais tarde!");
return;
}
con.setAutoCommit(false);
DatabaseMetaData meta=con.getMetaData();
if(meta.supportsTransactionIsolationLevel(
con.TRANSACTION_REPEATABLE_READ)) {
con.setTransactionIsolation(
con.TRANSACTION_REPEATABLE_READ);
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
419
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
int ultimo =obtemUltimo(con);
if (ultimo==-1) return;
ultimo++;
comando.append("id,nome");
values.append(ultimo+",'").append(aux).append("'");
for(int i=0;i<par.length;i++)
{
aux =request.getParameter(par[i]);
if (aux !=null && aux.length()>0)
{
comando.append(",").append(par[i]);
values.append(",'").append(aux).append("'");
}
}
comando.append(")");
values.append(")");
aux =comando.toString()+values.toString();
stmt = con.createStatement();
stmt.executeUpdate(aux);
con.setAutoCommit(true);
if(meta.supportsTransactionIsolationLevel(
con.TRANSACTION_READ_COMMITTED)) {
con.setTransactionIsolation(
con.TRANSACTION_READ_COMMITTED);
}
retorno =new StringBuffer("<br><h3>Inserido!</h3><br>");
return;
} catch(Exception e)
{retorno =
new StringBuffer("<br><h3>Erro:"+e.getMessage()+"!</h3><br>"); }
finall y
{
ConnectionBean.getInstance().devolveConnection(con);
try{stmt.close();}catch(Exception ee){};
}
}
private int obtemUltimo(Connection con)
{
String consulta ="SELECT MAX(ID) AS maior FROM PESSOA";
try
{
if (con ==null)
{
retorno =new StringBuffer("Servidor ocupado. Tente mais tarde.!");
return -1;
}
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
420
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
stmt =con.createStatement();
ResultSet rs =stmt.executeQuery(consulta);
if(rs.next())
return Integer.parseInt(rs.getString("maior"));
else return 0;
}catch(Exception e) {
retorno =
new StringBuffer("<br><h3>Erro:"+e.getMessage()+"!</h3><br>");
return -1;
}
finall y {try{stmt.close();}catch(Exception ee){};}
}
private void apaga(javax.servlet.http.HttpServletRequest request)
{
String aux =request.getParameter("nome");
if (aux ==null || aux.length()<1)
{
retorno =new StringBuffer("<br><h3>Digite o nome!</h3><br>");
return;
}
String consulta ="DELETE FROM PESSOA WHERE NOME ='"+aux+"'";
try
{
con=ConnectionBean.getInstance().getConnection();
if (con ==null)
{
retorno =new StringBuffer("Servidor ocupado. Tente mais tarde.!");
return;
}
stmt = con.createStatement();
stmt.executeUpdate(consulta);
retorno =new StringBuffer("<br><h3>Removido!</h3><br>");
return;
}catch(Exception e){
retorno =new StringBuffer("<br><h3>Erro:"+e.getMessage()+"!</h3><br>");
}
finall y {
ConnectionBean.getInstance().devolveConnection(con);
try{stmt.close();}catch(Exception ee){};}
}
public String[] getLeg(){return legenda;}
public String toString(){return retorno.toString();}
}
Exemplo XVI.XX AcaoBean.java.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
421
Instalao do SGBD
O HSQLDB (www.hsqldb.org) um SGBD de cdigo aberto
desenvolvido em J ava. Ele obedece os padres SQL e J DBC. Possui as seguintes
caractersticas:
Tamanho pequeno ( 100KB).
Funciona como servidor, standalone e in-memory.
Suporta transao.
Integridade referencial.
Procedimentos Armazenados em J ava.
Direitos de acessos
Para instal-lo em no MS-Windows execute as seguintes etapas:
1) Descompacte o arquivo hsqldb_v.1.61.zip em um diretrio qualquer. Por
exemplo : c:\sgbd
2) Coloque o seguinte comando em seu autoexec.bat
SET CLASSPATH=%CLASSPATH%;c:\sgbd\hsqldb_v.1.61\lib\hsqldb.jar
Execuo em modo servidor
c:\sgbd\hsqldb_v.1.61\demo\runServer.bat
Execuo do gerenciador grfico
c:\sgbd\hsqldb_v.1.61\demo\runManager.bat
Instalao da Aplicao
Para instalar crie a seguinte estrutura de diretrio abaixo do diretrio
webapps do Tomcat:
Servlets e
J avaBeans
pginas
HTML e J SP
arquivo
web.xml
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
422
webapps
|_____ agenda
|_____ Web-inf
|_____classes
|_______agenda
Figura XV.XX. Estrutura de diretrios para a aplicao agenda.
O arquivo web.xml deve ser alterado para conter mapeamento entre a
URL agenda e o Servlet AgendaServlet.
...
<web-app>
<servlet>
<servlet-name>
agenda
</servlet-name>
<servlet-class>
agenda.AgendaServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>
agenda
</servlet-name>
<url-pattern>
/agenda
</url-pattern>
</servlet-mapping>
...
</web-app>
Figura XV.XX. Arquivo web.xml para a agenda.
Consideraes sobre a soluo
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
423
A aplicao acima implementa uma agenda que pode ser acessada por meio
da Internet, no entanto, devido falta de espao e necessidade de destacarmos
os pontos principais, alguns detalhes foram deixados de lado, como por exemplo
uma melhor interface com o usurio. Abaixo seguem alguns comentrios sobre
algumas particularidades da aplicao:
1. O J avaBean da classe LoginBean armazenado na sesso para
permitir a verificao se o acesso ao site autorizado. Isto impede que os
usurios tentem acessar diretamente a pgina principal.jsp da
agenda. Caso tentem fazer isso, a sesso no conter um objeto
LoginBean associado e, portanto, o acesso ser recusado.
2. O J avaBean da classe AcaoBean armazenado no objeto request
uma vez que sua informaes so alteradas a cada requisio. Uma forma
mais eficiente seria manter o objeto AcaoBean na sesso e cada novo
requisio invocar um mtodo do AcaoBean para gerar os resultados.
No entanto, o objetivo da nossa implementao no fazer a aplicao
mais eficiente possvel, e sim mostrar para o leitor uma aplicao com
variadas tcnicas.
3. Apesar de termos adotado o padro MVC de desenvolvimento a
aplicao no exibe uma separao total da camada de apresentao
(Viso) em relao camada do modelo. Parte do cdigo HTML da
viso inserido pelo AcaoBean no momento da construo da String
contendo o resultado da ao. Isto foi feito para minimizar a quantidade
de cdigo J ava na pgina J SP. Pode-se argumentar que neste caso a
promessa da separao entre as camadas no cumprida totalmente.
Uma soluo para o problema seria gerar o contedo em XML e utilizar
um analisador de XML para gerar a pgina de apresentao. No entanto,
o uso da tecnologia XML foge ao escopo deste livro.
4. A soluo apresenta cdigo redundante para criticar as entradas do
usurio. Existe cdigo J avaScript nas pginas, e cdigo J ava no Servlet e
J avaBeans. O uso de cdigo J avaScript nas pginas para crticas de
entrada indispensvel para aliviarmos a carga sobre o servidor. J o
cdigo para crtica no servidor no causa impacto perceptvel e til para
evitar tentativas de violao.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
424
Captulo XVII Perguntas Frequentes
Como executar um programa a partir de uma aplicao em Java?
Resposta: isso pode ser feito com o mtodo de instncia exec da classe
Runtime.
Como criar um TextField que no exiba o que est sendo digitado para
se usado como campo de entrada de senhas?
Resposta: use o mtodo setEchoChar() do TextField para definir qual
caractere que deve ser ecoado.
Como aumentar a rea de ambiente do DOS para caber o CLASSPATH?
Resposta: coloque a seguinte linha no autoexec.bat
set shell=c:\command.com /e:4096
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
425
Bibliografia
Eckel B. Thinking in Java. 2
nd
Ed. New J ersey : Prentice Hall, 2000.
Gosling J ., J oy W., Steele G. The Java Language Specification. Massachusetts :
Addison-Wesley, 1996.
Oaks S. Java Security. California : OReilly & Associates, Inc, 1998.
Oaks S., Wong H. Java Threads. 2

Ed. California : OReilly & Associates, Inc,


1999.
Watt D. A. Programming Language Concepts and Paradigms. Great Britain :
Prentice Hall, 1990.
Ethan H., Lycklama E. How do you Plug Java Memory Leaks? Dr. Dobbs
J ournal, San Francisco, CA, No. 309, February 2000.
Wahli U. e outros. Servlet and JSP Programming with IBM WebSphere Studio
and VisualAge for J ava, IBM RedBooks, California, May 2000.
Sadtler C. e outros. Patterns for e-business: User-to-Business Patterns for Topology
1 and 2 using WebSphere Advanced Edition, IBM RedBooks, California, April
2000.
Bagwel D. e outros. An Approach to Designing e-business Solutions, IBM
RedBooks, California, December 1998.
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
426
Links
Revistas
http://www.javaworld.com/
Revista online sobre J ava.
Livros
http://www.eckelobjects.com/
Pgina do autor do livro Thinking in Java, atualmente em segunda edio. O
livro pode ser baixado gratuitamente no site.
http://www.redbooks.ibm.com/booklist.html
Livros da IBM
Servidores
http://jakarta.apache.org
Pgina do projeto J akarta que desenvolveu o Tomcat.
http://www.metronet.com/~wjm/tomcat
Lista Tomcat
http://www.jboss.org
Servidor de aplicao gratuito habilitado para EJ B
Dicas J ava e recursos
http://java.sun.com/
Pgina da Sun com informaes, tutoriais e produtos J ava.
http://gamelan.earthweb.com/
Pgina da com informaes, Applets, Lista de discusso, tutoriais.
http://www.inquiry.com/techtips/java_pro
Ask the J ava Pro
http://www.jguru.com/
jGuru.com(Home): Your view of the J ava universe
http://www.soujava.org.br
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
427
Bem Vindo ao SouJ ava!
Servlets e J SP
http://www.servlet.com/srvdev.jhtml
Servlet Inc : Developers Forum
http://www.servlets.com
Servlets.com
http://www.jspin.com/home
J spin.com - The J SP Resource Index
http://www.burridge.net/jsp/jspinfo.html
Web Development with J SP: J SP, J ava Servlet, and J ava Bean
Information
http://www.apl.jhu.edu/~hall/java/Servlet-
Tutorial
A Tutorial on J ava Servlets and J ava Server Pages (J SP)
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
428
ndice
A
Acesso Direto.........................................128
Acesso Sequencial .................................123
Agregao................................................25
Arrays .............................................37, 142
ASP........................................................378
Assert...................................................63
Assertivas......................Consulte Assert
Assinatura dos mtodos.....................18, 21
Associao comum..................................23
Atribuio...............................................49
atributos...................................................67
Atributos..................................................11
AWT ......................................................165
B
Bloco........................................................52
boolean.....................................................33
booleanos
boolean................................................37
break .....................................................60
Button.................................................201
Bytecodes.............................................7, 28
C
cadeias de caracteres......... Consulte Strings
Calendar ................................................1
Caractere
char......................................................37
cardinalidade da relao...........................23
casting............ Consulte Converso de tipos
CGI ........................................................353
char ..........................................................33
Classe.................................................11, 66
classe annima.......................................180
clone.........................................................81
Coleta de Lixo............................................8
Color ...................................................197
Comentrios ...........................................51
Component..........................................199
Construtor ................................................16
Construtores ...........................................68
Containers..............................................206
contexto da aplicao............................ 361
continue.............................................. 60
Convenes............................................. 10
Converso de Tipos ............................... 41
Cookies.................................................. 369
Cpia profunda...........Consulte deep copy
Cpia rasa ..............Consulte Shallow copy
CORBA................................................. 323
Criptografia............................................... 9
D
Date ..................................................... 145
deep copy................................................. 81
Demilitarized Zone................................ 405
Diagrama de Classes................................ 20
DMZ.............. Consulte Demilitarized Zone
double...................................................... 32
do-while .................................................. 58
E
EJ B........................................................ 403
Enterprise J avaBeans..............Consulte EJ B
escape...................................................... 34
Escopo..................................................... 52
Estruturas de Controle.......................... 53
extends..................................................... 17
F
final..................................................... 76
finally.............................................. 112
float.......................................................... 32
for............................................................ 59
Frame................................................... 209
G
Garbage Collection..Consulte coleta de lixo
Generalizao.......................................... 25
H
Hashtable ......................................... 139
Herana.............................................. 12, 14
hexadecimal............................................. 31
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
1
I
Identificadores........................................29
if.............................................................53
Instncia...................................................11
Inteiros
int36
J
J 2EE.........................................................10
J 2ME........................................................10
J AR........................................................234
java.io...............................................123
J avaBean................................................239
J CE.............................................................9
J DK..........................................................10
J SP.................................................351, 376
L
Label ...................................................202
linha de comando ...................................61
List......................................................203
Literais ....................................................31
M
main.........................................................28
Mquina Virtual .........................................7
mtodo de classe......................................71
mtodo de instncia..................................71
mtodos....................................................67
Mtodos...................................................15
Modificadores de acesso ........................72
Mudana de Contexto..........................259
MVC......................................147, 402, 405
N
native...................................................78
Nveis de isolamento..............................339
Nvel de Isolamento...............................337
null........................................................34
O
Object.......................................................19
Objeto
Comportamento...................................12
Objetos...............................................11, 69
Observable .......................................147
Observer ....................................148, 150
octal ......................................................... 31
Ocultao de informao................... 14, 16
Ol mundo............................................... 27
Operadores............................................. 43
P
Palavras Reservadas.............................. 30
Panel................................................... 208
PHP ....................................................... 377
Polimorfismo........................................... 19
Ponteiro..................................................... 7
Ponto Flutuante
float, double........................................ 36
pool de conexes ................................... 411
Precedncia entre Operadores ............. 50
Prepared Statements.............................. 341
private...................................................... 16
Procedimentos Armazenados................ 342
Propriedades............................................ 11
R
RandomAccessFile......................... 128
recurso................................................... 57
Referncias Compartilhadas ................ 78
return .................................................. 69
RMI ....................................................... 323
S
separadores.............................................. 34
Servlets.................................................. 351
shallow copy............................................ 81
Singleton................................................ 412
sites dinmicos ...................................... 351
Smalltalk.................................................... 7
Sobrecarga............................................... 18
Sobrescrita............................................... 18
Stack................................................... 137
static .................................................. 74
Stored Procedures.................................. 342
String....................................................... 33
StringBuffer.................................... 79
Strings..................................................... 39
StringTokenizer........................... 152
super..................................................... 73
Superclasse.............................................. 12
switch .................................................. 55
synchronized.................................... 78
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
2
T
TextArea ....................................178, 205
TextField..................................178, 204
this........................................................82
Tipos de dados........................................35
toString()..................................................42
Transao...............................................337
Tratamento de Eventos...........................168
U
UML.........................................................20
Unicode................................................... 29
Unidade de Compilao.......................... 67
V
Vector ................................................ 134
Visibilidade............................................. 22
void ....................................................... 69
W
while..................................................... 57
widgets................................................... 165
J ava na Prtica
Alcione de P. Oliveira, Vincius V. Maciel - UFV
1

Você também pode gostar