Академический Документы
Профессиональный Документы
Культура Документы
2.4. Literais 13
2.4.1. Constantes Inteiras 13
2.4.2. Constantes de ponto flutuante 13
2.4.3. Constante tipo caracter 14
2.4.4. Constantes de tipo boolean 14
2.4.5. Constantes de tipo String 14
3. OPERADORES 20
4. COMANDOS DA LINGUAGEM 38
8. O OBJETO VETOR 69
8.1. Referenciando os elementos de um vetor - Acesso aos elementos de um vetor 70
pag 2
8.2. A propriedade length 71
9.7. THIS 83
10. HERANÇA 87
10.1. Acesso aos membros da classe Base com super 89
pag 3
15.1. Nome simples, Nome Completo e ambigüidade 104
15.1.1. Ambigüidades 105
15.1.2. Unicidade dos Nomes 105
pag 4
1. Noções sobre linguagens de programação
1.1. Conceito de Variável
Umas das noções mais básicas de linguagens de programação é o conceito de variável. Uma
variável é uma região da memória onde se pode colocar conteúdo (escrever) ou ler o conteúdo dela.
Em linguagens de programação como a linguagem JAVA, C, C++, Pascal, etc. as células de
memória que serão usadas no programa fonte são referenciadas através de nomes e tais nomes
deverão ser declarados.
Declarar um nome de variável em um programa é associar um nome para a célula de
memória e estabelecer o tipo de coisa que a célula pode armazenar.
class exemplo {
public static void main(String [ ] args)
{ int data=345;
char tyu= 'B';
int valor = 678;
boolean condicao= false;
}
}
Neste programa, foram declarados nomes para quatro células de memória que são as seguintes:
data para aramazenar valor numérico inteiro
tyu para armazenar caracter
valor para armazenar valor numérico inteiro
condicao para armazenar um valor booleano (falso ou
veradeiro)
A figura abaixo mostra as quatro células de memória cujos nomes foram declarados no
programa.
células de memória
pag 5
class exemplo {
public static void main(String [ ] args)
{ int a=5,b=4,c=10;
a = a+b;
a = 10;
while(a<10) a= a+1;
}
}
a = a+b; é um comando
Sintaxe - Regras para escrever de forma correta coisas que são comandos,
declarações, etc. usando o alfabeto da linguagem.
Semântica - Regras para saber o significado das coisas escritas. Por exemplo, no
programa acima o que significa o comando a= 10;
Este item da apostila trata da notação usada para especificar a sintaxe de linguagens de
programação e esta notação será usada no restante da apostila.
As definições sintáticas de linguagens de programação são dadas através de um conjunto
regras de substituições denominado de gramática da linguagem. Esta forma de apresentar a sintaxe
de linguagens de programação é conhecida por BNF (Backus-Naur Form) em honra aos dois
cientistas, Backus e Naur que inventaram tal notação.
Intuitivamente, essas regras de substituição dizem como concatenar os símbolos de um alfabeto,
definido a apriori, para gerar por exemplo coisas que sejam: comando , declaração , expressão , etc.
Aquilo que sublinhamos ,acima, são conhecidas por categorias sintáticas.
A sintaxe de uma linguagem de programação é explicada através do relacionamento entre as
categorias sintáticas. Este relacionamento é dado através de um conjunto regras de substituição.
pag 6
Cada regra diz o que é uma categoria sintática em termos das outras. Algumas regras irão dizer o
que é uma categoria sintática em termos dos símbolos do vocabulário da linguagem. Lembre que
um texto de um programa só deve conter coisas escritas com os símbolos do alfabeto da linguagem.
Convencionaremos que os símbolos do alfabeto da linguagem estarão com cor vermelha por
exemplo: a , b , c , d , +, - , { , } , , ,etc.
<expressão> : <expressão><símbolo_de_operação><expressão>
A regra acima diz que uma expressão é produzida concatenando-se uma expressão com um
símbolo de operação e, uma expressão. Para ilustrar como se usa as regras sintáticas de uma
linguagem na produção de coisas sintaticamente corretas, vamos definir a sintaxe de uma
linguagem fictícia.
Alfabeto da linguagem - { a , A , b , B , etc., ( , ) , + , - }
Perceba que no lado direito de algumas regras estão presentes símbolos do vocabulário da
linguagem, por exemplo, na regra 2 o abre e fecha parênteses estão presentes. A regra 8 é na
verdade um conjunto de regras em que cada uma tem como lado esquerdo a categoria sintática
<letra> e o lado direito um símbolo do conjunto de caracteres do alfabeto latino.
As regras, acima, dizem como gerar expressões aritméticas em que são construídas com os
símbolo de operação adição e subtração.
Vamos ilustrar como usar as regras de substituição para gerar uma coisa que seja
<expr.> , por exemplo, a+b .
Agora, aplique uma regra de substituição em que a categoria sintática <expr> é lado esquerdo e a
substitua pelo lado direito da regra
1
n
<expr> <expr><op><expr> A notação significa aplicando
a regra substituição n.
No que foi obtido, escolhe-se uma categoria sintática na qual será feita a substituição.
Usando-se uma regra na qual esta categoria sintática é lado esquerdo substitua-a pelo lado direito de
uma regra. Prossiga desta forma até que nenhuma regra mais possa ser aplicada, isto é, o resultado
final das aplicações sucessivas de regras de substituição deverá ter somente os símbolos do alfabeto
da linguagem.
pag 8
3
<expr> <op><expr> <id> <op><expr>
a + <id> 7 a + <letra>
a + <letra> 8 a + b
pag 9
2. Identificadores, tipos, variáveis e literais
Na linguagem JAVA, as variáveis devem ser declaradas antes do uso no texto fonte.
<identificador> : <underscore>
<letra>
<identificador><caracter_de_sequencia>
<underscore>: _
<caracter_de_sequencia> : <letra>
<digito>
<underscore>
Analisando as regras acima concluímos que identificadores são seqüências de letras e dígitos
iniciados por letras ou underscore.
/* Exemplo */
class minha {
public static void main (String args[ ] )
{
int a; /* declaração de variável */
a=8;
}
}
pag 11
• Tipos numéricos
• Tipos Inteiros
• tipo byte
• tipo short
• tipo int
• tipo long
• Tipos em ponto flutuante
• tipo float
• tipo double
• Tipos caracter
• tipo char
• Tipos booleanos
• tipo boolean
O tipo byte
A faixa de valores correspondentes a este tipo é -128 a 127.
As variáveis que armazenam valores deste tipo tem tamanho de 8 bits.
O tipo short
A faixa de valores correspondentes a este tipo é -32768 a 32767.
As variáveis que armazenam valores deste tipo tem tamanho de 16 bits.
O tipo int
A faixa de valores correspondentes a este tipo é -2147483648 a 2147483647.
As variáveis que armazenam valores deste tipo tem tamanho de 32 bits.
O tipo long
A faixa de valores correspondentes a este tipo é -9223372036854775808 a
9223372036854775807.
As variáveis que armazenam valores deste tipo tem tamanho de 64 bits.
O tipo double
A faixa de valores correspondentes a este tipo é
(+ ou -)1.79769313486231570E+308 .
As variáveis que armazenam valores deste tipo tem tamanho de 64 bits.
pag 12
A faixa de valores do tipo boolean é a seguinte
Os valores correspondentes a este tipo são dois: true ou false .
2.4. Literais
Os literais também conhecidos por constantes é uma categoria sintática usada para expressar
os valores dos tipos que mostramos no capítulo anterior.
Uma constante inteira de tipo long é escrita colocando um sufixo L ou l por exemplo: 2L,
489l , 0XdefaL
3- Usando as formas 1 e 2 .
Exemplo: 2.3e-12, 45.9e-10, etc.
pag 13
Como mencionamos, uma constante em ponto flutuante é do tipo double entretanto, quando
uma constante em ponto flutuante é seguida do caracter f ou F ela passa a representar uma constante
do tipo float.
Exemplo: 2,2f , 0.25e-3f , etc.
Alguns caracteres especiais são representados por dígrafos. Este dígrafos são escritos pelo caracter \
seguido de um outro caracter.
As constantes caracteres correspondentes aos dígrafos mais usados são os seguintes:
pag 14
<declarador inicializado> : <declarador><inicializador>opc
<declarador> : <identificador>
<inicializador> : = <constante>
Na declaração acima, são declarados os nomes de 3 variáveis cada uma de tipo int. Além
disso, a variável de nome a é inicializada com o valor 10 , a variável b com valor 90 e a variável c
não é inicializada com nada portanto, o que está armazenado na variável c tem valor indefinido.
A declaração acima diz o seguinte: as variáveis y e t são do tipo char. A variável y terá valor
inicial a constante caracter 'W' e a variável t tem valor inicial a constante caracter 'A' .
Como dissemos, os nomes das variáveis devem ser declarados antes do uso para que
poderem ser referenciadas (usados) no texto de um programa fonte. Por exemplo, o programa
abaixo está errado. pois, as variáveis a e b não foram declaradas.
class exemplo {
public static void main(String[ ] args )
{ a = a+b; }
}
pag 15
class correto {
public static void main(String[ ] args )
{ int a=9, b=10;
a = a+b;
}
}
EXERCÍCIO 2.3- Na declaração int A =5, B; , com qual valor é inicializada a variável A
?
EXERCÍCIO 2.4- Na declaração char B = ‘y’, w = ‘a’; , quais são os tipos das variáveis B
ew?
EXERCÍCIO 2.5- Onde está o erro na declaração int 12A; ?
class <identificador>
{
public static void main(String[ ] args )
{ <declarações>
< comandos>
}
}
Isto é, entre o abre chaves e fecha chaves que imediatamente seguem ...void main(...)
estarão as declarações de variáveis seguida dos comandos.
Os arquivos contendo texto fonte em Java podem ser editados em qualquer editor de texto e
deverão ter a extensão .java . Como em um mesmo arquivo fonte podem existir várias definições de
classe, o nome do arquivo fonte deverá ser igual o nome da classe onde está definido o método
main.
class exemplo23
{
public static void main(String[ ] args)
{ int a=10, b=50; /* declaração */
int c = 30; /* declaração */
a = 10+b; /* comando*/
c = a; /* comando */
}
}
pag 16
O nome do arquivo que contém este fonte deverá ser exemplo23.java este arquivo pode ser
editado em qualquer editor de texto.
Por exemplo, para compilar o arquivo fonte do exemplo 2.3 deve-se digitar o seguinte na
janela dos:
Vimos que uma constante do tipo String é escrita colocando-se entre aspas duplas a cadeia
de caracteres como em "linguagem Java" .
Existe uma operação que se pode fazer entre strings que é a concatenação. Esta operação
tem como símbolo o + , por exemplo:
"Curso de " + "Linguagem Java" da como resultado a cadeia
Curso de Linguagem Java
Cuidado especial deve ser tomado quando é encontrado o símbolo + pois o seu significado
vai depender dos tipos dos operandos. Por exemplo, em 5 + 3 o símbolo + significa soma de coisas
de tipo int. Por outro lado, em "Curso " + "Linguagem Java" o símbolo + significa
concatenação.
Vamos supor que b seja uma variável de tipo int e tenha valor 5. Qual é então o significado do
símbolo + em "valor = " + b ?
Em "valor = " + b vai ocorrer uma conversão do valor de b que é int para o tipo String. Isto é, o
valor de b passa de 5 para "5" (a string que representa o valor). Desta forma o resultado de "valor
= " + b será a string valor = 5.
pag 17
Neste caso a resposta ano é tão imediata, precisamos analisar a expressão acima. Nela o símbolo +,
que ocorre mais a esquerda, representa é a concatenação , já o outro + representa a soma de coisas
de tipo int. Como associatividade não leva em conta o significado do símbolo, o que vai ocorrer é o
seguinte:
primeiro é calculada a subexpressão "valor = " + a que dá como resultado uma valor de tipo
String. Vamos chamar este resultado de R.
Em seguida é calculado R + b, só que o + significa soma de coisas de tipo int e R é de tipo String.
Portanto será gerado um erro na compilação.
Para resolver este problema basta colocar parentes na expressão como mostrado a seguir: "valor =
" + (a + b) . Desta forma, primeiro é calculado a+b cujo resultado é de tipo int . Depois, este
resultado é convertido para tipo String e concatenado com
"valor= " .
Para imprimir na tela uma string usamos o comando cuja sintaxe é dada abaixo:
System.out.println( <expressão>)
onde <expressão> deve ter valor de tipo String ou de um tipo básico.
Exemplo 2.5- System.out.println(" " + a + " " + (a+b) + " " + d);
O efeito do comando acima é fazer a seguinte impressão na tela:
10 70 W
pag 18
class exemplo27
{
static public void main(String[ ] args )
{ int a = 10;
int b = 50, c;
char q = ‘a’;
System.out.println("o valor de a = " + a + " o valor de b= " + b);
c = a + b; /* o valor de a+b sera armazenado em c */
System.out.println(" o valor de c = " + c);
System.out.println(" " + q);
}
}
pag 19
3. Operadores
Abaixo, é mostrado um programa , dentro do retângulo cinza tem uma expressão e ao lado é
explicado como que esta expressão é composta por expressões mais simples (sub-expressões).
Dentro dos retângulos amarelos estão as expressões aritméticas mais simples que são as constantes
ou variáveis. Dentro dos retângulos de cor branca estão os símbolos de operação
class exemplo{
public static void main (String[ ] args )
Qualquer expressão (seja aritmética ou não ) tem um valor. Em termos sintáticos, as expressões
mais simples na linguagem são das seguintes categorias sintáticas:
<constante> - os valores destas expressões é o valor que a própria constante denota por exemplo: 23
, 34.5 , ‘a’ , etc.
<identificador> - Somente aqueles que são usados para nomear variáveis. As expressões desta
categoria tem como valor o conteúdo armazenado na variável.
pag 20
• Símbolo de operação =
O nome do símbolo de operação acima é atribuição.
<identificador> = <expressão>
MINHA = 10
10
conteúdo após a atribuição
Minha
pag 21
3.2.1. Operadores aditivos binários
Símbolo de operação +
O nome do símbolo de operação é adição
• Símbolo de operação -
O nome do símbolo de operação é subtração
Exemplo 3.2- Expressões com operadores Aditivos. Nestas expressões, suponha que as variáveis
são de tipo int.
pag 22
<expressão 1> + <expressão2>
<expressão1> - <expressão2>
pag 23
• Símbolo de operação --
O nome do símbolo de operação é decremento unitário
Exemplo 3.3- Expressões com operadores aditivos unários. Em cada expressão em que a
variável A ocorre ela tem valor 3 é o do tipo int.
++ <identificador>
++ A + 2
Valor da expressão é 6
Valor de A é mudado para 4
<identificador> ++
A ++ +2 Valor da expressão é 5
Valor de A é mudado para 4
pag 24
-- <identificador>
-- A + 2
Valor da expressão é 4
Valor de A é mudado para 2
<identificador> --
A -- + 2 Valor da expressão é 5
Valor de A é mudado para 2
• Símbolo de operação *
O nome do símbolo de operação é multiplicação
• Sintaxe das expressões construidas com o
símbolo de operação * é a seguinte:
<expressão1> * <expressão2>
• Significado - O valor da expressão é o
produto dos valores das expressões
expressão1 e expressão2
pag 25
• Símbolo de operação %
O nome do símbolo de operação resto da divisão
Exemplo 3.4- Expressões com operadores multiplicativos. Nas expressões, as variáveis são do tipo
int.
<espressão1> * <expressão2>
<espressão1> / <expressão2>
pag 26
Símbolo de operação +=
• Sintaxe das expressões construidas com o símbolo de operação += é a
seguinte:
<identificador> += <expressão>
o identificador deverá ser um nome de variável.
Símbolo de operação -=
• Sintaxe das expressões construidas com o símbolo de operação -= é a
seguinte:
<identificador> -= <expressão>
o identificador deverá ser um nome de variável.
• Símbolo de operação *=
• Sintaxe das expressões construidas com o símbolo de operação *= é a
seguinte:
<identificador> *= <expressão>
o identificador deverá ser um nome de variável.
Símbolo de operação /=
• Sintaxe das expressões construidas com o símbolo de operação /= é a
seguinte:
<identificador> /= <expressão>
o identificador deverá ser um nome de variável.
pag 27
Símbolo de operação %=
• Sintaxe das expressões construidas com o símbolo de operação %= é
a seguinte:
<identificador> %= <expressão>
o identificador deverá ser um nome de variável.
Exemplo 3.5- Expressões com os operadores reduzidos de atribuição. Nas expressões, suponha que
as variáveis A e b sejam do tipo int e tenham inicialmente valores 3 e 2.
A += 4
o novo valor A é 7
A -= 2
o novo valor A é 1
A += b +4
o novo valor A é 9
A *= 4
o novo valor A é 12
A /= 3-b
o novo valor A é 3
A %= 2
o novo valor A é 1
Os operandos destes operadores deverão ser de tipo boolean se isto não acontecer, será acusado
erro na compilação.
pag 28
• Símbolo de operação ||
O nome deste simbolo de operação é OR ou OU LÓGICO .
• Sintaxe das expressões construidas com o símbolo de
operação ||
<expressão> || <expressão>
• Significado - se em <expressão> || <expressão> uma
das expressões tiver valor true então, o valor de
<expressão> || <expressão> é true.
• Símbolo de operação !
O nome deste símbolo de operação é NEGAÇÃO
• Sintaxe das expressões construidas com o símbolo de
operação !
!<expressão>
Exemplo 3.6- Expressões com operadores lógicos. Nas expressões abaixo todas as variáveis são de
tipo boolean.
pag 29
<expressão> || <expressão>
A || B
supondo que a variável A tenha valor true
e B valor false então, o valor da expressão
será true.
<expressão>&& <expressão>
A || B && B
supondo que a variável A tenha valor false,
B valor true e RR valor false então, o valor
da expressão será false
!<expressão>
Os resultados das operações relacionais são de tipo boolean. Os operandos só podem ser de
tipo básico exceto para o operador de igualdade que também pode ser do tipo referência.
pag 30
• Símbolo de operação >
O nome deste símbolo é MAIOR QUE .
• Sintaxe das expressões construidas com o símbolo de operação >
<expressão1> > <expressão2>
• Significado - <expressão1> > <expressão2> terá valor true caso o
valor da expressão1 for maior do que o valor da expressão2.
pag 31
• Símbolo de operação ==
O nome deste símbolo é igualdade .
• Sintaxe das expressões constuidas com o símbolo de operação ==
<expressão1> == <expressão2>
• Significado - o valor de <expressão1> == <expressão2> será
true caso o valor da expressão1 for igual ao valor da expressão2.
Caso contrário, o valor de
<expressão1> == <expressão2> será false.
• Símbolo de operação !=
O nome deste símbolo é DIFERENTE DE .
• Sintaxe das expressões constuidas com o símbolo de operação !=
<expressão1> != <expressão2>
• Significado - o valor de <expressão1> != <expressão2> será true
caso o valor da expressão1 for diferente do valor da expressão2.
Caso contrário, o valor de
<expressão1> != <expressão2> será false.
Exemplo 3.7- Expressões com os operadores relacionais. Nas expressões, suponha que todas as
variáveis são do tipo int.
pag 32
<expressão1> > <expressão2>
A > B
suponha que a variável A tenha valor 30
e B valor 10 então, o valor da expressão
é true.
A < B
suponha que a variável A tenha valor 30
e B valor 10 então, o valor da expressão
é false.
<expressão1> = = <expressão2>
A == B
suponha que as variáveis A e B tenham
valor 30 então, o valor da expressão é
true.
<expressão1> != <expressão2>
A != B
suponha que as variáveis A e B tenham
valor 30 então, o valor da expressão é
false.
pag 33
• Símbolo de operação ?:
O nome deste símbolo é OPERADOR CONDICIONAL
• Sintaxe das expressões construidas com o símbolo de operação ?:
<expressão1> ? <expressão2> :<expressão3>
O valor de <expressão1> deverá se do tipo booean.
•
Significado - o valor de <expressão1> ? <expressão2> :<expressão3>
será o valor da expressão2 caso o valor da expressão1 seja true. Caso
o valor da expressão1 seja false, o valor de <expressão1> ?
<expressão2> :<expressão3> será o valor da expressão3.
Exemplo 3.8 - Expressões com o operador condicional. Nas expressões, todas as variáveis são do
tipo int.
A>B ? A : 3
suponha que as variáveis A e B tenham
o mesmo valor então o valor da
expressão condicional é 3.
A ? F-G : 2*F
Estes são denominados bit a bit porque a operação se dá entre cada um dos correspondentes
bits dos operandos.
Exemplo 3.9 - Suponha que a e b são variáveis de tipo int. A figura abaixo mostra os
conteúdos em binário destas variáveis e o resultado de a&b.
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1
variável a
1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1
variável b
1 1 1 1 1 0 1 1 1 1 0 1 1 1 0 1
resultado
pag 35
3.6.2. Ou exclusivo bit a bit
• Símbolo de operação ^
Nome do símbolo de operação ou exlusivo bit a bit
Exemplo 3.10 - Suponha que a e b são variáveis de tipo int. A figura abaixo mostra os
conteúdos em binário destas variáveis e o resultado de a^b.
1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1
variável a
1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1
variável b
0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0
resultado
Exemplo 3.11 - Suponha que a e b são variáveis de tipo int. A figura abaixo mostra os
conteúdos em binário destas variáveis e o resultado de a|b.
pag 36
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 posição dos bits
1 1 1 1 1 0 1 1 1 1 0 1 1 1 0 1
variável a
1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1
variável b
1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1
resultado
pag 37
4. Comandos da linguagem
class Exemplo
<expressão> ;
{
public static void main(String[ ] args )
{ int a=10;
a +1 ;
}
}
class Exemplo42
{
public static void main(String[ ] args )
{;}
}
pag 38
Um dos conceitos fundamentais em Java é o conceito de bloco de comandos. Um bloco
também é denominado comando composto. A idéia é que um comando pode ser composto por uma
seqüência de comandos mais simples.
<comando> : <bloco>
<bloco> : {<lista de declarações>opc <lista de comandos>opc }
Como podemos ver, um bloco pode ter opcionalmente declarações que devem estar no início
do bloco. Seguindo as declarações, devem seguir, opcionalmente, uma seqüência de comandos.
Note que um bloco é sempre delimitado por um abre chaves e um fecha chaves. Pela sintaxe do que
pode ser comando, concluímos que podemos ter um bloco dentro de outro (isto é conhecido por
aninhamento).
class Exemplo
{
public static void main(String args[ ] )
{ int a,b;
a = a+1;
{ int x,y;
x = x+y;
}
}
}
Exemplo 4.4- O exemplo abaixo mostra um caso de aninhamento de blocos. Na figura , os blocos
estão contidos nos retângulos.
class Exemplo{
public static void main(String args[ ]
{ int x=0,y=9;
x = x+1;
{ int j=10,k=3;
j = j*2;
{int a=20;
a =a +1; }
}
}
}
pag 39
EXERCÍCIO 4.1- Resolver e depois executar o programa que está em bloco.java .
4.2.1. O comado if
if (<expressão>) <comando>
true
<expressão>
<comando>
false
demais comandos
do programa
a = a-1;
}
}
pag 40
class Exemplo {
public static void main(String args[ ])
{ int a= 10, b=8;
if (a>0) if( <expressão>)
{ a= a+9;
<comando>
b= a;
}
}
}
<comando1> <comando2>
Exemplo 4.6- Abaixo mostramos dois programas em Java contendo o comando if else.
Nas figuras , tudo que está englobado pelo retângulo maior faz o papel do comando if else.
pag 41
if (<expressão>) <comando1> else <comando2>
class Exemplo46a{
if ( a>b )
a = a+2;
else
b = b+8;
a = c;
}
class Exemplo47b {
{ a= a+2;
b= b-1;
}
else
a = a/b;
a = a+9;
}
}
pag 42
4.3.1. Coman do while
while(<expressão>) <comando>
false
<expressão>
true
comandos que se seguem
<comando>
{ b = b+ a;
a++;
}
}
}
pag 43
do <comando> while(<expressão>);
true
<comando>
<expressão>
false
class Exemplo48 {
}
}
pag 44
for(<expressão1>opc ; <expressão2>opc ; <expressão3>opc ) <comando>
<expressão1>
false
<expressão2>
outros comandos
true
que se seguem.
este
<comando>
<expressão3>
class Exemplo49 {
for( <expressão1> ; <expressão2> ; <expressão3>)<comando>
{
b = b+a ;
b = b+1;
}
while(<expressão>) <comando>
do <comando> while(<expressão>);
for(<expressão1>opc ; <expressão2>opc ; <expressão3>opc) <comando>
Nas definições acima, o ente sintático denotado por <comando> é denominado por corpo
da repetição.
Quando no corpo da repetição (que pode ser um bloco) existe um comando break, assim
que ele é executado o comando de repetição é finalizado.
Nos casos de aninhamentos de comando de repetição a seguinte regra é usada para saber
qual dos comandos de repetição é finalizado pelo break: é o comando de repetição mais interno em
que o corpo de repetição contem o break.
Exemplo 4.10 - Na figura abaixo, mostra um a programa contendo o comando while, o corpo da
repetição está dentro do retângulo.
class Exemplo410 {
System.println("acabou");
}
}
Exemplo 4.11- Na figura abaixo, mostra um programa que contem uma comando break em
comandos de repetição aninhados.
pag 46
class Exemplo {
static public void main(String args[ ] )
{ int a = 10, b = 20;
while( b-- > 0) na figura, o arco com
dupla seta mostra com
while( a > 0)
qual while o break está
{System. println("valor de a: " + a); associado.
if( a= = 5)
corpo de repetiçao a
break; ser finalizado pela
a--; execução do break.
}
System.println("acabou");
}
}
Por outro lado, caso não exista <cte> cujo valor seja igual ao valor de <expressão> então
acontece o seguinte: o corpo do swtich é executado a partir de default. Caso o default não exista, o
comando swtich é encerrado.
pag 47
switch( <expressão>)
{
case <cte 1 > : <co mando >
<comando>
.
.
.
<comando>
case <cte 2 > : <co mando >
<com ando>
. corpo do comando
. sw itch.
.
<com ando>
case <cte k > : <co mando >
<com ando>
.
.
.
<com ando>
case <cte n > : <comando>
<com ando>
.
.
.
<comando>
default : <co mando>
}
Exemplo 4.13- Exemplo de um programa em que existe o comando break dentro do corpo do
comando switch/case.
pag 48
class Exemplo413 {
switch( a )
{
case 10: a = a + 1;
System.out.println( "valor de a ="+ a );
case 30: a = a + 50; ponto de inicio do switch.
break;
ultimo comando
case 60: a ser executado.
case 70:
a = a + 78;
default: System.out.println("Bye"); corpo do switch
}
}
}
Exemplo 4.14- A figura abaixo é um programa que contem um comando continue. Quando
este comando executado, o fluxo de execução do programa (indicado na figura pelo arco em
linha grossa) volta para a condição de teste do while.
pag 49
class Exemplo414{
System.out.println( "acabou");
}
}
pag 50
5. Métodos Estáticos - Funções em JAVA
Vamos, por hora, entender como sendo uma classe em Java um grupo de códigos que são
encapsulados em rotinas.
As rotinas em Java são denominadas por métodos estáticos (mais adiante, veremos o
significado completo do que seja método).
Um programa em Java, ainda em uma visão restrita, será a definição de uma classe que por
sua vez agrupa um conjunto de métodos estáticos (rotinas).
Com isto, queremos dizer que os programas que desenvolveremos terão a seguinte forma:
Assim, as nossas aplicações por enquanto serão constituídas de uma classe. A execução de
uma aplicação (stand alone) é essencialmente a execução do código que define o método estático
main( ), que deverá existir na definição da classe que constituí a aplicação. A partir do método
estático main( ) são feitas as chamadas dos outros métodos presentes na classe.
Um método estático tem dois aspectos que são: a sua definição e chamada.
Resumindo, um método estático é essencialmente um grupo de comandos que fazem uma tarefa
específica.
A figura abaixo representa uma analogia. A caixa representa uma máquina de fazer bolo fazendo o
papel semelhante de um método estático.
tipo açucar
acucar
tipo fermento
entradas saída
tipo bolo
tipo acucar
Para fazer um bolo é necessário fornecer os ingredientes e estes fazem o papel de dados de
entrada do método. Para cada tipo de ingrediente existe uma caixa (na figura, denominada por
entrada) específica onde ele é armazenado para posterior manipulação.
Uma vez feito o bolo, que é o resultado produzido pelo método, este é armazenado na caixa
de saída.
pag 51
Um método estático é constituído por:
• entradas que podem ser zero ou mais entradas. Estas entradas são
variáveis que armazenarão os dados que serão manipilados pelo método.
As entradas são denominadas por parâmetros formais .
As definições de métodos são escritas fora dos blocos isto é , dentro dos blocos não
pode haver definição de métodos.
pag 52
static <tipo> <identificador>(<lista de parâmetros formais>) <bloco>
{ int r ;
r=x+y;
return r;
}
O nome do método é soma, tem dois parâmetros formais (as entradas) denominados de x e
y cada um de tipo int. Dentro do retângulo em azul celeste está o bloco que contém os comandos
que o método vai executar. O método tem uma saída que armazenará o resultado produzido pela
função que é de tipo int.
Exemplo 5.2- Exemplo de um método estático que não tem parâmetros formais.
static char func ( )
{ int a = 5;
System.out.println(" o valor de a = ” + a);
return ‘s’;
}
Para que os comandos de um método sejam executados e os dados sejam recebidos por suas
entradas, é necessário fazer a sua chamada.
A chamada de um método estático é feita através de uma expressão cuja sintaxe é a seguinte:
<identificador>( <lista de expressões> )
Significado:
<lista de expressões> - a lista de expressões, que pode ser eventualmente vazia, tem a
seguinte forma: exp1,...,expn,....,expk . O valor de expn é passado para o n-ésimo parâmetro
pag 53
formal (isto é, para n-ésima entrada).
Como dissemos, toda expressão em Java tem um valor e quando esta expressão é uma
chamada de método o valor dela é justamente o que está armazenado na saída do método.
O comando return
Até agora não explicamos como é armazenado um valor na saída de um método. Isto é feito
através do comando return cuja sintaxe é a seguinte:
return <expressão>opc;
Exemplo 5.4- Abaixo, está exemplificada a chamada de uma função que é feita a partir de main.
class Exemplo {
.
<comando>
}
definição do método
static int soma(int x , int y)
{ int r;
r = x + y;
return(2*r);
}
}
pag 54
Na figura, as retas com setas indicam que valor de b é passado para o parâmetro formal x e o
valor de b+c é passado para o parâmetro formal y. O comando return tem como expressão 2*r este
valor será armazenado na saída e portanto este é o valor de soma(b,a+b) .
Exemplo 5.5- Exemplo de chamada de método que não tem parâmetros formais.
static int g( )
{
System.out.println("exemplo");
}
Até agora não justificamos a razão porque os nossos programas em Java tiveram a forma
Exemplo 5.6- Abaixo, mostramos como é a forma de um texto fonte em Java contendo o
método main e a definição de dois métodos com nomes f1 e f2.
pag 55
class Exemplo56{
public static void main(String arg [ ] )
{ int a = 13, b = 5, n,m;
m = f1(a,b);
n = f2(a,2*b);
}
static int g( )
{return 5;}
pag 56
6. Regras escopo e tempo de vida das variáveis - PARTE I
O escopo de um nome de uma variável é a região do programa fonte onde aquele nome é
conhecido e consequentemente pode ser usado para referenciar uma variável.
As regras de escopo de nome de variáveis dizem onde, no programa fonte, um nome de
variável pode ser referenciada.
As regras de escopo dizem que os nomes declarados em um bloco são conhecidos somente
no bloco onde foram declarados, a partir do ponto onde ocorreu a declaração, até o final do bloco
onde ocorreu a declaração. As variáveis que tem nomes cujo escopo é de bloco são conhecidas por
variáveis locais.
pag 57
{
int a; bloco 0
<comando>
<comando>
{
int b;
<comando> bloco 1
<comando>
{
int f ;
<comando>
<comando>
}
<comando>
}
{
int d;
<comando> bloco 2
<comando>
}
<comando>
<comando>
}
Não podem existir declarações que declaram o mesmo nome no mesmo escopo. Este erro é
detectado pelo compilador.
Sejam T e K dois nomes quaisquer declarados tais que a declaração de T ocorre e um bloco
que englobe o bloco onde K foi declarado, então o nome T não pode ser igual ao nome K.
pag 58
Exemplo 6.2- abaixo é ilustrado redefinições de nomes.
class exemplo {
public static void main(String [ ])
{
{
int a; O a foi declarado mais de uma vez
char a; no bloco
} a = a+1;
Exemplo 6.3- O exemplo abaixo ilustra redefinições de nomes no caso de um bloco que
envolve dois outros.
class exemplo63 {
class exemplo61
{
pag 59
public static void main( String args[ ])
{
int a;
a = a+b;
}
}
EXERCÍCIO 6.2- Em relação às regras de escopo, quais são os erros no texto fonte
abaixo.
class exemplo62 {
public static void main(String args[ ] )
{int x;
x= x+a+b;
int b = 4;
}
static void F( )
{ int k;
k = x+a+b;
}
}
pag 60
7. O mecanismo class e o conceito de objeto
Neste tópico vamos, por questões didáticas, dar uma visão restrita do mecanismo class. Isto
é vamos ver este mecanismo essencialmente como meio de especificar agregação de variáveis de
tipos de diferentes.
Vamos entender pelo termo objeto como uma sendo uma região de memória que é alocada
explicitamente por um programa.
As variáveis de um programa apesarem de serem também regiões de memória não são
objetos pois, são implicitamente criadas quando as declaramos.
OBJETO
peso sexo
int char
Classe é um mecanismo usado para definir novos tipos a partir dos tipo básicos da
linguagem.
Intuitivamente e num sentido restrito, o mecanismo class serve para especificar o "lay out" (o
formato, estrutura) de objetos.
Vendo o mecanismo class, sob esta ótica, temos que a sintaxe para declarar uma classe será:
class<identificador>{<lista de membros>}
Significado da declaração:
<identificador> - serve para especificar o nome da classe. Este nome terá a mesma função
que os nomes do tipos embutidos da linguagem têm. Uma vez definida uma classe em um
programa, pode-se declarar neste programa variáveis que tem o tipo no nome da classe.
pag 61
Os membros podem ser: campos (também chamados de atributos ou membros-dado),
métodos ou construtores. No momento, vamos nos restringir quando os membros só são atributos.
int peso;
char sexo;
peso sexo
int char
class Fisio {
int peso;
char sexo;
}
Quando uma variável for de tipo referência, ela será representada por uma oval. Caso a
variável contenha uma referência a um objeto isto será representado através de uma seta que tem
sua origem na variável e aponta para o tal objeto. Por outro lado, caso a variável for de tipo básico
ela será representada por um retângulo.
A figura abaixo mostra que variável W contém uma referência a um objeto da classe Fisio.
Será mostrado mais adiante como se faz para que uma variável de tipo referência tenha como valor
uma referência a um objeto.
pag 62
W
peso sexo
int char
Exemplo 7.2- A declaração da estrutura abaixo exemplifica o caso em que os membros tem
tipos de classes anteriormente definidas. No caso do exemplo, existe um membro de nome biomet
que tem tipo Fisio que foi definida no exemplo 7.1 .
class Cadastro {
int idade;
Fisio biomet;
}
idade biomet
int Fisio
O campo denominado por idade é de tipo int. O campo denominado por biomet é de tipo Fisio
portanto, este campo por sua vez serve para armazenar uma referência à um objeto da classe Fisio
como ilustrado na figura abaixo.
pag 63
biomet
peso sexo
Exemplo 7.3- Usando a classe Fisio (exemplo anteriores), o efeito de new Fisio( ) é
instanciar um objeto da class Fisio. Neste exemplo é declarada uma variável de nome w e
inicializada com uma referência a um objeto da classe
Fisio.
tipo
instanciação do objeto
nome da variável
pag 64
7.2. Referenciando os atributos de um objeto
<nome do atributo> é o nome do atributo correspondente a parte do objeto onde se quer ter
acesso.
Exemplo 7.4- Este exemplo esta baseado na class Fisio que definimos
anteriormente. Suponha que em um programa fonte tenha a seguinte declaração de variável
e a instanciação Fisio w = new Fisio( );
A parte do objeto que é referenciado pela expressão w.peso é mostrada na figura
abaixo.
peso sexo
a expressão W.peso
referencia a parte
assinalada na figura.
Na figura abaixo, está indicada a parte da variável w que é referenciada pela expressão
w.sexo.
pag 65
W
peso sexo
a expressão W.sexo
referencia a parte
assinalada na figura.
w.peso = 70;
a = w.peso;
w.sexo = 'm';
b = w.sexo;
class program{
public static void main(String[] args )
{
int a ;
char b;
Fisio w = new Fisio( );
w.peso = 70;
a = w.peso;
w.sexo = 'm';
b = w.sexo ;
}
}
pag 66
Agora, para nós, um programa em Java passa a ser uma coleção de classes. Uma delas
contem a definição do método main onde efetivamente as coisas acontecem em termos de execução
do programa. As demais classes presentes no programa definem os novos tipos.
Em termos gerais, uma aplicação Java pode ser constituída de várias classes que podem estar
definidas no mesmo texto fonte ou não. Estes detalhes serão vistos mais adiante.
EXERCÍCIO 7.1- Este exercício usa as classes Fisio e cadastro definidas nos exemplos 7.1 e 7.2 .
Dada a sequência de comandos abaixo
Cadastro w = new Cadatro( ); ,
w.biomet = new Fisio( );
Exemplo 7.6
pag 67
inicializador de membro
class Fisio {
int peso = 70 ;
peso sexo
70 'f '
pag 68
8. O objeto vetor
Um objeto vetor é uma seqüência de variáveis em que todas são do mesmo tipo. Estas
variáveis ocupam posições adjacentes na memória como mostra a figura abaixo.
0 1 2 3 índices do vetor
cada retangulo é uma
variável.
objeto array
O tipo vetor é um tipo referência. Isto significa que para referenciar um objeto vetor
devemos declarar uma variável do tipo vetor para que ela possa armazenar a referência deste objeto.
A Sintaxe da declaração de uma variável de tipo vetor que referencia objetos vetores com
uma dimensão é a seguinte:.
<tipo><identificador> [ ] ;
ou
<tipo> [ ] <identificador> ;
Significado da declaração
Por exemplo, a declaração int Lista [ ] ; declara uma variável de nome Lista cujo tipo é
vetor de int. Assim, esta variável servirá para armazenar uma referência a um objeto vetor de int.
Para que uma variável de tipo vetor possa referenciar um objeto vetor é necessário que este
objeto seja instanciado.
A expressão para instanciar um vetor de uma dimensão composto por variáveis de um tipo T
é a seguinte:
new T [<expcte>]
onde <expcte> é uma constante do tipo int que especifica o número de variáveis que
constitui o objeto vetor. O valor de new T [<expcte>] é a referência do objeto vetor.
pag 69
<tipo>[ ] <identificador> ;
Int [ ] Lista ;
Para que a variável Lista tenha uma valor diferente de null é necessário que ela tenha uma
referência a um objeto vetor de int. Isto é mostrado abaixo.
Lista
A referência a uma variável que pertença a um vetor é feita através de uma expressão cuja
sintaxe é a seguinte:
<identificador>[<expressão>]
O significado é o seguinte:
pag 70
class Exemplo {
int b =0, a = 1;
b = vet[0]; <identficador [ <expressão ]
b = vet [ a+1 ] ;
vet[1] = 90;
}
}
O valor de b , depois da segunda atribuição será 70 pois, o valor de a+1 será 2 e no local
vet[2] está armazenado 70.
Depois da atribuição vet[1] = 90 , o local vet[1] armazenará 90.
Qualquer objeto vetor além das variáveis que o constitui também tem um campo de nome
length que armazena o número de variáveis que constitui o objeto.
pag 71
A
length
variáveis que constituem
o vetor
As variáveis que constituem um objeto vetor podem ser do tipo vetor.Um Objeto vetor com
várias dimensões é formado por variáveis do tipo vetor e cada uma por sua vez referencia um
objeto vetor que por sua vez é formado por variáveis do tipo vetor e assim por diante até as
variáveis se resumam a um tipo que não seja vetor.
pag 72
A
A sintaxe para declarar uma variável de tipo um vetor com n dimensões é a seguinte:
<tipo><identificador>[ ][ ]...[ ]...[ ] ;
pag 74
9. Generalizando o Conceito de Classe.
peso sexo
int char
Este objeto vai armazenar, por intemédio de seus atributos, um valor do tipo Biometrico que
é a composição de um valor de tipo int com outro de tipo char.
Vamos raciocinar como se o valor armazenado no objeto fosse "elementar". Este processo é
análogo com o caso de uma variável de tipo básico, por exemplo int. Sabemos que uma
variável de tipo int é constituída de 4 bytes mas ao nível do tipo nós não temos acesso a cada um
dos bytes que a constitui. Então, vamos tratar o objeto como se fosse uma "caixinha", isto é, vamos
nos abstrair do fato do objeto ser composto por dois atributos.
int char
pag 75
Assim, teremos os usuários de objetos de uma classe. Eles só poderão manipular os objetos da
classe através de operações (métodos de instância) que são definidas para os objetos da classe e não
pela manipulação direta a nível de representação dos objetos.
Desta forma, a representação dos objetos é escondida do usuário e isto é conhecido por
information hiding.
Por outro lado, teremos os implementadores, que cuidarão da representação dos objetos e da
implementação das operações (métodos) a partir da representação.
Os métodos de instância definidos em uma classe são as operações que usuários poderão
usar para manipularem as instâncias da classe.
Assim, além de se definir os atributos de uma classe pode-se também definir os métodos de
instância dela.
Em resumo, os atributos de uma classe dizem respeito a representação dos objetos por outro
lado, os métodos de instância dizem respeito às operações que se pode fazer sobre os objetos de
uma classe.
Atributos e métodos de uma classe são denominados coletivamente por membros. Desta
forma, podemos ter membros de uma classe que são atributos e outros membros que são métodos.
A terminologia usada em orientação a objetos é muito rica, método também é chamado por
função-membro (terminologia do C++) ou mensagem (terminologia do Smaltalk) . Atributo
também é chamado por variável de instância e também por
membro-dado.
class Biometrico
{
int peso;
atributos
char sexo;
void inic (int x, char y)
{ peso = x;
definição de método de instância
sexo = y;
}
void exibe( )
{ System.out.println("PESO = " + peso);
definição de método
de instância.
System.out.println("SEXO = " + sexo);
}
}
Os identificadores não declarados nos métodos são assumidos como sendo membros
(atributo ou método) da classe. Assim, na definição do método inic da classe Biometrico, que é
pag 76
reproduzido abaixo, os identificadores dentro dos retângulos sombreados são assumidos como
sendo membros da classe (no caso são atributos).
sexo = y;
}
Os identificadores dentro dos retângulos são membros da classe (no caso são atributos).
O acesso à um método é expresso em termos sintáticos da mesma for que o acesso a um atributo:
.
<identificador> <nome do método>(<lista de parâmetros> )
Exemplo 9.1
pag 77
class Biometrico
{
int peso ;
char sexo ;
void inic (int x, char y)
{ peso = x ;
sexo = y ;
}
}
class Program {
Vamos ver o que acontece com objeto referenciado pela variável W durante a execução do main.
peso sexo
imediatamente após o seguinte comando
0 '\0'
Biometrico W = new Biometrico( );
peso sexo
imediatamente após o seguinte comando
56 'm'
W.inic(56,'m' );
O programa acima, mostra que alteramos o objeto referenciado pela variável W através do
método inic e não através da manipulação direta dos atributos peso e sexo do objeto. Abaixo é
mostrado como seria feito no caso de manipulação direta dos atributos
pag 78
class program {
public static void main(String args[ ] )
{ Biometrico W = new Biometricio( );
W.peso = 56;
W.sexo = 'm';
}
}
Exemplo 9.2
class ASS {
int a ;
int b ;
int c ;
No exemplo acima, temos dois métodos com o mesmo nome mas as assinaturas são
diferentes; no primeiro caso a assinatura é: int , int enquanto no segundo caso a assinatura é int
.Desta forma, quando for aplicado o método sum em um objeto desta classe a escolha do método a
ser executado será feita com base na assinatura.
Supondo que W seja uma variável que referencie um objeto da classe ASS então
W.sum(10,9) executará definição de sum em que cada um dos parâmetros formais é do tipo int. Por
pag 79
outro lado, W.sum(8) implicará na execução do método sum em que o número de parâmetros
formais é 1 e do tipo int.
Caso não seja especificado para um membro de uma classe A o especificador de acesso
então, este membro poderá ser referenciado em qualquer método de qualquer
classe B desde que esta classe também pertença ao mesmo arquivo fonte da classe A.
Independente do especificador de acesso, qualquer membro de uma classe pode ser usado
(referenciado) nos métodos da classe em que eles foram definidos.
private char b;
public int f( )
{ a = a+1;}
}
operador .
• Costrutor não é herdado.
Exceto pelas características acima, um construtor é como qualquer outro método. Assim,
podemos ter overload de construtores, os especificadores de acesso são igualmente aplicáveis a eles.
Exemplo 9.4
class biometrico
{ definição de um método
int peso ; construtor
char sexo ;
void le( )
{ System.out.println ("PESO = "+ peso);
System.out. println("SEXO= "+ sexo);
}
}
class programa
{
static public main(String args[ ])
{
biometrico W = new biometrico(56, 'f') ;
W.le( );
}
} chamada do metodo construtor
pag 81
No exemplo, note que na definição método construtor tem dois parâmetros formais.
Portanto, os correspondentes argumentos devem ser passados na chamada do método.
Dada uma classe X qualquer, um construtor default da classe é aquele em que a lista de
parâmetros formais é vazia.
class X {
/* membros e métodos */
X( )
{
/* código a ser colocado */
}
}
Dada uma classe X , se para ela não é definido explicitamente um construtor, um construtor
default é gerado e este construtor tem a seguinte forma:
X( )
{
}
Isto é, o código é "vazio".
Portanto, para qualquer classe sempre existe um construtor.
Exemplo 9.5
class CONS { int a;
int b;
pag 82
class CONS {
int a;
int b;
Já neste exemplo não é gerado nenhum construtor default pois, existe a definição de um
construtor. Desta forma, a instanciação de um objeto da classe será por exemplo :
CONS t = new CONS(10,40); .Como o construtor tem parâmetros estes devem ser passados
quando ele é chamado.
9.7. THIS
O this é uma palavra reservada da linguagem que representa o objeto sobre o qual esta sendo
aplicado um método. this só pode ser usado no corpo de métodos que não são estáticos ou nos
construtores.
Implicitamente, no corpo de todos os métodos não estáticos de uma classe onde aparece um
nome de membro k em que a esquerda dele não ocorra o operador . ,na verdade está escrito this.k .
Além disto, em qualquer método não estático de uma classe T qualquer está implícito a existência
de um parâmetro formal definido da seguinte forma: T this.
Na figura que está à esquerda é uma definição de uma classe e um método de instância. Na
figura que está `a direita mostra como o this é explicitado pelo compilador.
pag 83
class Alfa { int a ; class Alfa { int a ;
int b ; int b ;
Assim, supondo que a variável W seja do tipo Alfa e esteja referenciando uma instância
então, por exemplo:
a chamada W.ge(10,50) é convertida pelo compilador para ge(W,10,50).
O this é usado em situações onde pode ocorrer ambigüidade entre o nome de um membro e
o nome de um parâmetro formal, variável ,etc.
Exemplo 9.7
class AMB {
int x ;
int y ;
pag 84
Exemplo 9.8
class EST {
int a ;
int b;
static int c;
}
Suponha que p e q sejam duas instâncias da classe EST. Como o atributo c é estático
então, a região de memória correspondente a este atributo é a mesma para as duas
instâncias .
instância p
a b
c
b instância q
a
Onde:
<nome da classe> é o nome da classe onde método estático foi definido e é opcional caso
chamada do método estático seja feita de algum método da própria classe.
<nome do método estático> é o nome do método estático que se deseja chamar.
Os métodos estáticos são chamados de métodos de classe. Por outro lado, os métodos que
não são estáticos também são denominados por métodos de instância.
pag 85
Só será opcional prefixar o nome da classe na chamada de um método estático caso a
chamada a este método seja feita dentro da própria classe.
Exemplo 9.9
class Mest {
static int ninst = 0;
int a ;
Mest ( int x )
{ a = x; chamada do método estático feita
conta_inst( ); dentro da classe onde o método foi
definido
}
}
class progr {
public static void main(String args [] )
{
mest.conta_inst( ) ; chamada do método
estático conta_inst fora da
} classe onde foi definido
}
pag 86
10. Herança
Por exemplo, vamos supor que tivéssemos definido uma classe funcionario com os tributos
nfunc (numero funcional) e nome_func (nome do funcionário) conforme mostrado abaixo. E com
os métodos mostrados abaixo:
class Funcionario {
int nfunc ; /* numero funcional */
String nome_func; /* nome do funcionario */
void exibe_func( )
{ System.out.println("Numero funcional: " + nfunc);
System.out. println("NOME: " + nome_func);
}
}
Suponha uma especialização da classe Funcionario, por exemplo, a classe dos funcionários
que são motoristas em que o atributo correspondente ao número da carteira de habilitação fosse
importante além dos atributos acima mostrados. Isto é expresso em Java através do conceito de
herança. Assim, podemos especificar a classe dos motoristas a partir da classe acima de forma que
esta herde todos os membros da classe funcionário. Desta forma, a classe motorista é
derivada (filha, herdeira, subclasse) da classe funcionário. Ela terá todos os membros da classe
funcionário além do atributo número da carteira de habilitação.
No exemplo, a classe funcionário é denominada por classe base ou super classe e a classe
funcionário é denominada de classe filha ou classe derivada ou subclasse.
A sintaxe, para se definir uma classe que é herdeira de outra é a seguinte:
class <nome da classe derivada> extends <nome da classe base>
{ aqui vão os membros
específicos da classe derivada
}
Então, a definição da classe motorista fica
pag 87
class Motorista extends Funcionario {
int Habilitação;
void inicHab(int x)
{
Habilitação = x ;
}
void exibe_HAB ( )
{
System.out.println("HABILITACÃO : " + Habilitação);
}
nfunc nome_func
int String
atributos herdados da
classe Funcionario atributo próprio da
classe Motorista
pag 88
• Os únicos métodos que não são herdados são os
construtores.
Suponha que tenhamos duas classes uma Xis e outra Ypslon em que Ypslon é derivada de
Xis além disto, Xis tem um único construtor que exige parâmetros.
Vamos usar bom senso, instanciar um objeto da classe Ypslon implica em instanciar um
objeto da classe Xis. Isto implica que o construtor de Xis deverá ser executado. Como o construtor
de Xis exige parâmetros então devemos definir um construtor na classe Ypslon para no mínimo
chamar o construtor da classe Xis e passar os seus parâmetros.
A chamada do método construtor da classe base deverá ser colocada no inicio do corpo do
construtor da classe derivada da seguinte forma:
super(<lista de parâmetros>)
Como a classe Beta não é subclasse explícita (não tem o extends) de outra, então, ela é
implicitamente subclasse da classe Object. Isto é, tudo se passa como se a definição da classe Beta
fosse:
class Beta extends Object
{ int a;
int b;
Exemplo 10.2
final class Gama {
definição de métodos e
atributos
}
definição de métodos e
atributos
}
pag 90
11. Polimorfismo e Overrading
Suponha que Xis e Ypslon são duas classes quaisquer em que Ypslon é subclasse de Xis.
Sejam as seguintes instanciações:
Se consideramos que a variável g referencia objetos da classe Xis, concluiremos que deve
ser executado o método M da classe Xis. Por outro lado, se consideramos o fato de que o objeto
referenciado por g é da classe Ypslon então, seria executado o método M da classe Ypslon e esta é a
resposta correta.
O Polimorfismo é justamente o mecanismo que acabamos de descrever. Em resumo: se
uma classe Base tem um método com mesma assinatura e tipo de retorno que um método de sua
classe derivada a escolha do método a ser aplicado será feita considerando o tipo do objeto e não o
tipo da referência.
No exemplo acima, g é uma variável cujo tipo é Xis mas o objeto referenciado é da classe
Ypslon (classe derivada).
Exemplo 11.1
pag 91
class Xis {
int a;
Xis( ) { }
void m ( )
{
System.out.println("classe BASE");
}
}
o método m é sobrescrito
class Ypslon extends Xis { na classe Ypslon.
int d;
Ypslon( ){ }
void m( )
{
System.out.println("classe Derivada");
}
}
class Progra {
public static void main(String arg[ ] )
{
Xis g = new Xis( );
}
}
Conforme esta assinalado acima, g é usado para referenciar objetos da classe Xis. Depois da
atribuição, g passa a referenciar objeto da classe Ypslon.
pag 92
12. Classes Abstratas
Note que na classe Motorista é implementado o método exibe. Na superclasse este método é
abstrato.
pag 93
class Secretaria extends Funcionario
{
int toq ; /* numero de toques por segundo */
void exibe( )
{ System.out.println("numero funcional: "+ nfunc);
System.out.println ("nome: "+ nome);
System.out.println ("velocidade de digitação: " + toq);
}
Em resumo, somente serão instanciados objetos das classes mais especializadas. A classe
abstrata não será usada para instanciar objetos. Por causa disto, que a classe abstrata não precisa ter
a implementação dos métodos.
12.1. Métodos Abstratos
Um método abstrato, como vimos, não tem implementação e só pode estar numa classe
abstrata. Em termos sintáticos é a seguinte a definição de um método abstrato.
Como vimos, uma classe abstrata será usada para derivar outras classes dela. Em termos
sintáticos uma classse abstrata é definida da seguinte forma:
abstract < sintaxe de definição de classe vista até o momento>
pag 94
13. Interfaces - Polimorfismo Irrestrito
Uma vez que já sabemos o que é polimorfismo, vamos estudar interfaces sob esta visão. No
caso de polimorfismo sempre está em jogo a relação de herança entre as classes. Já no polimorfismo
irrestrito não existe a relação de herança entre as classes. Vamos entender isto mais de perto.
Vamos supor 3 classes A1, A2 e A3 e existam nelas um método M com mesma assinatura,
mesmo tipo de retorno, por exemplo void M( ).
class A1{
<definições de membros>
void M( )
{
<código do método>
}
}
class A2{
<definições de membros>
void M( )
{ o método M tem a
<código do método> mesma assinatura e
} tipo de retorno.
}
class A3{
<definiçoes de membros>
void M( )
{
<código do método>
}
}
Então, se fizermos x.M( ) será executado o método M da classe A1. Da mesma forma, y.M(
) implica na execução do método M da classe A2 e igualmente z.M( ) implica ma execução do
método M da classe A3. Até agora tudo normal.
Vamos supor uma classe K tal que para cada método da classe K existe um método com
mesma assinatura e tipo retorno em A1, A2 e A3, no caso do exemplo que estamos usando é só o
método M.
Vamos supor mais, que seja automática a conversão de referências de A1 A2 e A3 para K (é
muito parecido quando vimos polimorfismo no capítulo 11).
pag 95
A1 x = new A1( );
A2 y = new A2( );
A3 z = new A3( );
Na verdade, K não será uma classe. K será, segundo a terminologia da linguagem java uma
interface e nela vamos somente especificar, no caso do exemplo, o método M sem a sua
implementação.
O que é importante entender desde já é que uma interface, assim como uma classe define
tipo. A diferença é que na interface não existe a implementação de seus métodos.
Quando é especificado que uma classe Xis implementa uma interface Pe então todos os
métodos especificados na interface Pe deve ter sua implementação na classe Xis. Além disto, uma
variável cujo tipo é de uma interface ela pode referenciar qualquer instância de qualquer classe que
implementa aquela interface.
Outro aspecto é que não se pode instanciar um objeto de um tipo definido por uma
interface (muito parecido com classes abstratas).
A sintaxe para definir uma interface é parecida com aquela para se definir uma classe
Quando uma classe implementa uma interface a sintaxe de definição de classe passa a ser,
levando em conta que ela pode ser derivada de outra:
class <nome da classe> extends <nome da classe base> implements <nome da interface> {
<membros> }
Os membros de uma interface são implicitamente públicos. Portanto, nas classes onde estes
métodos serão definidos deverão ser públicos.
pag 96
interface K {
definição da interface
void M( );
}
class interf {
public static void main(String args[ ])
{ A1 x = new A1( );
A2 y = new A2( );
A3 z = new A3( );
K w = x;
w.M( ); executa método M da classe A1
w= y;
w.M( ); executa método M da classe A2
w=z;
w.M( ); executa método M da classe A3
}
}
pag 97
14. Tratamento de Exceções
Vamos chamar de exceção o resultado produzido por uma ação quando um conjunto de pré-
condições não são satisfeitas. Intuitivamente, exceção é um resultado anômalo.
Por ação vamos entender como sendo basicamente:
. o cálculo de uma operação (aritmética, indexação, etc.)
. a execução de um método.
Por exemplo, vamos supor a seguinte divisão a/b . Para que ela possa ser feita a pré-
condicão a ser satisfeita é que o denominador não seja zero. Caso contrário esta operação vai
produzir uma exceção.
Um outro exemplo: vamos supor que tenhamos definido um array B de inteiros com 4
elementos portanto os índices estarão na faixa 0 a 3. Logo, a pré-condição a ser satisfeita para
realizar a operação B[ <expressão>] é que o valor de <expressão> cai na faixa acima caso contrário
será gerada uma execeção.
Mais outro exemplo: seja um método que faça a abertura de um arquivo e este método peça
como parâmetro o nome do arquivo a ser aberto. Evidentemente, a pré-condição é que o nome do
arquivo exista caso contrário, a execução deste método vai produzir como resultado uma exceção.
RESPOSTAS POSSÍVEIS
Resposta 2 - Parar a execução do programa é uma solução possível em certas situações mas
radical demais em outras por exemplo: o programa encerra caso o nome do arquivo não exista.
Podíamos dar uma chance ao usuário para passar no método o nome de um arquivo existente.
Tanto a resposta 2 e 3 são satisfatórias. Isto é, quando exceções forem produzidas às vezes
pode ser mais conveniente encerrar o programa como também pode ser conveniente desviar o fluxo
de execução do programa para as tais rotinas especiais que são denomindas por manipuladoras de
exceções ("exception handler" em inglês).
pag 98
Objetivamente, queremos dizer que um método pode produzir um resultado de tipo
esperado, por exemplo de tipo int, como pode produzir um resultado (objeto) do tipo (da classe)
exceção caso pré-condições na sejam satisfeitas.
Em Java uma exceção é uma instância de uma classe, isto é, uma exceção é um objeto de
uma classe que pertence a um conjunto de classes conhecidas genericamente por classes de
exceção. Como veremos, existem várias classes que pertencem e este conjunto.
Nos programas teremos que indicar duas coisas para podermos lidar com exceções:
• partes do código que podem produzir exceção.
----------
---------- linhas de código
----------
----------
----------
----------
---------- linhas de código
----------
try2 { linhas de código que produz exceção}
----------
----------
---------- linhas de código
----------
.
.
.
----------
----------
----------
----------
Em primeiro lugar, temos um bloco try nele é colocado código que pode produzir exceção.
Por exemplo, dentro do try colocamos a chamada do método que abre arquivo. Estamos assumindo
que a execução do método de abertura de arquivo é que pode produzir a exceção.
Imediatamente ao try, colocamos um bloco catch onde se define a rotina que manipula exceção.
Assim se dentro do try for produzido um objeto de uma classe de exceção o correspondente catch é
executado. Por outro lado, caso não seja produzido exceção no bloco try, o correspondente cath não
pag 99
é executado e o fluxo de execução do programa prossegue a partir dos comandos que se seguem ao
catch.
Na figura acima, estão assinalados os trys e os correspondentes catchs por linhas com setas.
Significado: Caso o código contido no bloco try produza uma exceção de classe igual aquela
especificada no catch correspondente, o bloco de comandos do catch é executado.
Como a exceção é um objeto, no escopo do bloco catch este objeto é referenciado por
<identificador>.
Em resumo, em cada clausula catch é especificada a classe de exceção que vai ser tratada
por ela.
Para cada try podem estar associados vários catchs pois no bloco try podem ser produzidas
exceções de classes diferentes. Para cada classe de exceção produzida no bloco deve existir um
catch correspondente.
pag 100
O funcionamento é o seguinte: se dentro do bloco try é produzida uma exceção, o catch que
será executado é aquele em que a classe de exceção é igual aquela que ocorreu no bloco try. O
identificador da clausula catch passa a referenciar o objeto daquela classe de exceção.
Em seguida, é executado os comandos que se seguem ao comando try-catch.
Caso não exista catch com classe de exceção igual à classe do objeto exceção produzido no
bloco try então, o programa encerra.
A ideia básica é: se a exceção não é tratada, o programa não pode prosseguir.
Um aspecto importante, se dentro do bloco try ocorrer exceção o restante do bloco try NÃO
É EXECUTADO.
Sempre que uma exceção é produzida e tratada pelo catch correspondente, dizemos que a
exceçao foi consumida.
finally {comandos}
pag 101
O significado é o seguinte: é instanciado um objeto da classe de exceção em seguida ele é
lançado para o catch correspondente à classe de exceção.
Além disto é obrigatório especificar que o método produz exceção daquela classe. Um
método pode lançar exceções de várias classes de exceção.
A sintaxe de definição de método incluindo a especificação das classes de exceção é a
seguinte:
< cabeçalho do método> throws <lista das classes de exceção> { corpo do método}
Exemplo: o exemplo abaixo mostra a definição de uma classe que tem um método que lança
exceção. No exemplo é usada a classe de exceção IOException que é uma classe que está definida
no JDK.
class Mostra {
int a;
No exemplo acima, foi especifcado que o método Atira da classe Mostra pode
eventualmente lançar uma exceção da classe IOException então temos a seguinte pergunta:
Será obrigatório colocar a estrurura try-catch num método que chame o método atira?
Existem duas respostas para a pergunta acima:
• colocar a estrutura try-catch para pegar a exceção IOException como exemplificado
abaixo
class Usa {
int d;
void teste(int k)
{ Mostra x = new Mostra( );
try{ x.Atira(k) }
catch(IOException e) {System.out.prinln("deu problema");}
}
}
• Outra alternativa, é não colocar a estrutura try-catch no método teste da classe Usa mas
será obrigatório colocar neste método a cláusula throws especificando a classe de exceção
IOException, que é a classe de exceção do método Atira. A razão é simples, se a
execução de Atira produz exceção ela não será tratada no método teste então ela vai ser
relançada por ele.
pag 102
class Usa {
int d;
class Usa {
int d;
void teste(int k)
{ Mostra x = new Mostra( );
x.Atira(k) ;
}
}
pag 103
15. Pacotes - Organização dos Programas
A figura abaixo, é uma árvore que representa um exemplo de relacionamento entre pacotes e
classes. Nesta figura, P e Q são pacotes e c1 c2 e c3 são classes que são membros do pacote P. Q é
membro do pacote P e a classe a1 é membro do pacote Q .
@P
Q
#c1 #c2 #c3 @
# a1
Um nome simples é aquele que não possui o símbolo . isto é, ele é formado por um só
identificador.
O nome completo de um pacote, situado num determinado lugar na árvore, é a
concatenação do nome do pacote ao qual ele membro seguido do símbolo . e seguido de seu nome
simples.
Se um pacote tem um nome simples W qualquer e e ele é raiz da arvore então, o seu nome
completo é W.
pag 104
@P P
Q P.Q
#c1 #c2 #c3 @
V P.Q.V
# a1 @
Em termos sintáticos, o nome completo de uma classe é a mesma coisa que o nome completo de
um pacote. Isto é, não dá para se fazer a distinção entre o nome completo de uma classe e o nome
completo de um pacote. Por esta razão se adota a convenção de o nome de uma classe iniciar por
letra maiúscula.
É importante notar que classes ou interfaces não tem como membros pacotes
@P
Q
P.c1 #c1 #c2 #c3 @
P.c2 # a1 @V
P.q.a1 #a1
P.Q.V.a1
Os nomes completo das classes assinaladas pelas flechas estão sobre elas
15.1.1. Ambigüidades
Note no último exemplo que existem duas classes como nome a1. Se em um trecho de
código de programa estivermos referenciando a classe a1 eventualmente isto poderia implicar em
ambigüidade. Então, para tirar esta ambigüidade basta referenciar a classe por seu nome completo.
Por exemplo: P.q.v.a1
pag 105
15.2. As declaraçoes package e import
Uma unidade de compilação é um texto sintaticamente correto em linguagem java. Este
texto é basicamente a definição de classes e interfaces. Uma palavra de precaução: Nao confunda
texto com arquivo que o armazena.
Devemos indicar na unidade de compilação onde é definida uma classe ou interface que ela
pertence a um pacote. Isto é feito declarando o nome do pacote no início da unidade de compilação.
A sintaxe de declaração de nome de pacote é a seguinte:
@P
@ F @K
1 2
Então a unidade de compilação que define a classe apontada pela flecha 1, na figura acima,
será:
package P.F; /*declaração do pacote */
class c2 { -----
-----
-----
}
A unidade de compilação onde é definida a classe apontada pela flecha 2, na figura acima, será
Em uma mesma unidade de compilação pode existir a definição de mais de uma classe ou
interface mas necessariamente elas pertencerão ao mesmo pacote pois em uma unidade de
compilação só pode existir uma declaração package.
pag 106
package P.F; /*declaração do pacote */
class c1 { -----
-----
-----
}
class c2 { -----
-----
-----
}
@P
# Alfa #Beta
Abaixo são mostradas as unidades de compilação onde são definidas as classes Alfa e Beta.
Veja a declaração package de cada uma delas.
package p;
class Alfa { ------
------
void membroA( )
{
Beta x = new Beta ( );
}
package p;
class Beta { ------
------
------
}
O nome Beta usado no corpo da classe Alfa se refere a classe beta do pacote P. A chamada
do construtor é o construtor (que não exige parâmetros) da classe Beta.
@ F @K
package P.F;
class c1 {
definições de membros
Perceba s usamos o nome da classe c3, pertencente ao pacote P.K, para declarar o membro
x na definição da classe c1. A questão é que o nome simples de uma classe só é conhecido no
pacote onde ela foi definida. Portanto, o nome c3 não é conhecido no pacote P.F. Então, quando
compilarmos o texto acima dará erro na compilação.
Para que o nome de uma classe X possa ser usado por classes fora do pacote que a classe X
pertence a classe X deverá ser declarada como pública como mostrado abaixo:
package <nome completo>;
public class X { <definiçoes dos membros>}
Em uma unidade de compilação no máximo pode existir uma classe declara como pública e
além disto o arquivo onde está esta unidade de compilação deve ter como nome o seguinte:
Agora, o nome da classe X pode ser usado em classes pertences a qualquer pacote
diferentes. Em princípio, o nome da classe X quando usado em classes de outros pacotes deve ser
feito pelo nome completo da classe.
@ F @K
pag 108
package P.K;
package P.F;
class c1 {
definições de membros
pag 109
package P.F;
class c1 {
definições de membros
definições de membros
}
Uma outra sintaxe para a declaração import é quando queremos usar várias classes de um
mesmo pacote.
package P.F;
import P.K.* ;
class c2 {
definições de membros
c3 x ;
usando o nome simples das
c4 y ; classes do pacote P.K
definições de membros
}
pag 110
A hierarquia de pacotes será representada a partir de uma sub-árvore do sistemas de
arquivos. Desta forma, um pacote será representado por um diretório desta sub-árvore e o nome
completo de um pacote será igual a nome do diretório (em relação ao diretório origem da sub-
árvore) e substituindo o símbolo / pelo símbolo . .
A figura abaixo ilustra tal representação supondo que sistema de arquivos está em um
disquete no driver a
B D
C
H F G
j1 p1 1 p2
j2
k1 x2 t1 t2 b1
k2 x1 b2
Com respeito ao exemplo acima esta especificacao é : classpath = a:\D\G; a:\ B\C
pag 111
b:
@P \
@ F @K
test
e
#c1 #c2 #c3 #c4
pg
c P
K
F
a classe cujo nome completo de classe é P.F.c1 é representada pelo arquivo de nome P\F\c1.java e
neste arquivo armazena o texto em Java que define a classe.
A restrição do nome do arquivo ter que ser igual ao nome da classe que pública é para que o
compilador possa achar de forma não ambígua onde está localizado o arquivo onde esta classe é
definida e compilá-lo.
Exemplo 15.1 - Seja o arquivo abaixo onde é definida a classe c1, suponha que este arquivo
tenha nome vvv.java e que as classes c3 e c4 pertençam ao pacote P.K
pag 112
package P.F;
import P.K.* ;
class c2 {
definições de membros
c3 x ;
c4 y ;
definições de membros
}
Na hora que for compilado o arquivo vvv.java vai ser verificado se existem os arquivos c3.class
e c4.class caso não existam então, deverão ser compilados os arquivos onde estas classes estão
definidas. Isto significa que o compilador deverá localizar os correspondentes arquivos fontes na
estrutura de diretórios. Portanto, ela vai procurar por \P\K\c3.java e por \P\K\c4.java.
A declaração package não tem como efeito a fabricação dos diretórios correspondestes aos
pacotes que ela especifica. Portanto, a estrutura de diretórios que representa a estrutura de pacotes
deve ser feita a priori.
Exemplo 15.2 - Este exemplo mostra o uso da opção -d do compilador. Suponha a definição
de classe dada abaixo e que o arquivo tenha nome teste.java:
package P.F;
import P.K.* ;
class c2 {
definições de membros
c3 x ;
c4 y ;
definições de membros
}
pag 113
Como resultado da compilação será gerado (caso não existir) o diretório P/F em relação a
origem especificada na variável de ambiente CLASSPATH e o arquivo c2.class estará neste
diretório.
15.4. Especificadores de Acesso a membros e Regras de acessibilidade
A condição necessária para que os membros de uma classe X possam ser acessados nas
unidades de compilação onde são definidas outras classes de outros pacotes é que X seja acessível
nestas unidades de compilação portanto, a classe X deve ser pública..
@w @p
1
#ap2
#ap4 @p #ap5
#ap3 @ #ap0
2
T
EXERCÍCIO 15.1- Identifique como estas hierarquias estão representadas por diretórios e arquivos.
Como seria definida a variável de ambiente CLASSPATH ?
EXERCÍCIO 15.2- Por qual razão no código da classe w.t.c1 é legal referenciar a classe w.t.c2 (isto
é , os nomes dos métodos e da própria classe).
EXERCÍCIO 15.3- Por qual razão no código da classe w.t.ap1 é legal fazer referencias a classe
w.t.c1?
EXERCÍCIO 15.4- Com respeito ao exercício 15.2, por qual razão não há necessidade de se colocar
o comando import w.t.c2 na unidade de compilação onde a classe w.t.a1 foi definida?
EXERCÍCIO 15.5- Por qual razão não houve necessidade de se colocar o comando
import w.t.c1 na unidade de compilação onde a classe w.t.ap1 foi definida ?
pag 114
16. Pacotes do Ambiente Java
O ambiente de programação Java vem acompanhado por uma série de classes (Aplication
Program Interface) que fazem o papel de uma biblioteca de rotinas. Estas classes estão agrupadas
em Pacotes e veremos, de forma resumida, algumas classes que constituem estes pacotes.
Esta implícito na definição de qualquer unidade de compilação o import do pacote
java.lang .
EXERCÍCIO 16.5- Localizar a documentação da classe String e estudar os seguintes métodos cujas
assinaturas são dadas abaixo:
Construtores:
pag 115
public String( )
public String (String a)
public String(char value [] )
Métodos
public boolean equals (Object x)
public static String valueOf( T x) onde T é um tipo básico
public String concat (String str)
public int compareTo(String x)
public char charAt(int i)
A idéia destas classes é transformar os tipos básicos em tipos construídos. Assim, por
exemplo, os significados de atribuição e passagem de argumentos para as funções, que são
diferentes quando se lida com tipos básicos e tipos construídos, passa a ser uniforme desde que se
trabalhe com o tipo construído correspondente ao tipo básico.
Cada classe Wraper tem métodos que convertem o seu objeto no valor correspondente ao seu tipo
básico.
Construtores
public Integer (int valor)
public Integer (String s)
Métodos
public boolean equals (Object ob)
public int intValue( )
public String toString( )
pag 116
public static Integer valueOf(String s) throws NumberFormatException
public long longValue( )
public StringBuffer( )
public StringBuffer append(Tx) onde T é um tipo básico
public int capacity( )
public int length( )
public char charAt(int i)
public void setCharAt(int i, char p)
public void setLength(int m)
pag 117
This document was created with Win2PDF available at http://www.daneprairie.com.
The unregistered version of Win2PDF is for evaluation or non-commercial use only.