Programac~ao em Java
TM
Alexandre Oliva
http://www.dcc.unicamp.br/ oliva
Instituto de Computaca~o
Universidade Estadual de Campinas
II Simposio Brasileiro de
Linguagens de Programac~ao
Campinas, 3 a 5 de setembro de 1997
Introduc~ao
1
1 Introduc~ao
'
$
Este mini-curso, dada a sua brevidade, n~ao tem a pretens~ao de fazer um estudo extenso e
muito menos completo da linguagem de programac~ao Java. O seu proposito e dar uma vis~ao
em largura dos varios elementos de Java, que a tornam uma linguagem de grande impacto
no contexto atual.
Conteudo
Motivac~ao
Conceitos Basicos
Exemplos
Orientac~ao a Objetos
Excec~oes
Concorr^encia e Sincronizac~ao
Biblioteca Padr~ao
Conclus~oes
&
2 Conteudo
%
Inicialmente, alguns dos objetivos almejados pelos projetistas de Java1 s~ao apresentados,
citando algumas das vantagens e desvantagens atuais da utilizac~ao de Java.
Algumas concepc~oes basicas de Java s~ao introduzidas, tais como o modelo de maquina
virtual, coleta de lixo assncrona e processamento concorrente. As diferencas entre aplicac~oes
e applets s~ao citadas, especialmente em termos de seguranca.
Seguem-se alguns exemplos de programas simples em Java, mostrando estruturas de
controle, alguns tipos basicos e o uso de operadores em express~oes.
Entrando no contexto de orientac~ao a objetos[?, ?], denem-se objetos, classes, interfaces,
pacotes, heranca e controle de visibilidade. S~ao apresentados diversos modicadores de
declarac~oes e alguns metodos de propositos especiais.
Topicos relativos a tratamento de excec~oes, multiplos uxos de execuc~ao e primitivas de
sincronizac~ao s~ao abordados em seguida. Alguns dos pacotes padr~ao de Java s~ao apresentados.
1 Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Motivac~ao
'
$
2
Finalmente, listam-se alguns dos elementos de outras linguagens que n~ao est~ao presentes
em Java, e s~ao citadas algumas das tend^encias futuras da linguagem.
Motivac~ao
Pros
{ Portabilidade
{ Familiaridade
{ Simplicidade
{ Distribuic~ao
{ Seguranca
Contras
{ Desempenho
{ Engenharia reversa
{ Falta de ferramentas
{ Instabilidade
{ (In)seguranca
&
3 Motivac~ao
%
Java foi criada com a principal intenc~ao de prover uma plataforma homog^enea, independente
do sistema operacional ou processador em que fosse executada. Desse fato vem uma de suas
maiores vantagens: um programa em Java pode ser compilado apenas uma vez e executado
em qualquer implementac~ao da plataforma Java.
Outra vantagem de Java e a similaridade com outras linguagens bastante difundidas.
A semelhanca sintatica com C[?] e C++[?, ?] e obvia, enquanto o modelo de objetos e de
execuc~ao foram baseados em Smalltalk[?] e Simula 67[?]. Isso faz com que uma pessoa ja
familiarizada com qualquer uma delas tenha maior facilidade e rapidez para aprender Java.
Sua especicac~ao, tanto da linguagem de programac~ao quanto do interpretador, e bastante simples, se comparada, por exemplo, com C++ ou Ada[?]. Por outro lado, sua biblioteca,
bastante poderosa, oferece recursos para programac~ao distribuda e concorrente, nos moldes exigidos por aplicac~oes voltadas a Internet, sem deixar de lado requisitos basicos como
interface graca ou mecanismos de entrada e sada.
Java dene um modelo de seguranca que impede que programas trazidos da rede (applets) executem operac~oes que possam comprometer a integridade do sistema em que s~ao
executados, ou ate mesmo que tenham acesso a informac~oes ou servicos locais. Tais operac~oes pode ser habilitadas seletivamente, com base na proced^encia e/ou em assinaturas que
acompanhem o applet.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Motivac~ao
3
Um dos principais motivos que levam as pessoas a n~ao utilizar Java e a crenca de que,
por ser interpretada, ela se torne mais lenta. Embora seja bastante sensvel a lentid~ao de
certas aplicac~oes Java, se comparadas com similares desenvolvidas em outras linguagens,
ha defensores da teoria de que, com o tempo, surgir~ao implementaco~es mais ecientes. Um
recurso extremo e a traduc~ao o-line de codigo Java para C ou diretamente para arquivos
objeto, transformando uma aplicac~ao Java num programa executavel. Perde-se a portabilidade, mas pode-se ganhar em eci^encia. Outra forma de aumentar o desempenho de
plataformas Java e atraves de compiladores sob demanda (just-in-time compilers), capazes
de traduzir Java pre-compilado (byte-codes) para codigo nativo da plataforma alvo, eliminando assim o impacto da interpretac~ao. Ja hoje em dia ha interpretadores que alcancam
desempenho semelhante a programas equivalentes escritos em C. Espera-se que a diferenca
se reduza ainda mais com o passar do tempo.
Outro fato que preocupa desenvolvedores de software em Java e a facilidade com que
seus byte-codes s~ao traduzidos para programas Java perfeitamente legveis. Exceto pela falta de comentarios, um executavel Java pode carregar praticamente tanta informac~ao quanto
o programa fonte: nomes de classes, metodos, atributos, ate mesmo nomes de variaveis e
numeros de linhas podem estar presentes no codigo, e apenas estes dois ultimos itens podem ser removidos sem prejuzo para a execuc~ao do sistema. Ha ate mesmo decompiladores
distribudos livremente circulando pela rede, capazes de produzirem codigo fonte surpreendentemente legvel. Os advogados vibram!
Outros aspectos que contam pontos negativos da plataforma Java s~ao o pequeno numero
de ferramentas disponveis para desenvolvimento de aplicac~oes e applets e a relativa instabilidade das APIs (bibliotecas). Ambos os aspectos s~ao frutos do pouco tempo que Java teve
para orescer. Mesmo assim, ja ha exemplos de grandes aplicac~oes desenvolvidas em Java,
tais como processadores de texto, planilhas de calculo, www browsers e servers, ambientes
de desenvolvimento tanto de aplicac~oes quanto de projeto de interfaces gracas.
Outro fator julgado desfavoravel a tecnologia Java s~ao as implementac~oes de seu modelo
de seguranca. Algumas delas s~ao excessivamente restritivas, enquanto outras apresentam
defeitos que permitem a violac~ao da poltica de seguranca. Enquanto usuarios julgam-se
seguros no que diz respeito a ac~ao de applets mal-intencionados, na realidade podem estar
sendo expostos em func~ao de erros na implementac~ao do modelo de seguranca.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
Conceitos Basicos
Conceitos Basicos
$
4
Maquina Virtual (JVM)
Compilac~ao Interpretac~ao
Byte-codes
Somador.java
class Somador f
int soma(int x, int y)
f return x + y; g
g
&
I1:
I2:
I3:
I4:
I1
;;!
iload 1
iload 2
iadd
ireturn
x
4 Conceitos Basicos
Argumentos
1 x
2 y
x I3 x+y I4 *
;;! y ;;!
;;! x+y
I2
%
O nome Java vai alem de apenas uma linguagem de programac~ao. Para executar programas Java e necessario um interpretador capaz de compreender as instruc~oes Java e efetuar
as ac~oes correspondentes. Esse interpretador e denominado a maquina virtual de Java,
normalmente denotado simplesmente JVM.
Apesar de Java ser uma linguagem interpretada, a maquina virtual n~ao precisa do codigo
fonte para executar um programa. E necessaria uma compilac~ao previa, que traduz programas fontes em Java para byte-codes, que s~ao compreendidos pela maquina virtual.
Esses byte-codes s~ao uma representaca~o compacta de uma especie de linguagem assembly de uma arquitetura orientada a pilha[?] | assim como Postscript, e tambem a notac~ao
RPN das calculadoras HP. Praticamente todas os elementos sintaticos da linguagem Java
t^em traduc~ao direta para instruc~oes dessa maquina. Mesmo assim, grande parte das instruc~oes s~ao muito simples: ha algumas que apenas empilham um valor | seja ele constante
ou o conteudo de uma variavel, um argumento ou um atributo de um objeto ou de uma
classe. Outras desempilham alguns elementos, efetuam uma operac~ao entre eles e nalmente
empilham o resultado.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
$
Conceitos Basicos
5
Conceitos Basicos
Carga din^amica de codigo
Concorr^encia
Pilha de Execuc~ao
Coleta de Lixo
Modelo de Objetos
Aplicac~oes Applets
&
%
Java foi projetada para permitir que seus programas n~ao fossem monolticos: cada classe
e armazenada de maneira independente, e pode ser carregada pela maquina virtual apenas
quando for utilizada. Java tem um mecanismo padr~ao para buscar classes, procurandoas em diretorios especicados numa variavel de ambiente chamada CLASSPATH. E possvel
tambem a um programa Java criar novas maneiras de procurar classes, ou ate mesmo de
gera-las dinamicamente. Para isso, basta especializar a classe ClassLoader.
A maquina virtual Java permite multiplas linhas de execuc~ao (threads)[?] num mesmo
programa e oferece primitivas para sincronizac~ao entre elas. No entanto, n~ao ha garantia de
troca de contexto automatica: todas as threads devem tomar, regularmente, o cuidado de
permitir que outra thread tome o controle.
O modelo de execuc~ao de Java, do ponto de vista de uma thread, e id^entico a outras
linguagens orientadas a objeto procedurais. Cada thread tem uma pilha propria, em que
s~ao guardados os contextos das chamadas de metodos n~ao encerradas. Quando uma nova
chamada e feita, um novo quadro (frame) da pilha e utilizado para guardar os argumentos
e as variaveis locais do metodo chamado, enquanto o quadro anterior se torna inacessvel.
Quando o metodo termina sua execuc~ao, seja por vias normais ou excepcionais, o quadro e
liberado, e o metodo que o chamou retoma o controle.
Um dos pontos fortes de Java e livrar o programador do peso de cuidar da desalocac~ao
de objetos n~ao mais necessarios. Utilizando algoritmos que detectam objetos ou conjuntos
de objetos inatingveis a partir de qualquer das linhas de execuc~ao ou de outros objetos,
uma linha de execuc~ao paralela procura liberar a memoria por eles ocupada. Mesmo que
haja refer^encias cruzadas entre objetos, se nenhum dos objetos de um ciclo for referenciavel
por outros, eles s~ao todos candidatos a desalocaca~o. Antes de ser desalocado, um objeto
e noticado de que e candidato a desalocac~ao, podendo tomar provid^encias de limpeza
ou desalocac~ao de outros recursos. Se, com isso, ele novamente se tornar alcancavel, sua
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Conceitos Basicos
6
destruic~ao sera adiada ate que ele eventualmente que inatingvel.
A coleta de lixo e facilitada pelo fato de Java n~ao permitir aritmetica com apontadores
| o que tambem e uma fonte de erros comum em outras linguagens. Nominalmente, Java
nem mesmo possui apontadores, porem as refer^encias, em Java, desempenham o papel dos
apontadores de linguagens como C, C++ e Pascal.
Outro fator que facilita a coleta de lixo e que objetos jamais s~ao alocados nas pilhas de
execuc~ao: a regi~ao em que s~ao alocados e chamada heap. Alem disso, objetos nunca s~ao
agregados contendo outros objetos: podem conter apenas tipos basicos e refer^encias para
outros objetos.
Java permite heranca multipla de interfaces, porem apenas heranca simples de implementac~ao. Permite ainda que a visibilidade de metodos e atributos seja controlada em
quatro nveis diferentes: irrestrita, restrita a subclasses, restrita ao pacote de classes ou restrita apenas a propria classe. O controle de visibilidade e garantido tanto pelo compilador
quanto pelo interpretador, de modo que e impossvel burla-lo.
Java oferece um sistema de tipos forte, conhecidos em tempo de compilac~ao, porem
prov^e mecanismos para criar e manipular objetos de tipos previamente desconhecidos. A
compatibilidade de tipos tambem e vericada tanto em tempo de compilac~ao quanto de
execuc~ao.
Todas essas vericac~oes em tempo de execuca~o podem comprometer o desempenho de
um programa. Por isso, nem sempre e conveniente que elas sejam efetuadas. Por exemplo,
se ha conanca de que o programa a ser executado n~ao tentara efetuar operaco~es ilegais,
pode-se executa-lo sem perder tempo fazendo certas vericaco~es. Ja um programa carregado
da rede, sem qualquer forma de identicaca~o, n~ao e conavel, e portanto deve ser validado
para evitar a entrada de vrus, a invas~ao de privacidade ou ate mesmo a destruica~o de
informac~oes locais.
Um programa executado localmente, iniciado com a invocaca~o de um interpretador Java, e chamado aplicac~ao Java. Um programa Java executado por um navegador (browser),
por ordem de um comando contido numa pagina HTML, e chamado applet. Aplicac~oes s~ao
supostamente conaveis, e por isso n~ao est~ao sujeitas a qualquer restrica~o de acesso n~ao
imposta pelo sistema operacional subjacente. Ja applets s~ao supostos hostis, e executados
dentro de uma chamada caixa de areia (sandbox), dentro da qual n~ao podem fazer acesso a
arquivos locais, e so podem se comunicar com o servidor de onde foram carregados. Ha mecanismos especicados para permitir que applets efetuem operac~oes privilegiadas, baseadas
em autorizac~oes individuais por parte de usuarios e/ou na validac~ao de assinaturas digitais
includas nos applets, porem as implementac~oes desses modelos ainda s~ao escassas e sujeitas
a erros.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
$
Conceitos Basicos
Tipo
byte
short
int
long
float
double
boolean
char
Tipos pre-denidos
Denic~ao
inteiro, 8 bits, complemento de 2
inteiro, 16 bits, complemento de 2
inteiro, 32 bits, complemento de 2
inteiro, 64 bits, complemento de 2
ponto utuante, 32 bits, IEEE 754
ponto utuante, 64 bits, IEEE 754
true ou false
caractere Unicode, 16 bits, sem sinal
Sequ^encias Unicode:
&
7
\u0063\u006c\u0061\u0073\u0073
4.1 Tipos pre-denidos
class
%
Todos os tipos de Java t^em uma representac~ao xa, indendente da plataforma sobre a qual
s~ao implementados. Mesmo que a plataforma opte por utilizar uma representac~ao diferente,
o comportamento deve ser exatamente equivalente ao esperado de uma implementac~ao que
utilizasse a representac~ao indicada.
Todos os tipos inteiros t^em sinal, e s~ao representados em complemento de 2. Os numeros
de ponto utuante devem seguir a risca a especicaca~o IEEE 754. Booleanos podem ser
somente verdadeiros ou falsos. Caracteres, em Java, s~ao Unicode, um superconjunto de
ASCII que permite a representac~ao de caracteres em multiplas lnguas. O tipo caractere e
tambem considerado um tipo inteiro, e e o unico inteiro sem sinal.
A proposito, um programa em Java pode conter caracteres n~ao-ASCII. Eles podem ser
especicados utilizando a notac~ao \uXXXX, onde XXXX e o codigo hexadecimal a ele associado,
necessariamente com 4 dgitos. Em qualquer lugar em que letras s~ao aceitas, por exemplo, em
nomes de identicadores, caracteres Unicode correspondentes a letras s~ao tambem aceitos.
Em lugares onde numeros s~ao esperados, caracteres Unicode correspondentes a numeros
podem ser utilizados.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Operadores
'
Tipo
pos-xos
unarios
criac~ao/cast
multiplicativos
aditivos
deslocamentos
relacionais
igualdade
E binario
OU exclusivo
OU binario
E logico
OU logico
selec~ao
atribuic~ao
&
5 Operadores
Operadores
$
8
Operadores
A[i] o.a m(. . . ) e++ e;;
++e ;;e +e ;e e !e
new (T)e
/ %
+ ;
<< >> >>>
< > >= <= instanceof
== !=
&
^
j
&&
jj
e?e:e
= op= (exceto logicos)
%
Na tabela acima, os operadores s~ao apresentados em ordem decrescente de preced^encia.
Operadores pos-xos s~ao para indexar arrays, referenciar metodos, atributos e classes
internos a outras classes, invocar metodos e incrementar ou decrementar o valor de uma
variavel, obtendo o valor antigo.
Operadores unarios fazem incremento e decremento de uma variavel, obtendo seu novo
valor, mant^em ou trocam o sinal de valores numericos e fazem negac~ao booleana ou logica.
O operador de alocac~ao de objetos e o de convers~ao de tipos t^em a mesma preced^encia.
Operadores aritmeticos t^em a preced^encia normal: multiplicac~ao, divis~ao e resto da divis~ao
t^em preced^encia maior que adic~ao e subtraca~o.
O operador de deslocamento para a esquerda move os bits de um inteiro para a esquerda,
preenchendo os bits menos signicativos com zeros. O operador de deslocamento para a
direita com sinal preenche os bits mais signicativos com o bit de sinal, enquanto o operador
de deslocamento para a direita sem sinal os preenche com zeros.
Operadores relacionais comparam tipos numericos; instanceof verica se o objeto pertence a uma classe ou n~ao. Igualdade ou desigualdade entre numeros ou entre refer^encias
pode ser vericada com os operadores de igualdade.
Em seguida, na ordem de preced^encia, v^em os operadores binarios: que fazem disjunc~ao,
ou exclusivo e ou inclusivo bit a bit: funcionam para valores inteiros e booleanos. Os
operadores logicos, por outro lado, so aceitam valores booleanos, e so avaliam a segunda
express~ao se necessario. O operador de selec~ao avalia a primeira express~ao, que deve ser
booleana. Dependendo do resultado, verdadeiro ou falso, a segunda ou a terceira express~ao
sera avaliada.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Comandos de Controle
'
$
9
Alem do operador de atribuic~ao direta, pode-se preceder o sinal de igual com qualquer
operador aritmetico, de deslocamento ou binario. O efeito de e1 op= e2 e o mesmo que de
e1 = e1 op e2.
Comandos de Controle
if (expr booleana) comando 1;
else comando 2;
while(expr booleana) comando;
do comando while (expr booleana);
switch (expr) f
case valor 1: comando 1;
case valor 2: comando 2;
break;
default: comando default;
g
rotulo:
for (comando inicial; expr booleana;
expr controle) f
comando;
if (cond) break rotulo; else continue;
&
g
6 Comandos de Controle
%
As construc~oes de controle de Java s~ao bastante semelhantes as de C++. Comandos como
if/else, while, do/while, switch/case e for s~
ao id^enticos. Falta a Java o comando goto
mas, para suprir essa falta, os comandos break e continue podem (ou n~ao) ser seguidos do
nome de um rotulo que indique a qual estrutura de controle se referem.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Exemplos
'
$
10
Exemplos
Um primeiro exemplo:
HelloWorld.java
public class HelloWorld f
public static void main(String[ ] argv) f
g
g
System.out.println("Hello
World!");
Testando-o:
oliva% javac HelloWorld.java
oliva% java HelloWorld
Hello World!
&
7 Exemplos
%
Este e certamente o programa Java mais conhecido do mundo. Nele, mostra-se a estrutura
minimal de um programa Java tipo aplicac~ao.
Escolhido o nome da aplicac~ao, deve-se criar um arquivo com esse mesmo nome, dentro
do qual se dene uma classe publica com nome igual ao nome do arquivo.
Para que essa classe possa iniciar uma aplicac~ao, ela deve oferecer um metodo estatico
e publico chamado main, que n~ao retorna valor algum (void), mas recebe como unico
argumento um array de Strings, obtidos a partir da linha de comando. Na declarac~ao
do array, os colchetes podem aparecer tanto antes quanto depois do nome da variavel, e seu
tamanho n~ao precisa ser especicado.
Na classe System (na realidade, seu nome completo e java.lang.System), uma classe
pre-denida de Java, existe um atributo publico da classe chamado out, que corresponde a
sada padr~ao do programa. O metodo println escreve a String fornecida como argumento
no dispositivo associado a sada padr~ao.
N~ao havendo mais nenhuma instruc~ao no metodo main, o programa termina.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Exemplos
'
Exemplos
$
11
Um programa que imprime seus argumentos, um
por linha:
Argumentos.java
= Este programa imprime seus argumentos,
um por linha.
@author Alexandre Oliva =
public class Argumentos f
= Escreve um argumento em cada linha.
@param argv argumentos. =
public static void main(String[ ] argv) f
for(int i = 0; i < argv.length; ++i)
g
g
System.out.println(argv[i]);
Resultado da execuc~ao:
&
oliva% java Argumentos 1 2
1
2
%
Um aspecto interessante de Java e a possibilidade de extrair documentac~ao a partir dos
programas fonte. Comentarios iniciados por uma barra e dois asteriscos, como os do trecho
de codigo acima, s~ao reconhecidos pelo programa javadoc, distribudo juntamente com o
Java Development Kit, e utilizados para gerar documentaca~o no formato HTML.
Este programa exibe os argumentos a ele passados atraves da linha de comando na
sada padr~ao, um em cada linha. Observe o laco for: assim como em C++, o primeiro
comando e a inicializac~ao do laco e pode ser uma declarac~ao, sendo que nesse caso o escopo
da variavel ali declarada vai ate o m do laco. O segundo item deve ser uma express~ao
booleana que controle as iterac~oes. No exemplo, compara-se o valor do contador com o
numero de elementos do array | que s~ao numerados a partir de zero, raz~ao pela qual
o numero de elementos e sempre maior que qualquer ndice valido. O terceiro item e um
comando qualquer, normalmente utilizado para ns de controle do laco, como o incremento
de contadores. Esse comando e executado apos a execuc~ao do corpo do comando.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Exemplos
'
Exemplos
$
12
Este programa escreve na sada padr~ao tudo que
l^e da entrada padr~ao:
Papagaio.java
import java.io.BueredReader;
import java.io.InputStreamReader;
public class Papagaio f
public static void main(String[ ] argv)
throws java.io.IOException f
&
g
g
String s;
BueredReader in =
new BueredReader(
new InputStreamReader(
System.in));
while ((s = in.readLine()) != null)
System.out.println(s);
%
No incio do programa, importam-se duas classes da biblioteca de entrada e sada de
Java, que ser~ao utilizadas ao longo do programa. N~ao e necessario importar uma classe,
mas, importando-a, pode-se referir a ela sem necessidade de utilizar seu nome completo,
como se fez com a classe java.io.IOException.
A classe que implementa a entrada padr~ao n~ao oferece um metodo para ler uma linha
inteira, so e possvel ler bytes. Felizmente, Java oferece outras classes de entrada e sada mais
poderosas, que podem ser acopladas umas as outras. Assim, ligamos a entrada padr~ao a uma
inst^ancia de InputStreamReader, que traduz bytes na representac~ao local do computador
(ou em qualquer outra representac~ao internacionalizada) para caracteres Unicode, utilizados
internamente em Java. Esse InputStreamReader e ent~ao atrelado a um BufferedReader,
que oferece um metodo que l^e linhas inteiras e as devolve na forma de Strings.
Finalmente, inicia-se um laco que tenta ler uma String e, caso seja bem-sucedido,
escreve-a na entrada padr~ao. Quando se chegar ao m da entrada padr~ao, sera devolvida uma refer^encia null, ao inves de uma String.
Caso ocorra algum erro de entrada e sada durante a leitura da linha, o metodo readLine
lancara ou propagara uma exceca~o do tipo IOException. Como n~ao se toma nenhuma
provid^encia para capturar esse tipo de exceca~o no metodo main, a declarac~ao indicando que
ele pode propagar ou lancar uma excec~ao desse tipo e necessaria.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
$
Orientac~ao a Objetos
13
Orientac~ao a Objetos
Objeto
{ Estado interno (atributos)
{ Operac~oes (metodos)
Classe
Interface
Implementac~ao
Encapsulamento
Heranca
Especializac~ao
&
8 Orientac~ao a Objetos
%
Um objeto e uma entidade abstrata que, em geral, representa um conceito concreto do
mundo real. Objetos possuem estados internos, representados por campos ou atributos.
Alem disso, um objeto oferece um conjunto de operac~oes que comp~oem a sua interface.
Conjuntos de objetos que se comportam de maneira semelhante, isto e, oferecem a mesma
interface, podem ser agrupados numa classe, que pode ser considerada como uma forma
que molda a composic~ao interna e o conjunto de operac~oes de um objeto. Uma classe
pode tambem denir a implementac~ao de seus objetos, caracterizada pela maneira como as
operac~oes s~ao efetuadas, o modo como elas afetam o estado interno do objeto e ate mesmo
a maneira pela qual o estado interno e armazenado.
Tr^es requisitos basicos para que uma linguagem seja considerada orientada a objetos s~ao
a possibilidade de encapsulamento, o mecanismo de heranca e a possibilidade de especializac~ao.
Encapsulamento e a possibilidade de uma classe impedir que outros objetos observem ou
alterem o estado interno de seus objetos. E uma maneira de evitar que se criem depend^encias
externas sobre mecanismos internos: oferece-se um conjunto de operaco~es basicas, cuja
implementac~ao n~ao diz respeito a quem as utiliza. Dessa forma, pode-se decidir alterar
a maneira de representar um objeto internamente, sem para isso ter de alterar todos os
usuarios do objeto.
Outro requisito fundamental para orientac~ao a objetos e a possibilidade de heranca.
Diz-se que uma classe herda propriedades de outra, ou estende a outra, se todas as suas
inst^ancias (objetos membros da classe) s~ao tambem inst^ancias da outra. Diz-se ent~ao que a
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Orientac~ao a Objetos
14
classe herdada e a mais geral, chamada classe base ou superclasse, enquanto a que herda e
a mais especca, chamada classe derivada ou subclasse.
Ha dois tipos de heranca: de interface e de implementac~ao. Herdar uma interface signica assumir o compromisso de oferecer as operac~oes denidas na interface. Ja herdar a
implementac~ao signica que inst^ancias da classe especializada ter~ao parte de seus estados denidos e controlados pela classe mais geral mas, em compensac~ao, as operaco~es denidas na
classe mais geral tambem se aplicam a classe especializada, o que permite reaproveitamento
de codigo.
Em alguns casos, apesar de uma classe base denir a implementac~ao de uma certa
operac~ao, convem a classe derivada especializar ou ate mesmo redenir essa operaca~o. E
importante que, ate mesmo para clientes desse objeto que o utilizem como inst^ancia da classe
base, quando for solicitada uma operac~ao especializada, esta deve ser executada conforme
especicada na classe mais derivada.
'
$
Orientac~ao a Objetos
Conta.java
public abstract class Conta f
static private int proxNum = 1;
nal public int numero = proxNum++;
nal protected String titular;
private long saldo = 0; == em centavos
public Conta(String titular)
f this.titular = titular; g
public long Saldo() f return saldo; g
public void Lanca(long valor)
throws SemSaldo
f Autoriza(valor); saldo += valor; g
public abstract void Autoriza
(long valor) throws SemSaldo;
g
&
%
Para iniciar a apresentac~ao dos recursos de orientac~ao a objetos em Java, vamos utilizar
uma classe bastante simples. Ela oferece um modelo simplista de comportamento de uma
conta bancaria. Cada conta tem um numero, um titular e um saldo. Contas s~ao numeradas
segundo um contador global (proxNum), compartilhado por todas as inst^ancias da classe.
Sempre que for criada uma nova conta, ela recebera o numero armazenado nesse contador
global, e esse contador sera em seguida incrementado.
O saldo de uma conta recem-aberta e iniciado com zero. O titular da conta deve ser
informado da invocac~ao do construtor de objetos, que e um metodo com o mesmo nome que
a classe, mas sem especicac~ao de tipo de valor de retorno. O qualicador this pode ser
utilizado para diferenciar uma variavel local ou argumento de um atributo da classe, como
se faz no construtor.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Orientac~ao a Objetos
15
Oferece-se um metodo publico para a obtenc~ao do saldo da conta (Saldo), ja que o
atributo saldo e privado, ou seja, so a propria classe pode fazer refer^encia a ele. Isso e
desejavel porque poder-se-ia decidir alterar a maneira de armazenar o saldo, e, se outras
classes zessem refer^encia direta ao atributo, teriam de ser alteradas. Separando a interface
da implementac~ao, ganha-se em termos de manutenca~o do codigo.
O titular da conta e declarado protected. Isso signica que apenas a propria classe
e suas subclasses podem fazer refer^encia direta a esse atributo. (Na realidade, qualquer
classe no mesmo pacote tambem pode fazer refer^encia a ele, mas discutiremos pacotes mais
adiante.)
A classe oferece uma operac~ao (Lanca) que corresponde a deposito ou debito da conta:
caso a operac~ao seja bem-sucedida, o valor fornecido sera adicionado ao saldo atual. Antes
disso, porem, efetua-se uma operac~ao (Autoriza) para conrmar a autorizac~ao de credito
ou debito. Essa autorizac~ao dependera do tipo de conta, portanto, esse metodo e declarado
abstrato, o que torna a classe tambem abstrata. Isso signica que a classe n~ao pode ser
instanciada diretamente: e necessario que sejam criadas subclasses (classes derivadas) que
implementem o metodo abstrato. Apenas essas classes derivadas poder~ao ser instanciadas.
Alguns dos campos s~ao declarados final e por isso, uma vez inicializados, permanecem
com valor constante ate o nal da execuc~ao. Anal, n~ao seria natural alterar o numero de
uma conta ou seu titular. Cabe aqui chamar a atenc~ao para o fato de que o atributo titular
e apenas uma refer^encia para uma String e que, se a String pudesse ser alterada, seria
possvel mudar o nome do titular. Como em Java Strings s~ao imutaveis, o fato de a conta
ter uma associac~ao permanente com um objeto String garante que a conta tera sempre o
mesmo titular.
'
Orientac~ao a Objetos
$
Poupanca.java
import java.util.Calendar;
public class Poupanca extends Conta f
private int aniv;
public int Aniv() f return aniv; g
public Poupanca(String titular, int aniv)
f super(titular); this.aniv = aniv; g
public Poupanca(String titular) f
this(titular, Calendar.getInstance()
.get(Calendar.DAY OF MONTH));
g
public void Autoriza(long valor)
throws SemSaldo f
if (Saldo() + valor < 0)
throw new SemSaldo();
g
&
g
%
Uma caderneta de poupanca acrescenta a uma conta bancaria apenas o fato de possuir
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Orientac~ao a Objetos
16
um dia de aniversario. Assim como qualquer outra conta, ela possui um titular, um numero
de conta e um saldo, e oferece operac~oes para obter saldo e para efetuar lancamentos. A
clausula extends e responsavel pela inclus~ao desses campos e operac~oes nessa classe, pois
essa palavra reservada indica heranca de implementaca~o em Java.
A classe Poupanca possui dois construtores. Num deles, escolhe-se o dia do aniversario
da conta. No outro, o dia atual e utilizado. Observe como o primeiro construtor chama
super(titular): nesse momento, ele est
a solicitando ao construtor da superclasse que
faca sua inicializac~ao. Se ele n~ao o zesse, seria implicitamente gerada uma chamada ao
construtor da superclasse sem nenhum par^ametro. Como n~ao ha construtor sem par^ametros
na classe base, a compilac~ao falharia.
Observe, por outro lado, que o segundo construtor, ao inves de chamar um construtor
da superclasse, chama outro construtor da propria classe a que ele pertence, fornecendo
uma lista diferente de argumentos. Essa sintaxe e util para prover valores default para
determinados argumentos.
Na implementac~ao oferecida ao Autoriza, caso o saldo se torne negativo devido a execuc~ao da operac~ao, esta ultima e rejeitada, lancando uma excec~ao.
$
'
Orientac~ao a Objetos
ContaCorrente.java
public abstract class ContaCorrente
extends Conta f
protected static long total = 0;
public ContaCorrente(String titular)
f super(titular); g
public void Lanca(long valor)
throws SemSaldo f
super.Lanca(valor);
total += valor;
g
public void nalize()
throws SemSaldo
f Lanca(-Saldo()); g
&
g
%
Esta classe apenas cuida de totalizar os valores em todas as contas que sejam inst^ancias
de suas subclasses. Isso e feito especializando o metodo Lanca: apos o lancamento ser
efetuado, o valor que foi somado ao saldo e somado ao total.
E importante notar que, como o metodo Autoriza n~ao foi implementado, essa classe
tem de ser declarada abstrata.
O metodo finalize e um metodo invocado pelo coletor de lixo de Java, imediatamente
antes de destruir um objeto. A maior parte dos objetos n~ao implementa esse metodo, mas,
se for necessario tomar alguma aca~o especial quando o objeto for deixar de existir, essa e
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Orientac~ao a Objetos
'
$
17
a ultima chance. Excec~oes lancadas por esse metodo s~ao ignoradas, porem, se a operac~ao
para zerar o saldo for rejeitada, o total n~ao sera corrigido.
Orientac~ao a Objetos
ContaComLimite.java
public class ContaComLimite
extends ContaCorrente f
private long limite = 0;
public long Limite() f return limite; g
public void Limite(long limite)
f this.limite = limite; g
public ContaComLimite
(String titular, long limite)
f super(titular); Limite(limite); g
public void Autoriza(long valor)
throws SemSaldo f
if (Saldo() + valor + limite < 0)
throw new SemSaldo();
g
g
&
%
Esta classe e uma extens~ao de ContaCorrente que permite que se estabeleca um limite
de credito para as contas. Qualquer debito sera autorizado a n~ao ser que o saldo resultante,
somado ao limite, seja um valor negativo.
S~ao oferecidas operaco~es para obter e alterar o limite da conta. Ambas t^em o mesmo
nome e s~ao diferenciadas pelo numero e tipo dos par^ametros. A isso chama-se sobrecarga de
metodos (overloading). Pode-se diferenciar metodos pelos tipos dos argumentos, mas n~ao
pelo tipo do valor de retorno. Um metodo so especializa outro denido numa superclasse
se tiver o mesmo numero de argumentos e os tipos dos argumentos forem os mesmos para
ambos. Caso contrario, o metodo e sobrecarregado, como mostra o proximo exemplo.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
Orientac~ao a Objetos
Orientac~ao a Objetos
Especializa.java
class baseEspecializa f
private void m1() fg
protected void m2() fg
nal public void m3() f
m1(); == sempre baseEspecializa.m1()
g
public void m4() fg
g
nal public class Especializa
extends baseEspecializa f
public void m1() fg
private void m2() fg == erro
public void m3() fg == erro
public void m3(int i) fg == ok
public int m4() f return 1; g == erro
g
&
$
18
%
Metodos privados n~ao s~ao especializaveis, logo, mesmo que uma classe derivada declare
um metodo com a mesma assinatura (nome e tipos dos argumentos), a classe base sempre
chamara o metodo privado que ela propria declarou.
E proibido restringir a visibilidade de um metodo. Se a classe base declara o metodo
como protegido, por exemplo, a derivada n~ao pode faz^e-lo ser privado. Por outro lado, a visibilidade pode ser aumentada: se m2 fosse declarado public em Especializa, a declarac~ao
estaria correta.
Quando um metodo e declarado final, ele n~ao pode ser especializado, por isso, a declarac~ao de m3 e invalida. No entanto, e permitido sobrecarrega-lo.
N~ao se pode alterar o tipo de valor de retorno de um metodo especializado. Nesse caso,
nem mesmo sobrecarga ocorre, ja que a sobrecarga so se faz pelos tipos dos argumentos,
nunca pelo tipo do resultado. No caso do metodo m4, ocorre um erro de compilac~ao.
Observe que a classe Especializa e declarada final. Isso signica que todos os seus
metodos s~ao implicitamente declarados nais, e que nenhuma outra classe pode estend^e-la.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
$
Orientac~ao a Objetos
19
Orientac~ao a Objetos
Transacao.java
public abstract interface Transacao
= extends I1, I2, I3, ... =
f
public nal static int DEPOSITO = 1;
public static int SAQUE = 2;
int TRANSFERENCIA = 3;
public abstract int Tipo();
public void Efetua()
throws SemSaldo;
void Estorna()
throws SemSaldo;
g
&
%
Uma interface, em Java, e um tipo especial de classe abstrata que apenas especica
um conjunto de operac~oes que devem ser oferecidas por objetos que as implementarem.
Interfaces n~ao servem para reaproveitamento de codigo, mas sim para classicar objetos,
n~ao de acordo com sua implementac~ao, mas de acordo com seu comportamento. Alem de
metodos, uma interface pode denir constantes.
Como n~ao se pode instanciar diretamente uma interface, ela e implicitamente considerada
abstrata, portanto a palavra chave abstract em sua declarac~ao e desnecessaria, e poderia
ter sido omitida.
Todo atributo denido numa interface e implicitamente publico, nal e estatico, isto e, o
atributo e visvel globalmente, imutavel e compartilhado por todas as inst^ancias da classe.
As palavras reservadas public, final e static s~ao opcionais na declarac~ao de atributos de
uma interface.
Metodos de uma interface s~ao implicitamente publicos e abstratos, isto e, visveis globalmentes e sem implementac~ao | que deve ser fornecida pelas classes que implementarem
a interface. Da mesma forma que nos atributos, as palavras reservadas public e abstract
s~ao opcionais.
Uma interface pode estender outra interface, assim como uma classe pode estender outra
classe. No entanto, uma interface n~ao pode estender uma classe, ja que classes cont^em
implementac~ao e interfaces, n~ao. Alem disso, uma classe pode estender apenas uma outra
classe, enquanto uma interface pode estender inumeras outras interfaces, e uma classe pode
implementar inumeras interfaces. Em outras palavras, Java permite heranca multipla de
interfaces, mas apenas heranca simples de implementac~ao.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
Orientac~ao a Objetos
Orientac~ao a Objetos
Saque.java
public class Saque extends Object
implements Transacao ==, i1, i2, ...
f
nal Conta conta;
nal long valor;
public int Tipo() f return SAQUE; g
public void Efetua()
throws SemSaldo
f conta.Lanca(valor); g
public void Estorna()
throws SemSaldo
f conta.Lanca(-valor); g
public Saque(Conta conta, long valor) f
this.conta = conta;
this.valor = valor;
g
g
&
$
20
%
Para uma classe indicar que oferece uma implementac~ao de uma determinada interface,
sua declarac~ao deve conter a especicac~ao implements. Uma classe pode estender outra
classe ao mesmo tempo em que implementa uma ou mais interfaces.
Uma classe pode indicar que implementa uma interface mesmo que n~ao ofereca todos os
metodos nela declarados. Nesse caso, a classe deve ser declarada abstrata, e suas subclasses
s~ao responsaveis por prover implementaco~es para esses metodos.
Nesse exemplo, observa-se que a classe Saque estende a classe Object, uma classe padr~ao
de Java que e a raiz da hierarquia de classes. Isto e, toda classe e toda interface e, direta
ou indiretamente, derivada de Object | e o unico caso em que uma interface pode estender uma classe. Quando a clausula extends esta ausente numa declarac~ao, o compilador
implicitamente toma Object como classe base.
O metodo Tipo faz refer^encia a constante SAQUE, denida na interface Transacao. O
nome SAQUE e acessvel desse metodo sem necessidade de ser prexado do nome da classe,
pois esta denido numa classe (no caso, uma interface) base.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
Orientac~ao a Objetos
Orientac~ao a Objetos
IndPoupanca.java
import java.util.Hashtable;
import java.util.Calendar;
public abstract class IndPoupanca f
private IndPoupanca() fg
private static Hashtable
indices = new Hashtable();
static f leIndices(); g
public static void
PoeInd(Calendar data, double i)
f indices.put(data.clone(),
new Double(i)); g
public static double Ind(Calendar data)
f return ((Double)indices.get(data))
.doubleValue(); g
private static native void leIndices();
static
f System.loadLibrary("indpoup"); g
g
&
$
21
%
Todos os metodos e atributos da classe IndPoupanca s~ao estaticos e portanto podem
ser utilizados sem que haja uma inst^ancia da classe. Por decis~ao de projeto, criou-se a
classe de modo que ela n~ao pudesse ser instanciada, nem direta nem indiretamente. Por ter
sido declarada abstrata, ela n~ao pode ter inst^ancias diretas, mas ainda assim seria possvel
criar uma subclasse que permitisse instanciac~ao. Como n~ao e permitido declarar uma classe
abstrata e nal, para evitar qualquer tipo de instanciaca~o (e tambem qualquer possibilidade
de extens~ao), declarou-se um construtor privado. Se n~ao fosse declarado nenhum construtor,
Java criaria um construtor default, publico e sem nenhum argumento.
O atributo indices e inicializado quando a classe e carregada, com uma Hashtable vazia.
Essa classe oferece um mecanismo para armazenar dados para busca rapida: fornecida uma
chave, obtem-se o dado associado a ela. Para isso, todo objeto Java prov^e um metodo
hashCode. A classe Object tem uma implementa
c~ao default para esse metodo, mas, para
que esse exemplo funcione corretamente, e necessario que objetos Calendar calculem hashcodes iguais para datas iguais. Felizmente, a implementac~ao padr~ao de Calendar, chamada
GregorianCalendar, toma conta desse detalhe.
Uma desvantagem da Hashtable e que ela so trabalha com Objects. Porem, o metodo
PoeInd recebe uma data, que e um objeto, e um ndice, que n~ao e. Por isso, para armazenar
o ndice na tabela, ele precisa transforma-lo num objeto. Java oferece uma classe para cada
tipo pre-denido, que serve para encapsular valores desses tipos na forma de objetos. Assim,
ao inves de armazenar o numero do tipo double na tabela, armazena-se uma inst^ancia da
classe Double.
A Hashtable armazena refer^encias para os objetos que lhe forem fornecidos. A chave para busca na tabela, no caso do exemplo, e uma data, especicada como um objeto
Calendar. Se esse objeto for alterado ap
os a inclus~ao na tabela, ele pode n~ao ser mais
encontrado, pois o hash-code e calculado em func~ao da data e horario nele armazenados.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Orientac~ao a Objetos
22
Assim, para prevenir que quem tenha chamado o metodo modique o objeto da tabela,
armazena-se uma copia exata do objeto Calendar fornecido, obtida utilizando o metodo
clone. Todo objeto oferece um m
etodo clone, porem a implementaca~o default, oferecida
pela classe Object, verica se a classe do objeto implementa a interface Cloneable, e so
fornece uma duplicata se essa interface for implementada. Caso contrario, uma excec~ao e
lancada. A classe Calendar implementa essa interface.
Como uma Hashtable so esta preparada para lidar com objetos, seu metodo get, que
devolve o objeto associado a chave dada, devolve uma refer^encia para objeto. Sabemos,
porem, que essa refer^encia e para um objeto da classe Double, e por isso podemos utilizar
uma convers~ao de tipo (type-cast) para transforma-la numa refer^encia para o tipo apropriado, e solicitar ao objeto Double ao qual ela se refere o valor do tipo double nele armazenado.
Se, por alguma raz~ao, o objeto devolvido pelo metodo get n~ao fosse uma inst^ancia da classe
Double, uma exce
c~ao de execuc~ao seria gerada.
Iniciar uma tabela de ndices vazia toda vez que ela fosse carregada seria um desperdcio.
Ideal seria armazena-la em meio permanente, por exemplo, em disco, e ter uma maneira
de recupera-la de forma transparente. Por isso, quando a classe e carregada, executa-se o
metodo leIndices, a partir do chamado bloco de inicializaca~o estatica. Qualquer classe
pode ter um ou mais blocos como esses, que s~ao executados na ordem em que aparecem.
Observe que o metodo leIndices e declarado como um metodo nativo. Isso signica
que ele n~ao e implementado em Java, mas sim em outra linguagem de programac~ao, como
C ou C++. Sua implementac~ao deve ter sido compilada e armazenada numa biblioteca
din^amica, que e carregada pelo inicializador estatico que aparece logo em seguida.
'
Passagem de Par^ametros
$
Param.java
public class Param f
public static void main(String[ ] sa) f
boolean b = true;
String s = "Fica";
sa = new String[ ]fs,sg;
muda(b, s, sa);
System.out.println("b: "+b+
"nns: "+s+"nnsa[1]: "+sa[1]);
g
static void muda
(boolean v, Object o, Object[ ] oa) f
&
g
g
v = false;
== oa[0] = new Object();
o = oa[1] = "Muda";
== oa[2] = "";
Programac~ao em Java
%
Alexandre Oliva, IC, UNICAMP
'
$
Orientac~ao a Objetos
Passagem de Par^ametros
23
Resultado:
b:
true
s:
Fica
sa[1]:
Muda
Veja por qu^e:
b: true
sa:
s:
@
;;
@
-- ? \Fica"
- \Muda" @;;@
o:
so:
v: true
@
;;
@ false
.
&
?
[0]
[1]
6
%
Neste exemplo, mostra-se que, em Java, argumentos s~ao sempre passados por valor.
Primeiramente, cria-se uma variavel booleana com valor verdadeiro, uma refer^encia para a
String "Fica" e uma refer^
encia para um array de duas refer^encias para String, ambas
referenciando a mesma String que s. E importante ter a consci^encia de que nem s nem os
elementos de sa s~ao Strings: s~ao todos refer^encias para String.
A chamada do metodo muda, portanto, recebe um valor booleano, uma refer^encia para
um objeto e uma refer^encia para um array de (refer^encias para) objeto. Como a classe
String estende Object, a refer^
encia para String e implicitamente convertida para Object.
Da mesma forma, a refer^encia para array de String e implicitamente convertida para array
de Object. Ambas as refer^encias, para a String e para o array, s~ao passadas por valor.
O metodo muda recebe copias dos argumentos, isto e, v recebe uma copia do valor de b;
o, da refer^
encia s, devidamente convertida, e oa, da refer^encia sa, tambem convertida. Por
isso, quando se altera o valor de v, a variavel b n~ao e alterada. Quando se altera a refer^encia
o, ela passa a se referir a outra String, mas s n~
ao se altera.
Porem, quando se altera oa[1], o array esta sendo alterado. Tanto oa quanto sa fazem
refer^encia ao mesmo array, assim, sa[1] passa a fazer refer^encia para a String "Muda".
Ha dois comandos desabilitados por marcas de comentarios. Ambos seriam compilados
com sucesso, porem falhariam em tempo de execuc~ao. O primero, porque estaria armazenando, num array de Strings, uma refer^encia para um Object que n~ao e realmente uma
String. O segundo, porque estaria alterando um elemento que n~
ao pertence ao array, que so
possui dois elementos, numerados de 0 a 1. Cada um desses comandos geraria uma excec~ao
diferente. Naturalmente, se o array passado como par^ametro fosse um array de Objects
com tr^es elementos ou mais, esses comandos seriam bem-sucedidos.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
'
Orientac~ao a Objetos
Convers~ao de Tipos
Cast.java
public class Cast f
public static void main(String[ ] argv) f
String[ ][ ] saa = ff"a"g, argvg;
&
g
g
Object o = saa;
Object[ ] oa = (Object[ ])o;
Object[ ][ ] oaa = (Object[ ][ ])oa;
saa = (String[ ][ ])oaa;
oa = new Object[ ] f"b", o, nullg;
if (oa instanceof String[ ])
System.out.println(((String[ ])oa)[0]);
else System.out.println("Nao!");
if ((o=oa[0]) instanceof String)
System.out.println((String)o);
else System.out.println("Nao!");
oaa = new String[3][2][5];
oa = new Object[3][ ][ ];
$
24
%
Este exemplo pretende mostrar convers~oes automaticas e explcitas entre classes. Comeca-se criando um array de arrays de Strings. Seu primeiro elemento e um array de
apenas um elemento, enquanto o segundo e o array dos argumentos com que o programa foi
chamado. N~ao ha problema se os dois tiverem tamanhos (numero de elementos) diferentes.
Um array qualquer, assim como qualquer classe em Java, e um tipo derivado de Object
e, como convers~oes para classes base s~ao feitas implicitamente, pode-se inicializar uma refer^encia para objeto com uma refer^encia para um array qualquer.
Para fazer a convers~ao no sentido contrario, da classe base para a derivada, e necessario
usar a notac~ao de type-cast. Naturalmente, a convers~ao e vericada e, se for invalida, uma
exceca~o e lancada. No caso, como a classe do objeto referenciado por o e um array de arrays
de String, e um array de String e um Object, a convers~ao e bem-sucedida.
Prosseguindo o caminho de volta, converte-se a refer^encia para array de Object que, na
realidade, e o array de arrays de Strings, para array de arrays de Objects. Como cada
String e um Object, a convers~ao e feita com sucesso. Finalmente, converte-se a refer^encia
de volta para seu tipo original, o que naturalmente transcorre sem problemas.
Depois, cria-se um array de Objects, com o primeiro elemento sendo uma String, o
segundo sendo um Object, que na realidade e um array de arrays de Strings, e o terceiro
sendo uma refer^encia para um objeto null, isto e, inexistente. Em se tratando de arrays
de Objects, n~ao ha problemas que os arrays tenham numero de dimens~oes diferentes. De
fato, um array de Objects pode conter uma refer^encia para si proprio. Quanto a refer^encia
null, qualquer tentativa de utiliz
a-la para chamar um metodo ou fazer acesso a um atributo
causara o lancamento de uma exceca~o.
O operator instanceof e utilizado para vericar se um type-cast do objeto que o antecede para a classe que o sucede seria bem sucedido ou n~ao. No caso, como o array foi criado
como array de Objects, e n~ao de Strings, o resultado da operac~ao e falso. Mesmo que
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Orientac~ao a Objetos
25
todos os elementos do array fossem realmente Strings, a convers~ao n~ao seria possvel, pois
a classe do array e Object[ ], e n~ao String[ ]. Portanto, o programa imprime "Nao!"
Apos converter a refer^encia ao primeiro elemento de oa, que e "b", para o tipo Object,
essa refer^encia e armazenada em o, e verica-se se a convers~ao dela para String teria sucesso.
Nesse caso, a convers~ao funciona, e o programa escreve a String correspondente.
No nal, mostra-se que e possvel alocar arrays sem inicializa-los. No primeiro caso,
aloca-se um array de tr^es elementos; para cada elemento, aloca-se um array de dois elementos e, para cada um desses dois, cria-se um array de cinco refer^encias null. No segundo
caso, como faltam as dimens~oes dos ultimos dois nveis, e alocado apenas um array de tr^es
refer^encias null.
'
Classes Internas
$
Internas.java
import java.util.Observer; == interface
import java.util.Observable; == class
public class Internas f
private static char a = 'a'; int i;
static class interna1
f char a = Internas.a; g
public class interna2 f int j = i; g
Observer m(nal int[ ] oa) f
class interna3
f oat k = oa[0] + i; g
return new Observer()
f public void update
&
g
g
(Observable o, Object arg)
f ++oa[0]; g g;
%
Classes internas (inner classes) s~ao um recurso para denir classes com acesso privilegiado
a outras classes, em geral como parte de sua implementac~ao. Essas classes podem ser
denidas dentro do corpo de outra classe e ate mesmo dentro do corpo de um metodo dela.
Neste exemplo, a classe interna1, por ser membro estatico da classe que a contem, tem
acesso a todos os membros estaticos dessa classe, sejam eles publicos, protegidos ou privados.
Ja uma inst^ancia da classe interna2, por a classe n~ao ser estatica, guarda implicitamente
uma refer^encia para um objeto da classe que a contem: o objeto que a instanciou.
Classes declaradas no interior de metodos podem fazer acesso a atributos do objeto que
os criou e a variaveis locais do metodo, desde que estas sejam declaradas nais. Ha ainda
uma sintaxe para denir classes an^onimas, bastante uteis para denir callbacks especicados
atraves de interfaces, como o Observer do exemplo.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Excec~oes
'
Excec~oes
Excecoes.java
class Excecao extends Exception fg
public class Excecoes f
void m1() throws Throwable
f throw new Excecao(); g
void m2() throws Excecao
f throw new Excecao(); g
public Excecoes() f
try f m1(); m2(); g
catch (RuntimeException e) fg
catch (Error e) fg catch (Excecao e) fg
catch (Throwable e) fg
nally fg g
g
class SubExcecoes extends Excecoes f
void m1() fg
void m2() == throws Exception
fg g
&
9 Excec~oes
$
26
%
Quando um metodo levanta uma excec~ao, essa excec~ao e propagada pela pilha ate que
encontre uma clausula catch que capture excec~oes da mesma classe ou de uma classe base
da excec~ao levantada. Toda excec~ao deve ser derivada da classe Throwable e, se um metodo
pode lancar ou propagar uma exceca~o, ela deve ser declarada na clausula throws.
Ha algumas classes de excec~oes, porem, que n~ao precisam ser declaradas: Error e
RuntimeException podem ser geradas durante a opera
c~ao normal da maquina virtual, por
exemplo, numa convers~ao de tipo, num enderecamento de array, na tentativa de chamar um
metodo ou calcular um atributo de uma refer^encia nula, etc.
Para que seja possvel tratar excec~oes ocorridas durante a execuc~ao de um ou mais
comandos, esses comandos devem estar dentro de um bloco do comando try, seguido por
uma ou mais clausulas catch e opcionalmente terminado por uma clausula finally. O
bloco que segue esta clausula e executando tanto num termino normal quanto excepcional.
Quando uma classe estende metodos que declaram excec~oes, ela pode remover excec~oes
da lista ou declarar excec~oes mais especializadas, mas nunca excec~oes mais gerais. No
exemplo, m1 remove as declarac~oes, enquanto a declarac~ao de m2 seria invalida se o trecho
comentado fosse includo.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Threads
'
Threads
Threads.java
public class Threads f
public void main(String[] argv) f
nal Threads t = new Threads();
new Thread() f
public void run() f
try f Thread.sleep(15); g
catch (InterruptedException e) fg
synchronized (t) f
$
27
t.notify();
gg
g.start(); t.m();
g
synchronized void m() f
try f wait(); g
catch (InterruptedException t) fg
g
volatile int i = 0;
&
g
10 Threads
%
Java oferece a classe Thread, que permite multiplos uxos de execuc~ao concorrentes. Ao
se instanciar essa classe, e acionar seu metodo start, o metodo run da propria classe, e
acionado, numa linha de execuc~ao independente. O metodo pode ser especializado, ou a
classe pode ser inicializada com uma refer^encia para um objeto que implemente a interface
Runnable, a m de que o m
etodo run desse objeto seja executado.
Java tambem oferece primitivas de sincronizac~ao. Cada objeto tem a ele associado um
lock. Os locks s~ao reentrantes, isto e, uma mesma Thread pode adquirir um mesmo lock
inumeras vezes antes de libera-lo.
Ha duas maneiras de se adquirir um lock: declarando um metodo como synchronized
ou com um bloco com guarda synchronize. Na primeira alternativa, enquanto o metodo
estiver sendo executado, e garantido que a Thread possui o lock sobre o objeto. No caso
de metodos estaticos, o lock da propria classe (que tambem e um objeto) e adquirido. No
caso do bloco com guarda, o lock e adquirido sobre o objeto especicado na guarda, e e
mantido ate que o bloco termine. Em ambos os casos, se houver termino anormal por causa
de excec~oes, os locks s~ao liberados corretamente.
Para permitir que qualquer objeto se comporte como um monitor[?], a class Object
oferece os metodos wait e notify (entre outras variantes). Ambos so podem ser executados
em objetos sobre os quais se possuem locks. O primeiro, atomicamente, libera o lock e
espera por uma noticac~ao, que e provida pelo segundo. Ao receber a noticac~ao, o lock e
novamente adquirido | assim que a thread que gerou a noticac~ao libera-lo, e claro.
Outro recurso para facilitar a programac~ao concorrente e a possibilidade de declarar
atributos como volateis. Isso signica que o compilador e o interpretador devem evitar
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Biblioteca Padr~ao
'
$
28
otimizac~oes sobre esses atributos que pudessem alterar seu comportamento na presenca de
outras threads.
Biblioteca Padr~ao
java.lang
java.lang.reflect
java.util
java.util.zip
java.math
java.io
java.net
java.rmi
java.applet
java.awt
java.beans
&
java.security
java.sql
java.text
11 Biblioteca Padr~ao
%
Pacotes, em Java, s~ao mecanismos para agrupar classes. Todo arquivo fonte em Java pode
ter uma declaraca~o \package nome.do.pacote;", que indica a que pacote a classe pertence.
Ha uma convenc~ao para garantir nomes de pacotes e classes unicos, baseada na hierarquia
de domnios da internet. Um pacote desenvolvido na Unicamp, por exemplo, deve ter seu
nome iniciado por BR.unicamp.
Os pacotes padr~ao de Java t^em seus nomes iniciados por java. Para se utilizar uma
classe de outro pacote, ela deve ter sido declarada publica. Para se poder referir a uma
classe de outro pacote sem ter de escrever seu nome completo, deve-se importar a classe
ou todo o pacote, utilizando um comando import. Para importar o pacote todo, deve-se
escrever \import nome.do.pacote.".
O pacote java.lang n~ao precisa ser importado, todas as classes desse pacote s~ao visveis
em qualquer outro pacote, a n~ao ser que outra classe seja declarada com o mesmo nome.
Nesse pacote, residem as classes principais da plataforma Java. Desde as classes Object
e Thread, ate mecanismos para controlar o comportamento do compilador Just-in-Time,
carregar classes dinamicamente e limitar a liberdade da maquina virtual, especialmente no
caso de applets.
Juntamente com a classe java.lang.Class, o pacote java.lang.reflect oferece mecanismos para obter informac~oes a respeito de classes, assim como para criar e manipular
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Biblioteca Padr~ao
29
objetos de classes desconhecidas em tempo de compilac~ao, sem porem violar os mecanismos
de controle de visibilidade.
Em java.util, encontram-se algumas classes convenientes, como um vetor de tamanho
variavel, uma tabela de hashing, um gerador de numeros aleatorios, manipuladores de data
e hora, e mecanismos para obtenc~ao de propriedades do sistema e para internacionalizac~ao.
No pacote java.util.zip, ha classes para manipulac~ao de arquivos .zip, o formato
padr~ao utilizado em Java para armazenar arquivos de classe de maneira agrupada (mas n~ao
necessariamente compactada).
Em java.math, encontram-se classes para numeros de precis~ao ilimitada. As func~oes
matematicas comuns, por raz~oes historicas, encontram-se na classe java.lang.Math.
O pacote java.io oferece inumeras classes para manipulaca~o de arquivos, tanto em
modo binario (byte por byte) quanto em modo Unicode (caracteres). Classes com nomes
terminados em InputStream ou OutputStream s~ao baseadas em bytes; Readers e Writers
utilizam caracteres. Ha diversas modalidades dessas classes, que podem ser encadeadas
de modo a acrescentar propriedades as implementac~oes basicas, que d~ao acesso direto a
arquivos ou a arrays em memoria.
Classes para comunicac~ao em rede, utilizando sockets, e para resoluc~ao de URLs, podem
ser encontradas no pacote java.net. Em java.rmi, ha classes que permitem a criac~ao de
aplicac~oes distribudas em Java, de forma razoavelmente simples. RMI, as iniciais de remote
method invocation, e um protocolo conceitualmente semelhante a RPC (remote procedure
call), porem adaptado a ideologia de Java.
Em java.applet est~ao as classes utilizadas para a implementac~ao de applets, que podem
ser includos em paginas HTML. O Abstract Window Toolkit, a biblioteca de interface
graca de Java, esta no pacote java.awt e em seus pacotes componentes. Dentro deles, ha
diversas classes necessarias para a implementac~ao de interfaces gracas, desde os mecanismos
de tratamento de eventos ate componentes basicos para criaca~o de interfaces e tratamento
de multimdia.
O pacote java.beans dene uma biblioteca para criac~ao de componentes de software,
e java.security oferece diversas classes para autenticac~ao atraves de assinaturas digitais.
Em java.sql ha classes para consulta a bancos de dados relacionais, e java.text oferece
ferramentas para manipulac~ao de texto e formatac~ao de dados com apoio a internacionalizac~ao.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Diferencas
'
Diferencas
$
30
tipos enumerados
union
sin^onimos para tipos (typedef)
bit-elds
goto
const
templates
sobrecarga de operadores
pre- e pos-condic~oes
&
modulos
12 Diferencas
%
Nesta sec~ao analisam-se algumas diferencas entre Java e outras linguagens. Como ja se
mostrou o que existe em Java, aqui listam-se apenas elementos que n~ao est~ao presentes na
linguagem.
N~ao ha tipos enumerados nem unions em Java. Tipos enumerados podem ser facilmente
simulados utilizando interfaces com constantes inteiras, ou ate mesmo denindo classes.
Para unions n~ao ha lugar numa linguagem que pretende oferecer seguranca total de tipos.
E possvel obter efeito semelhante utilizando heranca e type-casts seguros ou denindo os
atributos numa classe sem o compartilhamento do espaco de memoria. Alem disso, n~ao ha
como estabelecer nomes alternativos para tipos, como se faz utilizando typedef em C/C++.
N~ao existem bit-elds em Java, mas e perfeitamente possvel utilizar operadores de deslocamento e operac~oes binarias em tipos inteiros para efeito equivalente. Denindo metodos
apropriados, a diferenca e ainda menor.
Ha muitos defensores do extermnio do comando goto, por ele ser t~ao prejudicial a
estruturac~ao de programas. Mesmo assim, goto e uma palavra reservada em Java, talvez
indicando a possibilidade de incorporac~ao futura. Uma das raz~oes para se utilizar goto
em outras linguagens e a falta de um mecanismo para interrupc~ao ou reincio de comandos
repetitivos. Tal funcionalidade e suprida pelos comandos break e continue, opcionalmente
seguidos de rotulos associados a ciclos.
Para tipos basicos, a palavra final e equivalente ao termo const de C/C++, mas, para
tipos complexos, n~ao ha substituto eciente. A unica alternativa e encapsular objetos em
interfaces que n~ao permitem alterac~oes, e encontrar meios para que alterac~oes possam ser
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Futuro
31
feitas quando forem cabveis. Vale notar que const tambem e palavra reservada para uso
futuro em Java.
Tipos parametrizaveis e func~oes com polimorsmo parametrico s~ao dois aspectos que
fazem falta em Java. Valendo-se do fato de que todo objeto Java e inst^ancia da classe base
Object, podem-se criar classes capazes de tratar quaisquer tipos de objetos, mas n~
ao ha o
mesmo poder de express~ao da facilidade de templates de C++.
A possibilidade de sobrecarregar operadores, isto e, denir signicados especiais para
operadores quando aplicados a tipos denidos pelo usuario, e considerada um aspecto negativo por muitos, que argumentam que pode-se produzir codigo incompreensvel com o mau
uso de operadores. Entretanto, isso parece n~ao justicar a proibica~o do bom uso deles, mas
foi esse o caminho tomado por Java.
Especicac~ao de pre- e pos-condic~oes a metodos, para projeto por contrato, n~ao t^em
subsituto razoavel em Java. Tambem faz falta separac~ao clara entre interface e implementac~ao, isto e, um mecanismo de modularizaca~o ortogonal a hierarquia de classes. A provis~ao
de interfaces e um passo nesse sentido.
$
'
Futuro
Melhora de desempenho
Network computers
Criac~ao de ferramentas
Seguranca e conabilidade
Amadurecimento
&
13 Futuro
%
Java atingiu, em seu pouco tempo de exist^encia, um nvel de popularidade nunca antes
conquistado em perodo t~ao curto. Isso se deve, em parte, ao surgimento da WWW (World
Wide Web) e tambem a conu^encia de ideias interessantes ja testadas e utilizadas com
sucesso em outras plataformas. Da mesma forma, buscou-se corrigir pontos fracos dessas
mesmas plataformas, e assim surgiu Java.
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Leituras indicadas
32
Em meio a uma guerra de interesses comerciais de gigantes como Sun, Microsoft, Netscape, Corel, IBM e Apple, a proposta de uma plataforma multi-plataforma, se e que se pode
assim dizer, teve grande repercuss~ao e aceitac~ao, e tem sido alvo de grandes investimentos.
Cada fabricante de software ou hardware busca oferecer aos consumidores a plataforma mais
eciente para o desenvolvimento de aplicac~oes Java, assim como para sua execuc~ao.
Com tamanha competic~ao, espera-se que o desempenho de aplicac~oes Java tenha melhora consideravel nos proximos anos, especialmente com o advento de Network computers,
equipados com processadores capazes de executar diretamente byte-codes Java. Outro fruto
desse grande investimento e o surgimento de ferramentas cada vez melhores, e de aplicaco~es
cada vez mais completas.
Na contra m~ao desse uxo, perde-se um pouco em seguranca e conabilidade. Com ciclos
de desenvolvimento de software cada vez mais rapidos, em func~ao da grande competic~ao, a
qualidade acaba um pouco prejudicada, pois o tempo para testar funcionalidades que t^em
de ser postas no mercado o mais rapido possvel e curto. Por outro lado, com os esforcos
da Sun em criar testes de validac~ao de implementac~oes, a tend^encia e que se reduzam os
problemas de seguranca, um grande foco de atenca~o tanto dos criadores da linguagem quanto
dos proprios usuarios.
Em func~ao do pouco tempo que Java teve para se estabilizar, ainda ha grandes alterac~oes entre uma vers~ao e outra. E certo que, a medida em que a poeira for abaixando,
as tend^encias car~ao mais claras, e Java amadurecera, passando a oferecer uma plataforma
estavel, conavel e homog^enea.
Leituras indicadas
Alguns documentos foram agrupados nesta sec~ao, conforme o topico principal a que se
referem.
Introduc~ao: [?];
Especicac~ao de Java: [?];
Java API: [?], [?], [?];
RMI: [?];
Maquina virtual: [?], [?];
Tutoriais: [?], [?];
White Paper: [?];
Seguranca: [?], [?];
Reex~ao: [?];
Classes Internas: [?];
Metodos Nativos: [?].
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Agradecimentos
33
Agradecimentos
Agradeco a Profa. Dra. Ceclia Mary Fischer Rubira, pela oportunidade de lecionar este
curso no II Simposio Brasileiro de Linguagens de Programaca~o.
Agradeco ao Prof. Dr. Luiz Eduardo Buzato, meu orientador, que me permitiu estudar
Java quando ja havamos decidido que a implementac~ao da minha dissertac~ao de mestrado
seria em C++.
Agradeco a minha noiva, Islene Calciolari Garcia, pelo amor, pela compreens~ao, pelas
ideias e pela baita forca pra preparar esta apostila. Valeu!
Programac~ao em Java
Alexandre Oliva, IC, UNICAMP
Download

Programa cão em JavaTM