Вы находитесь на странице: 1из 118

CURSO DE JAVA BÁSICO

1. NOÇÕES SOBRE LINGUAGENS DE PROGRAMAÇÃO 5

1.1. Conceito de Variável 5

1.2. Sintaxe e Semântica de linguagens de Programação 5

1.3. Especificação Sintática de Linguagens de Programação - BNF 6

2. IDENTIFICADORES, TIPOS, VARIÁVEIS E LITERAIS 10

2.1. Declarações e Identificadores 10

2.2. Identificadores reservados da Linguagem Java - palavras-Reservadas 10


2.2.1. Comentários em texto fonte 11

2.3. Os tipos Simples da linguagem 11


2.3.1. O tipo void 13

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

2.5. Declaração de variáveis e Programas simples em Java 14


2.5.1. Declaração de variáveis 14
2.5.2. Escrevendo, compilando e executando programas Simples em Java 16

2.6. Compilando um arquivo fonte em JAVA 17

2.7. Executando uma aplicação JAVA 17


2.7.1. Escrevendo Strings na tela 17

3. OPERADORES 20

3.1. Expressões de Atribuição Simples 20

3.2. Expressões com operadores aditivos e Multiplicativos 21


3.2.1. Operadores aditivos binários 22
3.2.2. Operadores aditivos unários 23
3.2.3. Expressões com operadores multiplicativos binários 25

3.3. Operadores de atribuição reduzidos 26

3.4. Operadores Lógicos e Relacionais 28


3.4.1. Os Operadores Lógicos 28
3.4.2. Os operadores Relacionais 30

3.5. O operador condicional 33

3.6. Operadores bit a bit 35


3.6.1. And bit a bit 35
3.6.2. Ou exclusivo bit a bit 36
3.6.3. Ou bit a bit 36
pag 1
3.7. Precedência dos operadores 37

4. COMANDOS DA LINGUAGEM 38

4.1. Comando expressão, comando vazio e blocos 38


4.1.1. Comando expressão 38
4.1.2. Comando vazio 38
4.1.3. Bloco (comando composto) 38

4.2. Comandos if /else 40


4.2.1. O comado if 40
4.2.2. O comando if else 41

4.3. Comandos while, do e for 42


4.3.1. Coman do while 43
4.3.2. O comando "do while" 43
4.3.3. O comando "for" 44

4.4. Comando break 46

4.5. Comando switch/case 47

4.6. Comando continue 49

5. MÉTODOS ESTÁTICOS - FUNÇÕES EM JAVA 51

5.1. Definição e chamada de Métodos estáticos 52


5.1.1. Definição de método estático 52
5.1.2. Chamada de Método 53

5.2. Fluxo de execução dos programas 55

6. REGRAS ESCOPO E TEMPO DE VIDA DAS VARIÁVEIS - PARTE I 57

6.1. Declarações nos blocos 57

6.2. Tempo de vida das variáveis declaradas nos blocos 57

6.3. Redefinições de Nomes 58

7. O MECANISMO CLASS E O CONCEITO DE OBJETO 61

7.1. O mecanismo class 61


7.1.1. Declarando variáveis de tipos construídos 62
7.1.2. O conceito de Instanciação 64
7.1.3. Operador new e Instanciação 64
7.1.4. O valor null 64

7.2. Referenciando os atributos de um objeto 65

7.3. Atribuição entre objetos de Tipos Construídos 67


7.3.1. Inicialização dos atributos. 67
7.3.2. Passagem de argumentos para funções 68

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

8.3. Passando Vetores para os Métodos 72

8.4. Vetores com várias dimensões 72

9. GENERALIZANDO O CONCEITO DE CLASSE. 75

9.1. Métodos de Instância 76

9.2. Aplicando Métodos aos Objetos - Acesso aos métodos 77

9.3. Assinatura e Overload 79

9.4. Restringindo o Acesso aos membros de uma classe 80

9.5. Métodos Construtores 81

9.6. Construtor default 82

9.7. THIS 83

9.8. Membros Estáticos - Varáveis de Classe 84


9.8.1. Atributos Estáticos. 84
9.8.2. Métodos estáticos 85

10. HERANÇA 87
10.1. Acesso aos membros da classe Base com super 89

10.2. A Classe base com construtor 89

10.3. Herança implícita da classe Object 89

10.4. Impedindo Herança - final 90

11. POLIMORFISMO E OVERRADING 91

12. CLASSES ABSTRATAS 93

12.1. Métodos Abstratos 94

13. INTERFACES - POLIMORFISMO IRRESTRITO 95

14. TRATAMENTO DE EXCEÇÕES 98


14.1. A cláusula catch 100

14.2. A clausula finally 101

14.3. - Produzindo Exceçoes 101

14.4. Fazendo uma Classe de Exceção 103

15. PACOTES - ORGANIZAÇÃO DOS PROGRAMAS 104

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

15.2. As declaraçoes package e import 106


15.2.1. O escopo de nome de uma classe 107
15.2.2. Classe Pública e a declaração import 107
15.2.3. Declaração import 109

15.3. Repesentação de Pacotes e Unidades de Compilação 110

15.4. Especificadores de Acesso a membros e Regras de acessibilidade 114


15.4.1. Espeficadores de acesso membro 114

16. PACOTES DO AMBIENTE JAVA 115

16.1. A classe java.lang.Object 115


16.1.1. O método finalize 115
16.1.2. Clonagem – o método clone 115

16.2. A classe java.lang.String 115

16.3. Classes Empacotadoras 116


16.3.1. A classe java.lang.Integer 116

16.4. A classe StringBuffer 117

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.

Exemplo 1.1- Um exemplo de programa que declara as quatro células de memória.

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.

data tyu valor condicao


345 'B' 678 false

células de memória

1.2. Sintaxe e Semântica de linguagens de Programação

Exemplo 1.2 - Um pequeno programa em linguagem JAVA.

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

Com respeito ao programa temos que:

int a=5,b=4,c=10; é uma declaração

a = a+b; é um comando

while(a < 10) a = a+1; é um comando

Naturalmente, irão surgir duas perguntas:


como escrever corretamente em uma linguagem de programação ?
qual o significado das coisas escritas naquela linguagem ?

A definição de uma linguagem de programação consiste de 3 coisas básicas:

Alfabeto da linguagem- que é um conjunto de símbolos com os quais serão escritos


os programas. No programa , acima, os elementos escritos em negrito fazem parte do
alfabeto da linguagem Java.

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;

1.3. Especificação Sintática de Linguagens de Programação - BNF

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.

Uma regra de substituição tem a seguinte forma:

Lado esquerdo da regra : Lado direito da regra


No lado esquerdo da regra estará o nome de uma categoria sintática e como convenção
adotaremos que os nomes das categorias sintáticas virão entre os símbolos < e > por exemplo:
<comando>, <declaração>, <expressão> .
O lado direito de uma regra será uma concatenação de categorias sintáticas e/ou símbolos do
alfabeto da linguagem por exemplo: <expressão><símbolo_de_operação><expressão>

Convencionaremos que os símbolos do alfabeto da linguagem estarão com cor vermelha por
exemplo: a , b , c , d , +, - , { , } , , ,etc.

Abaixo temos um exemplo de uma regra de substituição

<expressão> : <expressão><símbolo_de_operação><expressão>

lado esquerdo lado direito da regra


da regra

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., ( , ) , + , - }

Isto é, o alfabeto de nossa linguagem consiste: das letras maiúsculas e minúsculas do


alfabeto latino; dos símbolos abre e fecha parênteses; dos símbolos de adição e subtração.

As regras de substituição são dadas abaixo

numero da lado esquerdo lado direito


regra
1 <expr> : <expr><op><expr>
2 <expr> : (<expr>)
3 <expr> : <id>
4 <op> : +
5 <op> : -
6 <id> : <letra><id>
7 <id> : <letra>
8 <letra> : qualquer caracter do
alfabeto latino maiúsculo ou
minúsculo

Nas regras de substituição acima, as categorias sintáticas usadas são:


<expr> significa expressão;
pag 7
<op> significa símbolo de operação;
<letra> significa letra ;
<id> significa identificador .

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 .

Etapa 1 - inicie pela categoria sintática da coisa a ser fabricada no caso


<expr>

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.

Continuando aplicando as regras temos as etapas baixo. Em cada etapa, é assinalada em


fundo cia a categoria sintática que esta sendo substituída e por fundo amarelo a substituição.

pag 8
3
<expr> <op><expr> <id> <op><expr>

<id> <op> <expr> 3 <id><op> <id>

<id> <op> <id> 4 <id> + <id>

<id> + <id> 73 <letra> + <id>

<letra> + <id> 83 a + <id>

a + <id> 7 a + <letra>

a + <letra> 8 a + b

EXERCÍCIO 1.1- Usando as regras de substituição dadas no capítulo, mostrar como se


obtém (a+b) a partir da categoria sintática <expr> .
EXERCÍCIO 1.2- Mostre que ((a+b) não pode ser obtido a partir de <expr> .
EXERCÍCIO 1.3- Mostre como obter aBb a partir da categoria sintática <id>

pag 9
2. Identificadores, tipos, variáveis e literais

2.1. Declarações e Identificadores

Declarar um nome na linguagem Java é associar um identificador a uma determinada coisa


de forma que ela possa ser referenciada em um programa fonte. Em Java, podemos associar
identificadores para as seguintes classes de coisas:
. variáveis
. tipos
. métodos
. classes
. modificadores, etc.

Na linguagem JAVA, as variáveis devem ser declaradas antes do uso no texto fonte.

A sintaxe que define identificador é dada pelas seguintes regras:

<identificador> : <underscore>
<letra>
<identificador><caracter_de_sequencia>

<underscore>: _

<letra>: qualquer caracter do alfabeto latino maiúsculo ou


minúsculo

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

É importante notar que em Java um caracter em maiúsculo é diferente de seu correspondente


em minúsculo. Assim, os identificadores AbC e aBc não são a mesma
coisa .

Exemplos de indentificadores: abc, e43, o_p89,Total_dol

EXERCÍCIO 2.1- Usando a sintaxe de identificador, mostre que _ _A é um


identificador válido.
EXERCÍCIO 2.2- Mostre, usando a sintaxe de identificador, que 12R não é um
identificador válido .
2.2. Identificadores reservados da Linguagem Java - palavras-
Reservadas

Certos identificadores têm uso reservado na linguagem Java.


Tais identificadores não podem ser usados para nomear, por exemplo métodos, variáveis, classes,
etc.
pag 10
Os identificadores reservados servem para: dar nome para comandos; dar nome aos tipos
básicos; dar nome para aos especificadores de acesso, etc. A relação de identificadores reservados
é dada abaixo:

abstract default goto null synchronized


boolean do if package this
break double implements private threadsafe
byte else import protected throw
byvalue extends instanceof public transient
case false int return true
catch final interface short try
char finally long static void
class float native super while
continuue for new switch

2.2.1. Comentários em texto fonte

Os comentários em um texto fonte devem estar entre /* e */ . Os comentários são


descartados pelo compilador.

Exemplo 2.1- Abaixo é ilustrado um texto fonte contendo comentários

/* Exemplo */
class minha {
public static void main (String args[ ] )
{
int a; /* declaração de variável */
a=8;
}
}

2.3. Os tipos Simples da linguagem

A linguagem Java tem duas grandes espécies de tipos:


tipos simples
tipos referência.

Inicialmente, vamos ver os tipos simples e nos capítulos posteriores os referência.

Os tipos simples são ainda divididos em:

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

A faixa de valores dos tipos inteiros é a seguinte:

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.

A faixa de valores dos tipos em Ponto Flutuante é a seguinte:


O tipo float
A faixa de valores correspondentes a este tipo é (+ ou -)3.40282347E+38
As variáveis que armazenam valores deste tipo tem tamanho de 32 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.

A faixa de valores do tipo char é a seguinte:

Os valores deste tipo correspondem ao conjunto de códigos UNICODE cuja faixa de


valores corresponde 0 a 65535. Isto é, são valores inteiros positivos codificados em 16 bits.
Portanto, variáveis que armazenam valores deste tipo tem tamanho 16 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.3.1. O tipo void


O tipo void denota a ausência de valor. Este tipo é usado em situações especiais envolvendo
métodos. Nenhuma variável pode ter tipo void.

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.

2.4.1. Constantes Inteiras


As constantes podem ser escritas na base decimal, octal, hexadecimal. Se as constantes
forem inferiores a 32 bits elas representam valores de tipo int, caso elas sejam superiores a 32 bits
elas passam a representar valores de tipo long

Constante inteira na base decimal


É qualquer constante escrita com os dígitos de 0 a 9 nunca começando por 0. Estas
constantes denotam valores do tipo int.
Exemplos: 200, -890, 334, etc.

Constante inteira na base octal


É qualquer constante escrita com os dígitos de 0 a 7 sempre começando com 0
Exemplos: 077, 012, 054, etc.

Constante inteira na base hexadecimal


É qualquer constante escrita com os dígitos de 0 a 9 e os caracteres a, A, b, B, c, C,
d, D, e, E, f, F e prefixada com 0x ou 0X.
Exemplos: 0xAA, 0xff, 0x56fE, etc.

Uma constante inteira de tipo long é escrita colocando um sufixo L ou l por exemplo: 2L,
489l , 0XdefaL

2.4.2. Constantes de ponto flutuante


Uma constante em ponto flutuante sempre representa um valor do tipo double.
Estas constantes são escritas nas seguintes formas:

1- colocando-se sempre um ponto decimal na seqüência de dígitos


Exemplo : .23, 9.78, -99.89 , etc.

2- Uma seqüência de dígitos seguida do caracter e ou E seguido de uma seqüência de


dígitos prefixados opcionalmente com o sinal para denotar a parte do expoente.
Exemplo: 23e-10, 45E-23 , etc.

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.

2.4.3. Constante tipo caracter


Uma constante caracter é escrita colocando entre apóstrofes um caracter
Exemplo: 'a' , 'B', 'f' , 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:

'\n' denota nova linha


'\t' denota tabulação
'\r' denota retorno de carro (carrige return)
'\v' denota tabulação vertical
'\b' denota retrocesso do cursor
'\\' denota o caracter \
'\'' denota o caracter apostrofe
'\"' denota o caracter aspas

2.4.4. Constantes de tipo boolean


As constantes de tipo boolean são duas: false denotando o valor falso e true denotando o
valor verdadeiro.

2.4.5. Constantes de tipo String


Uma constante cadeia de caracteres é escrita colocando-se entre aspas uma seqüência de
caracteres:
Exemplos: "aBcV" , "aaaaa\nlllll" , "Curso de Linguagem Java", etc.

2.5. Declaração de variáveis e Programas simples em Java

2.5.1. Declaração de variáveis


As declarações de variáveis tem o propósito de dar nome e associar tipos as variáveis que
são usadas em um programa.
Em um texto fonte, em linguagem Java, sempre é necessário declarar os nomes das variáveis
antes que elas sejam referenciadas no texto fonte.

A sintaxe de declaração de variáveis é dada pelas regras abaixo:

<declaração> : <tipo><lista de declaradores inicializados> ;

<lista de decladores inicializados> :


<declarador inicializado>
<lista de declaradores inicializados>,<declarador inicializado>

pag 14
<declarador inicializado> : <declarador><inicializador>opc
<declarador> : <identificador>
<inicializador> : = <constante>

Exemplo 2.2- Exemplos declarações

<tipo><lista de decladores inicializados> ;

int a = 10, b=90, c ;

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.

<tipo><lista de decladores inicializados> ;

char y = 'w', t = 'A' ;

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

O correto seria o seguinte supondo que as variáveis fossem de tipo int.

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

2.5.2. Escrevendo, compilando e executando programas Simples em Java


Por enquanto, os nossos textos fontes que conterão programas em Java sempre terão
a seguinte forma:

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.

Exemplo 2.3- Um programa em Java escrito conforme a “receita”.

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.

2.6. Compilando um arquivo fonte em JAVA


Para compilar um arquivo fonte em Java devemos utilizar o programa utilitário javac que
acompanha o JDK. O javac pede como argumento o nome do arquivo fonte em JAVA que se deseja
compilar. O javac é uma aplicação "console" no windows 95, isto é, ela roda em uma janela dos.
Caso não exista erros no arquivo fonte então é gerado um arquivo de nome <nome da classe>.class
para cada classe definida no arquivo fonte.

Por exemplo, para compilar o arquivo fonte do exemplo 2.3 deve-se digitar o seguinte na
janela dos:

> javac exemplo23.java

Como resultado da compilação é gerado o arquivo exemplo23.class

2.7. Executando uma aplicação JAVA


Para executar uma aplicação Java devemos utilizar o programa utilitário java que
acompanha o JDK. Este programa é o interpretador e pede como argumento o nome da classe onde
está definida o método main. O utilitário java também é uma aplicação console no windows 95.
Por exemplo, para executar o programa que está no exemplo 2.3 deve-se digitar o seguinte
na janela dos:

> java exemplo23

2.7.1. Escrevendo Strings na tela

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.

Qual é o resultado de "valor = " + a + b ?

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.4- System.out.println("Linguagem Java");

A execução tem como resultado a impressão na tela de:


Linguagem Java
Suponha nos exemplos abaixo as variáveis a e b sejam do tipo int e que a variável d seja
do tipo char e que a está armazenando o valor 10, b valor 60 e d está armazenando ‘W’.

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

Exemplo 2.6- Seja a seguinte seqüência de comandos


System.out.println (" " + a);
System.out.println (" " + a + " " + b);

O efeito do comando acima é a seguinte impressão em tela:


10
70 W

Exemplo 2.7- Um programa completo contendo o comandos para impressão em tela.

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

EXERCÍCIO 2.6- Faça um programa em Java que imprima a cadeia mostrada no


exemplo 3.2 .
EXERCÍCIO 2.7- Faça um programa que imprima o que foi mostrado no exemplo 3.4 mas o
valor de cada expressão deve aparecer em cada linha da tela .
EXERCÍCIO 2.8- Sem executar no micro, qual será o resultado da execução do programa
do exemplo3.5. Depois execute programa para verificar a sua resposta.

pag 19
3. Operadores

Neste capítulo da apostila vamos mostrar as expressões conhecidas por expressões


aritméticas. Em java, existem várias categorias de expressões que não são necessariamente
expressões aritméticas e isto será mostrado nos próximos capítulos.

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 )

{ int abcd, def, g;


g = abcd + df * 30 ;
g = abcd + df * 30
}
}

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.

As expressões mais complicadas são construídas com os símbolos de operação (como + , - ,


* , / etc..), o valor delas dependerá do significado dado para os símbolo de operação.
São discutidos a seguir, os símbolos de operação bem como a sintaxe e o significado das
expressões construídas com eles.

3.1. Expressões de Atribuição Simples

pag 20
• Símbolo de operação =
O nome do símbolo de operação acima é atribuição.

• Sintaxe das expressões construidas com o símbolo de operação =


é a seguinte:
<identificador> = <expressão>
• Significado - <identificador> tem que ser um nome de variável
("caixinha", região de memória).
• Em <identificador> = <expressão> , o valor de <expressão> é
armazenado na variável cujo nome é dado pelo identificador. O
valor anterior da variável é perdido.
O valor de <identificador> = <expressão> é o valor que foi
atribuido à variável.
• Associatividade - Os operadores de atribuição são
associativos da direita para a esquerda.
• Prioridade - Os operadores de atribuição são os menos
prioritários.

Exemplo 3.1- No exemplo, a variável Minha é do tipo int.

<identificador> = <expressão>

MINHA = 10

10
conteúdo após a atribuição
Minha

Então, o valor da expressão Minha = 10 é 10 .

EXERCÍCIO 3.1- Resolver e depois executar o programa que está em expatri.java.

3.2. Expressões com operadores aditivos e Multiplicativos

pag 21
3.2.1. Operadores aditivos binários

Símbolo de operação +
O nome do símbolo de operação é adição

Sintaxe das expressões construidas com símbolo de operação +


é a seguinte:
<expressão 1> + <expressão 2>

Significado - O valor da expressão é soma dos valores das expressões


expressão 1 e expressão 2 .

• Símbolo de operação -
O nome do símbolo de operação é subtração

• Sintaxe das expressões construidas com o simbolo de operação -


<expressão1> - <expressão2>

• Significado - O valor da expressão é subtração dos valores das


expressões expressão1 e expresão2.

• Associatividade - Os operadores aditivos binários são associativos da


esquerda para a direita.

• Prioridade - Os operadores aditivos são mais prioritários que os


operadores de atribuição. Entre os operadores aditivos a prioridade é
a mesma .

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>

AB + 33 Supondo que AB tenha valor 60 então o


valor da expressão é 93.

<expressão1> - <expressão2>

Supondo que AB tenha valor 60 e XY


AB + 33 - XY valor 10 então, o valor da expressão é
83.

EXERCÍCIO 3.2 - Resolver e depois executar o programa que está em expaadi.java.

3.2.2. Operadores aditivos unários


Veremos agora dois operadores aditivos unários que são muito utilizados em programas em
Java. Eles são chamados de operadores unários pois, necessitam de apenas um operando e este
operando deverá ser um nome de variável. Estes operadores podem ser aplicados ao operando na
forma pré-fixada e na forma pós-fixada.
• Símbolo de operação ++
O nome do símbolo de operação é incremento unitário.

• 1o caso forma préfixada


• Sintaxe das expressões construidas com o símbolo de operação
++.
++ <identificador>
o identificador deverá ser nome de variável
• Significado: o novo valor da variável será o valor corrente
somado de 1. Portanto, o valor da expressão é o novo valor da
variável.
• Associatividade - da esquerda para a direita.
• Prioridade - acima dos operadores multiplicativos

• 2o caso na forma pós-fixa


• Sintaxe
<identificador>++
• Significado - na forma posfixa, tudo se passa como no caso anterior e
tudo se passa como se o operador tivesse a menor das prioridades de
todos os operadores.Em resumo, quando numa expressão existem
variáveis com este operador na forma posfixada, calcule toda a
expressão como se aquelas variáveis não tivessem o operador e só
depois aplique o incremento nas tais variáveis.
• Associatividade - Direita para a esquerda.

pag 23
• Símbolo de operação --
O nome do símbolo de operação é decremento unitário

• 1o caso forma préfixada


Sintaxe das expressões construidas com este símbolo de
operação na forma prefixa é aseguinte:
-- <identificador>
onde <identificador> deverá ser nome de variável

• Significado- é o mesmo do operador ++ na forma prefixada


execeto que decrementa de 1 o valor da variável.
• Associatividade - da esquerda para a direita.
• Prioridade - acima dos operadores multiplicativos.

• 2o caso forma posfixada

• Sintaxe das expressões construidas com este símbolo de


operação na forma posfixa é a seguinte:
<identificador>--
• Significado - é o memo do operador ++ na forma posfixada
execeto que decrementa de 1 o valor da variável.
• Associatividade - Direita para a esquerda.

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

EXERCÍCIO 3.3 - Resolver e depois executar o programa que está em expun.java.

3.2.3. Expressões com operadores multiplicativos binários

• 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

• Símbolo de operação / divisão


O nome do símbolo de operação é divisã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 é a divisão do valor da
expressão1 pelo valor da expressão2. Caso o valor de expressão2
seja zero então, o resultado da desta operação será um valor
especial denominado de exceção.

pag 25
• Símbolo de operação %
O nome do símbolo de operação resto da divisã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 resto da divisão do
valor da expressão1 pelo valor da expressão2. Caso o valor
de expressão2 seja zero então, o resultado da desta
operação é indefinida (isto depende do compilador).
• Associatividade- os operadores multiplicativos são
associativos da esquerda para direita.

• Prioridade dos operadores multiplicativos


operadores multiplicativos são mais prioritários
que os aditivos. Entre os operadores
multiplicativos a prioridade é a mesma .

Exemplo 3.4- Expressões com operadores multiplicativos. Nas expressões, as variáveis são do tipo
int.

<espressão1> * <expressão2>

AB * 33 supondo que o valor da variável


AB seja 2, o valor da expressão é
66.

<espressão1> / <expressão2>

supondo que AB tenha valor 2 e XY


AB * 33 / XY
valor 66, o valor da expressão é 1.

EXERCÍCIO 3.4- Resolver e depois executar o programa que está em expmul.java.

3.3. Operadores de atribuição reduzidos

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.

• Significado - o significado de <identificador> += <expressão> é


equivalente à <identificador> = <identificador> + <expressão>

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.

• Significado - o significado de <identificador> -= <expressão> é


equivalente à <identificador> = <identificador> - <expressão>

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

• Significado - o significado de <identificador> *= <expressão> é


equivalente à <identificador> = <identificador> * <expressão>

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.

• Significado - o significado de <identificador> /= <expressão> é


equivalente à <identificador> = <identificador> / <expressão>

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.

• Significado - o significado de <identificador> %= <expressão> é


equivalente à <identificador> = <identificador> % <expressão>

Prioridade e Associatividade - todos os operadores de


atribuição reduzidos tem as regras de prioridade e
associatividade iguais às regras do operador de atribuição.

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

EXERCÍCIO 3.5- Resolver e depois executar o programa que está em expmatr.java)

3.4. Operadores Lógicos e Relacionais

3.4.1. Os Operadores Lógicos

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 simbolo de operação é AND ou E 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 false então, o valor de
<expressão> || <expressão> é false.

Prioridade - Os operadores || e && são menos


prioritários que os operadores aritméticos (+ , - , /, %).
Entretanto, && é mais prioritário do que ||

• Associatividade - Os operadores || e && são


associativos da esquerda para a direita.

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

• Significado - o valor de ! <expressão> será false se o


valor de <expressão> em ! <expressão> é true. Caso
contrário o valor de ! <expressão> será false.
• Associativiade - da direita para a esquerda.
• Prioridade - tem prioridade superior aos dois operadores
lógicos && e || . E tem prioridade superior aos dos
operadores aditivos e multiplicativos.

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>

suponha que os valores das variáveis sejam


! (A|| B) && RR)
iguais as do último exemplo. O valor da
expressão será true

EXERCÍCIO 3.6 - Resolver e depois executar o programa que está em explog.java .

3.4.2. Os operadores Relacionais

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.

• Símbolo de operação <


O nome deste símbolo de operação é MENOR QUE .
• Sintaxe das expressões construidas 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 menor do que o 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 é MAIOR OU IGUAL .
• Sintaxe das expressões construidas 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 maior ou 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 é MENOR OU IGUAL .
• Sintaxe das expressões construidas com o símbolo de operação <=
<expressão1> <= <expressão2>
• Significado - O valor de <expressão1> <= <expressão2> será true
caso o valor de <expressão1> for menor ou igual ao valor de
<expressão2>. Caso contrário, o valor de <expressão1> <=

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.

• Associatividade - os operadores relacionais são associativos da esquerda


para a direita.

• Prioridade - os operadores relacionais são mais prioritários do que os


operadores lógicos e menos dos que os aritmeticos. Os operadores < >
<= >= têm a mesma prioridade e são mais prioritários do que os
seguintes operadores:= = e != . Estes últimos têm a mesma prioridade.

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.

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

EXERCÍCIO 3.7- Resolver e depois executar o programa que está em exprela.java.


EXERCÍCIO 3.8 - Resolver e depois executar o programa que está em exprelog..java
EXERCÍCIO 3.9 - Resolver e depois executar o programa que está em expmix.java

3.5. O operador condicional

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.

• Associatividade - o operador condicional é associativo da direita para a


esquerda.

• Prioridade - o operador condicional tem prioridade imediatamente


superior aos operadores de atribuição.

Exemplo 3.8 - Expressões com o operador condicional. Nas expressões, todas as variáveis são do
tipo int.

<expressão> ? <expressão> : <expressão>

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.

<expressão> ? <expressão> : <expressão>

A ? F-G : 2*F

suponha que A tenha valor true, F tenha


valor 10 e G valor 5 então, o valor da
expressão condicional é 5.

EXERCÍCIO 3.10- Resolver e depois executar o programa que está em expcond.java


pag 34
3.6. Operadores bit a bit

Estes são denominados bit a bit porque a operação se dá entre cada um dos correspondentes
bits dos operandos.

3.6.1. And bit a bit

• Símbolo de operação: &


Nome do símbolo de operação: And bit a bit
• Sintaxe das expressões construidas com o símbolo de operação &:
<expressão1> & <expressão2>

• Significado: são comparados cada bit do primeiro operando com o


correspondente do segundo operando. Se ambos os bits é 1, o
correspondente bit do resultado é 1. Caso contrário o correspondente
bit do resultado é 0 .

• Associatividade: este operador é associativo da esquerda para a


direita.
• Prioridade: imediatamente abaixo dos relacionais e acima dos
operadores lógicos.

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.

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

• Sintaxe das expressões construidas com o símbolo de operação ^


<expressão1> ^ <expressão2>
• Significado - são comparados cada bit do primeiro operando com o
correspondente do segundo operando. Se um dos bits é 0 e o outro é
1, o correspondente bit do resultado é 1. Caso contrário o
correspondente bit do resultado é 0 .
• Associatividade- este operador é associativo da esquerda para a
direita.
• Prioridade- imediatamente abaixo dos relacionais e acima dos
operadores lógicos.

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.

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

3.6.3. Ou bit a bit


• Símbolo de operação |
Nome do símbolo de operação Ou bit a bit.

• Sintaxe das expressões construidas com o símbolo de operação |


<expressão1> | <expressão2>
• Significado - são comparados cada bit do primeiro operando com o
correspondente do segundo operando. Se um dos bits é 1, o
correspondente bit do resultado é 1. Caso contrário, isto é, se os
correspondentes bits dos operandos é 0 o correspondente bit do
resultado é 0 .
• Associatividade- este operador é associativo da esquerda para a
direita.
• Prioridade- imediatamente abaixo do Ou exclusivo bit a bit.

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

3.7. Precedência dos operadores

Abaixo é mostrada uma tabela com os operadores ,sua precedência e associatividade.


Alguns dos operadores presentes nesta tabela serão explicados mais adiante.
símbolo operador classe precedência associatividade
[] subscrito 15 esquerda
f(...) chamada de 15 esquerda
método
. seleção de 15 esquerda
membro
++ e - - incremento e pós-fixo 14 esquerda
decremento
++ e -- incremento e pré-fixo 13 esquerda
decremento
~ não bit a bit unário 13 direita
! não lógico unário 13 direita
-e+ sinal unário 13 direita
(nome de tipo) cast unário 12 direita
* / % multiplicativos binário 11 esquerda
+e- aditivos binário 10 esquerda
< > <= >= relacionais binário 9 esquerda
= = != relacionais binário 8 esquerda
& And bit a bit binário 7 esquerda
^ ou exclusivo bit binário 6 esquerda
a bit
| ou bit a bit binário 5 esquerda
&& And lógico binário 4 esquerda
|| Ou lógico binário 3 esquerda
?: condicional ternário 2 direita
= += -= *= atribuição binário 1 direita
%=

pag 37
4. Comandos da linguagem

Como em todas as linguagens de programação, Java possui entre outros, comandos de


repetição, seleção(if’s), seleção múltipla (swtich/case), vários comando de repetição (do, for e
while). Neste capítulo vamos tratar destes comando nos capítulos posteriores serão apresentados
outros comandos.

4.1. Comando expressão, comando vazio e blocos

4.1.1. Comando expressão

A sintaxe do comando expressão é a seguinte


<expressão>;

Desta forma, toda expressão seguida por ponto e vírgula é um comando.

Exemplo 4.1 - programa que contém comando expressão

class Exemplo
<expressão> ;
{
public static void main(String[ ] args )
{ int a=10;
a +1 ;
}
}

4.1.2. Comando vazio

A sintaxe do comando vazio é dada abaixo


;
O significado deste comando é o seguinte: não faz nada.

Exemplo 4.2- programa que contem somente o comando vazio

class Exemplo42
{
public static void main(String[ ] args )
{;}
}

4.1.3. Bloco (comando composto)

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.

A sintaxe de comando composto é dada abaixo.

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

observação: Na verdade, as declarações não precisam encabeçar os blocos, elas devem


preceder os comandos que usam os nomes declarados.

Exemplo 4.3 - O Exemplo abaixo é um texto de um programa em Java que contem um


bloco, que está contido no retângulo pontilhado da figura abaixo. Quando o fluxo de execução do
programa alcançar o bloco, os comandos nele contidos serão executados.

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. Comandos if /else

Estes comandos são usados para desviar condicionalmente o fluxo de execução de um


programa.

4.2.1. O comado if

A sintaxe do comando if é a seguinte:

if (<expressão>) <comando>

O valor de <expressão> deverá ser do tipo boolean.

O significado do comando é dado pelo diagrama de fluxo abaixo.

true
<expressão>

<comando>
false

demais comandos
do programa

Exemplo 4.5- Abaixo mostramos exemplos de programas contendo comandos if.


class Exemplo { if ( <expressão> ) <comando>
public static void main(String args[ ] )
{int a= 2, b=3,c=10;
if (a>0)
a = b+c;

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

EXERCÍCIO 4.2- Resolver e depois executar o programa que está em if1.java


EXERCÍCIO 4.3 - Resolver e depois executar o programa que está em arquivo if2.java.

4.2.2. O comando if else

A sintaxe do comando if else é a seguinte:

if (<expressão>) <comando1> else <comando2>

O significado deste comando é dado pelo diagrama de fluxo desenhado abaixo.

true <expressão> false

<comando1> <comando2>

comandos que se seguem

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{

public static void main(String args[ ] )


{ int a, b, c ;

if ( a>b )

a = a+2;
else
b = b+8;
a = c;
}

class Exemplo47b {

public static void main( String arg[ ] )


{ int a, b;
if( <expressão> ) <comando1> else <comando2>
if ( a>b )

{ a= a+2;
b= b-1;
}
else
a = a/b;
a = a+9;
}
}

EXERCÍCIO 4.4- Resolver e depois executar o programa que está em ifel1.java.


EXERCÍCIO 4.5- Resolver e depois executar o programa que está em ifel2.java.
EXERCÍCIO 4.6- Resolver e depois executar o programa que está em anif1.java.
EXERCÍCIO 4.7- Resolver e depois executar o programa que está em anif2.java.

EXERCÍCIO 4.8- Resolver e depois executar o programa que está em anifel1.java .


EXERCÍCIO 4.9- Resolver e depois executar o programa que está em anifel2.java .

4.3. Comandos while, do e for

pag 42
4.3.1. Coman do while

Sintaxe do comando while é a seguinte:

while(<expressão>) <comando>

Na sintaxe acima, <comando> é chamado de o corpo da repetição

O significado do comando while é dado pelo diagrama de fluxo abaixo.

false
<expressão>

true
comandos que se seguem

<comando>

Exemplo 4.7- Exemplo de um programa contendo o comando while


class Exemplo47{

while <expressão> <comando>


public static void main (String args[ ] )
{ int b = 30, a= 0;
while ( a < 10 )

{ b = b+ a;
a++;
}
}
}

EXERCÍCIO 4.10- Resolver e depois executar o programa que está em wh.java .

4.3.2. O comando "do while"

A sintaxe do comando do while é a seguinte:

pag 43
do <comando> while(<expressão>);

Na sintaxe acima, <comando> é chamado de o corpo da repetição.

O significado do comando “do while” é dado pelo diagrama de fluxo abaixo

true

<comando>

<expressão>

false

comandos que se seguem

Exemplo 4.8- Programa contendo o comando do while

class Exemplo48 {

public static void main (String args[ ] ) do <comando> while <expressão> ;


{ int b = 30, a= 0;
do
{ b = b+a;
a++;
}
while ( a < 10 )

}
}

EXERCÍCIO 4.11 - Resolver e depois executar o programa que está em do1.java .

4.3.3. O comando "for"

Sintaxe do comando for é a seguinte:

pag 44
for(<expressão1>opc ; <expressão2>opc ; <expressão3>opc ) <comando>

onde <expressão2> deverá ser do tipo boolean.

Na sintaxe acima, <comando> é chamado de o corpo da repetição

O significado do comando for é diagramado abaixo onde as linhas indicam o fluxo de


execução no comando.

<expressão1>

false
<expressão2>

outros comandos
true
que se seguem.
este
<comando>

<expressão3>

Exemplo 4.9 - Programa contendo o comado for

class Exemplo49 {
for( <expressão1> ; <expressão2> ; <expressão3>)<comando>

public static void main(String arg[ ] )


{ int b=30 , a =0 ;

for( a =0 ; a<10 ; a++ )

{
b = b+a ;
b = b+1;
}

EXERCÍCIO 4.12- Resolver e depois executar o programa que está em for1.java .


pag 45
EXERCÍCIO 4.13- Resolver e depois executar o programa que está em for2.java .

4.4. Comando break

O comando break funciona somente em comandos de repetição e no comando switch/case.


Inicialmente, vamos ver como funciona o comando break nos comandos de repetição.

Vimos que as definições sintáticas dos comandos de repetição são:

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.

A sintaxe do comando break é seguinte:


break;

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 {

public static void main(String args[ ] )


{
int a = 10;
na figura, o arco com duas
while( a > 0) setas mostra com qual while
o break está associado.
{System.println("valoe de a: " +, a);
if( a= = 5)
break; corpo da repetição
a-- ;
}

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

EXERCÍCIO 4.14- Resolver e depois executar o programa que está em break1.java .


EXERCÍCIO 4.15- Resolver e depois executar o programa que está em break2.java .
EXERCÍCIO 4.16- Resolver e depois executar o programa que está em break3.java .
4.5. Comando switch/case

O comando switch funciona dentro do esquema mostrado na figura abaixo. Dentro do


retângulo amarelo temos um bloco que é o corpo do comando switch. Ainda na figura, <cte> é a
categoria sintática das constantes (literais).
Quando o fluxo de execução dos comandos atinge o comando switch acontece o seguinte: é
verificado qual das <cte> (expressão constante) tem valor igual ao valor de <expressão> , se existir
alguma <cte> que satisfaça a tal igualdade então, o corpo do swtich é executado a partir desta
<cte>.

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.

Quando um comando break é encontrado dentro do corpo do comando switch/case, o


comando switch/case é terminado e o fluxo de execução do programa prossegue para o próximo
comando.

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.12- Um programa com o comando switch/case

class Exemplo 412 {

public static void main(String arg [ ] )


{ int a = 30;
os valores das expressões são iguais
switch( a )
{ case 10 : a = a+1;
System.out.println("valor de a = :" + a); começa a executar a
case 30: a = a + 50; partir deste ponto.
case 60:
case 70:
a = a + 78; corpo do switch.
default : System.out.println("bye");
}
}
}

Exemplo 4.13- Exemplo de um programa em que existe o comando break dentro do corpo do
comando switch/case.

pag 48
class Exemplo413 {

public static void main(String arg [ ] )


{ int a = 30;

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
}

}
}

EXERCÍCIO 4.17- Resolver e depois executar o programa que está em sw1.java .


EXERCÍCIO 4.18- Resolver e depois executar o programa que está em sw2.java .
EXERCÍCIO 4.19- Resolver e depois executar o programa que está em sw3.java .

4.6. Comando continue


O comando continue só é usado no contexto de comandos de repetição.
Sintaxe do comando continue é a seguinte: continue;
Significado - Este comando é usado da mesma forma que o comando break só que o continue
quando executado faz com que o fluxo de execução do programa seja desviado para a condição de
teste do comando de repetição.

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{

public static void main(String arg[ ] )


{ int a = 10;

while( a > 10) corpo da repetição


{ System.out.println( "a = " + a );
if(a == 5)
continue; quando executado, o fluxo de
a--; execução vai para a condição de
} teste do while.

System.out.println( "acabou");
}
}

EXERCÍCIO 4.20- Resolver e depois executar o programa que está em cont1.java .

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:

class <nome da classe> {


<método estático1>
.
.
.
<método estáticok >
.
.
<método estáticon >
}

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:

• corpo que é essencialmente os comandos que o método vai executar;

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

• uma saída no máximo que é uma variável onde será armazenado o


resultado produzido pelo método. Pode-se ter métodos que não produzem
resultados no sentido que não será armazenado coisa alguma na caixa de
saída. Neste caso, se diz que o método não produz valor como saída.

5.1. Definição e chamada de Métodos estáticos

5.1.1. Definição de método estático

Mencionamos que um dos aspectos de um método é sobre sua definição.

Definir um método significa:


• Definir o nome do método.
• Especificar, através de um bloco de comandos, o que o
método faz
• Definir o número, tipo e o nome dos parâmetros formais.
• Definir o tipo de resultado que será armazenado na saída.

Sintaxe (restrita) de definição de método é a seguinte:

static <tipo><identificador>(<lista de parametros formais>)<bloco>

onde: <tipo> especifica o tipo de resultado que será armazenado na saída.


Quando um método não produz saída o tipo de retorno é void;

<identificador> - é o nome do método;


<lista de parâmetros formais> - é uma lista, eventualmente vazia, contendo a
declaração das variáveis ( as entradas) que recebem os valores que são passados
para o método. Os nomes destas variáveis são conhecidas em <bloco>.
<bloco> - é o bloco de comandos que definem o que o método faz a partir dos
valores passados para os parâmetros acima.

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.

Exemplo 5.1 - Abaixo, está exemplificada uma definição de um método.

pag 52
static <tipo> <identificador>(<lista de parâmetros formais>) <bloco>

static int soma ( int x , int y )

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

Exemplo 5.3- Exemplo de definição de método que não produz saída.


static void sca(int a)
{
System.out.println(" " + a);
}

5.1.2. Chamada de Método

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:

<identificador> - é o nome do método a ser chamado.

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

Quando o método estático é chamado, o fluxo de execução do programa é desviado para o


bloco que define o método, as variáveis que fazem o papel de entradas e a saída são fabricadas e
começa a execução dos comandos desse bloco.
O bloco é executado até a ultima instrução ou até a execução de um comando return ( a
sintaxe deste comando está definida mais abaixo) depois, o fluxo de execução do programa volta
para o próximo comando que se segue a chamada do método e as variáveis que fazem o papel de
entradas e saída são destruídas.
Em particular, a hora em que a variável que faz o papel da saída é destruída vai depender se
a chamada do método faz parte de uma expressão mais complicada.
É importante perceber que para cada chamada de um método são fabricadas variáveis de
entrada e saída exclusivas para aquela chamada .

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;

Significado: quando o return for executado o valor de <expressão> é armazenado na


saída da função .

Exemplo 5.4- Abaixo, está exemplificada a chamada de uma função que é feita a partir de main.

class Exemplo {

static public void main(String args[ ] )


{ int a,b,c;
.
.
.

a = soma( b , b+c ) ; chamada do método

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

Suponha a seguinte definição para um método:

static int g( )
{
System.out.println("exemplo");
}

então a chamada deste método será: g( )

5.2. Fluxo de execução dos programas

Até agora não justificamos a razão porque os nossos programas em Java tiveram a forma

class <nome da classe> {


public static void main(String arg [ ] )
{ <declarações>
< comandos>
}
}

Em primeiro, lugar é importante perceber que main é um método estático. A execução de


um programa em Java é a execução dos comandos e só dos comandos que estão no corpo da função
main. A partir de main são feitas chamadas de outros métodos estáticos que foram escritos no
texto fonte. A execução de um programa termina quando termina a execução do método main.
Em resumo, todo programa em Java deverá ter um é só um método main.
Por outro o lado, quando é dado ao interpretador um programa, o interpretador é quem
chama o método main.

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 f1(int x, int y)


{ return x*y;
}

static int f2(int p, int q)


{ return(p-q);
}
}

No exemplo, a execução do programa inicia chamando o método f1, o fluxo de execução do


programa é desviado para o corpo do método f1,o fluxo volta para main e o valor da saída de f1 é
atribuído a m. Em seguida, é feita a chamada do método f2, o fluxo de execução do programa é
desviado para o corpo do método f2 depois, o fluxo volta para main e o valor da saída de f2 á
armazenado em n.

EXERCÍCIO 5.1- Abaixo, está a definição de um método, responda as seguintes


perguntas:
a- Qual é o nome do método?
b- Quantos são e quais são os nomes e tipos dos parâmetros formais ?
c- Qual é o tipo de resultado ?

static char BRK(int a, int b)


{ a = a+b;
return 'W';
}

EXERCÍCIO 5.2- Dado a definição do método abaixo


Responda: como seria a sua chamada ?

static int g( )
{return 5;}

EXERCÍCIO 5.3- Resolva e depois execute o programa que está em fb1.java .


EXERCÍCIO 5.4- Resolva e depois execute o programa que está em fb2.java .
EXERCÍCIO 5.5- Resolva e depois execute o programa que está em fb3.java .
EXERCÍCIO 5.6- Resolva e depois execute o programa que está em fb4.java .

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.

6.1. Declarações nos blocos

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.

6.2. Tempo de vida das variáveis declaradas nos blocos

Durante a execução de um programa variáveis são criadas e destruídas. O momento em que


as variáveis são criadas e destruídas, na execução do programa, tem como base o escopo dos nomes
destas varáveis.
Os termo criar uma variável significa alocar área em memória e o ente que aloca é o sistema
operacional. Por outro lado, destruir uma variável significa devolver para o sistema operacional a
área alocada para ser usada em outra coisa.
Uma variável cujo nome tenha sido declarado dentro de um bloco (escopo de bloco) é
criada e inicializada quando o fluxo de execução do programa atinge o bloco e destruída quando o
fluxo de execução do programa sai do bloco.

Exemplo 6.1- O exemplo abaixo ilustra as regras de escopo de nomes de variáveis


declarados dentro de blocos bem como o tempo de vida destas variáveis. Na figura, abaixo
temos o seguinte:
1- ao lado de cada declaração fizemos um desenho de uma caixa correspondente a variável.
Para cada variável desenhada o preenchimento da caixa é diferente.
2- Os retângulos delimitam os blocos e a cada bloco foi associado um nome

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

O escopo do nome a ,que é nome da variável representada por , se estende por


todos os blocos uma vez que a declaração deste nome ocorre no bloco 0 que engloba os demais
bloco. Assim se o nome a é usado no bloco 1, por exemplo, este nome referencia a variável
.
Por outro lado, quando o fluxo de execução do programa chega no bloco 0 a variável
é alocada (criada) e quando o fluxo de execução do programa sai do bloco 0 a variável
é desalocada (destruída).
O escopo do nome d que é nome da variável representada por , fica restrito
somente no bloco 2. Assim se o nome d é usado fora deste bloco, por exemplo no bloco 1, ocorrerá
erro (nome não declarado), pois o nome d só é conhecido dentro do bloco que foi declarado até o
final do bloco onde ocorreu a declaração. Dentro deste bloco, o nome d referncia a variável
. Quando o fluxo de execução do programa chega no bloco 2, a variável é
alocada e quando o fluxo de execução sai do bloco 2 a variável é destruída.

6.3. Redefinições de Nomes

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;

{ int b ; O b foi declarado mais de uma vez


boolean b; no bloco
int x ;
x = x +b;
}
}
}

Exemplo 6.3- O exemplo abaixo ilustra redefinições de nomes no caso de um bloco que
envolve dois outros.

class exemplo63 {

public static void main(String [ ] args)


{ int a;
int b; a é declarada tanto no bloco mais
externo como no mais interno.
{ int a;
a = a+1;
}
b é declarada tanto no bloco mais
{ int b ; externo como no mais interno.
int x ;
x = x +b;
}
}
}

EXRCÍCIO 6.1- Qual é o erro no texto fonte abaixo ?

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

EXERCÍCIO 6.3- Resolver e depois executar o programa que está em scp0.java .


EXERCÍCIO 6.4- Resolver e depois executar o programa que está em scp1.java .
EXERCÍCIO 6.5- Resolver e depois executar o programa que está em scp2.java .

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.

7.1. O mecanismo class


Um objeto é uma concatenação de variáveis de tipos diferentes. A figura abaixo, mostra um
exemplo de um objeto que é resultado da agregação de duas 2 variáveis (campos). Os campos
componentes são peso de tipo int e sexo de tipo char. Os nomes peso e sexo são usados para
referenciar “em relação ao objeto” as partes que constituem tal agregação.

OBJETO

peso sexo

int char

Classe é um mecanismo usado para definir novos tipos a partir dos tipo básicos da
linguagem.

observação: Os termos class e tipo serão considerados sinônimos

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.

<lista de membros> - é a especificação de cada um dos campos da estrutura ( tipo e o nome)


separados por ; . Os tipos que são especificados para os campos de uma classe podem ser: de tipo
simples(int, char, etc.) ; arrays (veremos mais adiante) e de tipos especificados por classes definidas
a priori.

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.

Exemplo 7.1- declaração de uma classe.

class Fisio { class <identificador>{listas de membros }

int peso;
char sexo;

Os objetos da classe Fisio terão o aspecto ilustrado na figura abaixo.

peso sexo

int char

7.1.1. Declarando variáveis de tipos construídos


A rigor, quando em um programa se define uma classe na verdade está se definindo um
novo tipo. Desta forma, podemos declarar variáveis que tem este novo tipo, por exemplo, Fisio w; .
Esta declaração diz o seguinte: w armazena um valor que é uma referência à um objeto da classe
Fisio. Além disto, este objeto terá o formato especificado pela class Fisio como ilustrado abaixo.
Quando uma variável tem o seu tipo definido por uma classe se diz genericamente que o tipo
da variável é um tipo referência. Em resumo, qualquer tipo definido por uma classe é um tipo
referência

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

Os objetos da classe Cadastro terão o formato ilustrado na figura abaixo.

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

objeto da classe Fisio

7.1.2. O conceito de Instanciação

Diferente de outras linguagens de programação, em Java, a declaração de um nome de


variável, cujo tipo não é básico, não implica na criação automática do objeto que ela referencia.
Na terminologia de orientação a objetos, a frase criar objeto é a mesma coisa que
instanciar objeto.

7.1.3. Operador new e Instanciação


A instanciação de um objeto de uma classe deverá ser feita explicitamente através do
operador new.
A sintaxe da expressão que instancia um objeto de uma classe é:

new <nome de classe> (<lista de parâmetros>)


O valor desta expressão é a referência ao objeto instanciado.
Para os nossos propósitos a lista de parâmetros será vazia por enquanto.

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

Fisio W = new Fisio( )

nome da variável

7.1.4. O valor null

O valor null denota inexistência de objeto. Assim, se simplesmente declaramos, em um


programa, o nome de uma variável e não instanciarmos o objeto que ela referencia, o valor da
variável será null.

pag 64
7.2. Referenciando os atributos de um objeto

A referência aos atributos de um objeto é feita através de expressões cuja sintaxe é:


<identificador>.<nome do atributo> .
O símbolo . usado na expressão é chamado operador de seleção de membro.
O significado da expressão acima é o seguinte:

<identificador> é o nome da variável que contem a referência ao 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.

Abaixo é um trecho de um programa onde a variável w é do tipo Fisio e referencia uma


instancia da classe Fisio. Note como são feitas atribuições e leituras dos atributos do objeto
referenciado pela variável w .

w.peso = 70;
a = w.peso;
w.sexo = 'm';
b = w.sexo;

Exemplo 7.5- Abaixo é mostrado um programa em Java contendo várias classes


class Fisio { int peso;
char 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( );

O que significa a expressão w.biomet.peso ?

EXERCÍCIO 7.2 - Resolva e depois execute o programa que está em strb1.java.

7.3. Atribuição entre objetos de Tipos Construídos


A atribuição tem significado diferente quando ela se dá entre varáveis que têm os seus tipos
numa classe.
Quando se faz atribuição entre variáveis de tipos básicos o significado da atribuição é da
cópia bit a bit por exemplo: suponha que x e y são nomes de objetos declarados como int então o
efeito de x= y é a copia do conteúdo de x para y.
Por outro lado, se x e y, tivessem os seus tipos numa classe, por exemplo, a classe Fisio
(mostrada nos exemplos anteriores) o efeito de x = y é o seguinte: a variável x passa a ter o mesmo
o mesmo valor que a variável y. Lembrando que as variáveis são do tipo referência, então, a
variáveis x e y estariam apontando para o mesmo objeto.

EXERCÍCIO 7.3 - Resolva o depois execute o programa que está em strb2.java .

7.3.1. Inicialização dos atributos.


Pode-se especificar valores iniciais para qualquer atributo de uma instância de uma classe .
Desta forma, quando for instanciado um objeto daquela classe (daquele tipo) os atributos terão
aqueles valores.
Quando um atributo não é inicializado explicitamente, o valor inicial para ele depende do
tipo:

1- Se o atributo for de tipo int é 0 (zero).


2- Se o atributo for de tipo boolean o valor é false.
3- Se o atributo tiver o seu tipo numa classe o valor é null.

Exemplo 7.6

pag 67
inicializador de membro
class Fisio {
int peso = 70 ;

int sexo = 'f ' ;


} inicializador de membro

O efeito dos inicializadores de membros é o seguinte: por exemplo, imediatamente


após uma instanciação de um objeto da classe Fisio este objeto terá o seguinte
aspecto mostrado abaixo.

peso sexo

70 'f '

instancia da classe Fisio

EXERCÍCIO 7.4 - Resolva e depois execute o programa que está em strb3.java .

7.3.2. Passagem de argumentos para funções


A passagem de argumentos em Java é sempre por valor . Devemos lembrar que se um
argumento for do tipo referência, o valor recebido será a referência do objeto.

EXERCÍCIO 7.5 - Resolva e depois execute o programa que está em strb4.java .


EXERCÍCIO 7.6 - Resolva e depois execute o programa que está em strb5.java .

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

Os índices do array servirão para referenciar as variáveis que o constitui.

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

<tipo> especifica o tipo de cada variável do objeto vetor.

<identificador> dá o nome para a variável que referencia o vetor.

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.

Exemplo 8.1- declaração de uma variável de tipo vetor de int

pag 69
<tipo>[ ] <identificador> ;

Int [ ] Lista ;

A declaração diz que o tipo da variável Lista é vetor de int.


Perceba que neste exemplo nenhum objeto vetor de int foi instanciado. Assim o valor da
variável Lista é null.

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 = new int [3];

A figura abaixo ilustra a situação logo após a atribuição acima.

Lista

objeto vetor de int

8.1. Referenciando os elementos de um vetor - Acesso aos elementos


de um vetor

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:

<identificador> - é o nome da variável que referencia o vetor


<expressão> - o valor da expressão deverá ser o índice da variável do vetor onde se
que ter acesso.
Durante a execução de um programa é verificado se o valor de <expressão> é um índice
válido do vetor. Caso este valor não seja um índice válido, um erro
(na verdade uma exceção) será apresentado.
Exemplo 8.2- Abaixo é mostrado um programa contendo um vetor:

pag 70
class Exemplo {

public static void main(String args[ ] )


{
int vet[ ] = new int[3];
vet[0] =10;
vet[1] = 45;
vet[2] = 70;

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.

EXERCÍCIO 8.1- Resolver e depois executar o programa que está em vetb1.java .


EXERCÍCIO 8.2- Resolver e depois executar o programa que está em vetb2.java .
EXERCÍCIO 8.3- Resolver e depois executar o programa que está em vetb3.java .

8.2. A propriedade length

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.

A figura abaixo esquematiza um objeto vetor definido da seguinte forma:


int A[ ] = new int[3];

pag 71
A

length
variáveis que constituem
o vetor

O valor da expressão A.length é 3

EXERCÍCIO 8.4 – Faça um programa em Java como o seguinte:


• Tenha um vetor de int’s ;
• Para cada variável do vetor, coloque valores arbitrários.
• Exiba: os valores de cada uma das variáveis; o tamanho do vetor a partir da propriedade
length.

8.3. Passando Vetores para os Métodos

EXERCÍCIO 8.5 - Resolva e depois execute o programa que está emvetb4.java .

8.4. Vetores com várias dimensões

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.

Por exemplo, o comando int[ ][ ] A = new int[2][3]; diz o seguinte:


A é o nome de uma variável que armazena uma referencia a um objeto vetor cujos elementos
são variáveis do tipo vetor de int. No caso, temos duas variáveis do tipo vetor de int. Cada uma
destas variáveis, por sua vez, armazena uma referência a um objeto vetor de int em que cada um é
composto por 3 variáveis de tipo int.

A figura abaixo mostra:


a estrutura do vetor referenciado pela variável A
a estrutura do vetor referenciado pelas variáveis do objeto vetor referenciado pela variável A.

pag 72
A

objeto vetor referenciado


pela variável A .
A[o] A[1]

A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2]


objeto vetor referenciado objeto vetor referenciado pela
pela variável A[ 0 ] . variável A[1] .

A sintaxe para declarar uma variável de tipo um vetor com n dimensões é a seguinte:
<tipo><identificador>[ ][ ]...[ ]...[ ] ;

Para se instaciar um objeto correspondente à declaração acima a expressão é:


new <tipo>[<expcte1>].........[<expcten>]

Exemplo 8.3- declarações com vetores com várias dimensões.

int[ ][ ] A = new int [3][5];


Declara uma variável de nome A do tipo vetor de vetor de int ,isto é, com 2 dimensões. Ela
referencia um objeto vetor que é composto por 3 variáveis em que cada uma é do tipo vetor de int.
Cada uma destas variáveis, por sua vez, referencia um vetor com 5 variáveis de tipo int.

char[ ][ ]w = new char [2][3];

Declara um vetor de nome w de tipo vetor de vetor de char. A variável w referencia um


objeto vetor composto por 2 variáveis em que cada uma tem tipo vetor de char. Cada uma destas
variáveis, por sua vez, referencia um objeto vetor que é composto por 3 variáveis de tipo char.

EXERCÍCIO 8.6- Resolva e depois execute o programa que está em vetb5.java .

EXERCÍCIO 8.7 - Seja a seguinte definiçao de classe


class Fisio { int peso;
char sexo;
}

a- qual o significado de Fisio[ ] A = new Fisio[3];


b- qual o significado da expressão A[1].peso
pag 73
c- identifique o problema com a sequência de comandos abaixo:
Fisio[ ] B ;
B[1].peso = 10 ;

EXERCÍCIO 8.8 - Resolva e depois execute o programa que está em vetb6.java .

pag 74
9. Generalizando o Conceito de Classe.

O conceito de Information Hinding

Seja a definição de classe abaixo

class Biometrico { int peso;


char sexo;
}

Dada a seguinte declaraçao e instaciação Biometrico X = new Biometrico( ); então, o


objeto referenciado pela variável X tem o aspecto mostrado na figura abaixo.

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.

objeto da classe biometrico variável de tipo int

peso sexo byte 0 byte 1 byte 2 byte 3

int char

Este processo de se abstrair da representação é um dos conceitos básicos do paradigma da


orientação à objetos.
Quando manipulamos objetos de tipo int, fazemos através de um conjunto de operações e
não pela manipulação direta da representação, isto é, não manipulamos os bytes de uma variável de
tipo int. A manipulação ao nível dos bytes é feita pela implementação da linguagem. Em resumo, o
usuário da linguagem só tem acesso ao objeto de tipo int através das operações que foram definidas
para o tipo (atribuição, operações aritméticas, etc.) .
Esta idéia é também usada nos tipos construídos, isto é, as classes.

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.

9.1. Métodos de Instância

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.

Exemplo de definição de uma classe

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

void inic (int x , int y)


{
peso = x;

sexo = y;
}

Os identificadores dentro dos retângulos são membros da classe (no caso são atributos).

9.2. Aplicando Métodos aos Objetos - Acesso aos métodos

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

onde <identificador> é o nome do objeto sobre o qual se quer aplicar o método

Se para um objeto é aplicado um método, o método é executado.


Se no corpo do método selecionado ocorrem nomes de atributos em que a esquerda deles
não ocorre o operador , então, estes são os atributos do objeto sobre o qual o método esta sendo
aplicado.

Exemplo 9.1

pag 77
class Biometrico
{
int peso ;
char sexo ;
void inic (int x, char y)
{ peso = x ;
sexo = y ;
}
}

class Program {

public static void main(String args[ ] )


{ Biometrico W = new Biometrico( );
W .inic(56, 'm') ; aplicação do método inic
}
}

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

Fazendo isto, estaremos violando a idéia de esconder do usuário a representação do objeto.


Gostaríamos de impedir o acesso aos membros como exemplificado acima. Mostraremos
adiante como se restringe o acesso aos membros.

EXERCÍCIO 9.1 - Resolva e depois execute o programa que está em program1.java .


EXERCÍCIO 9.2 - Resolva e depois execute o programa que está em program2.java .

9.3. Assinatura e Overload


A assinatura de um método consiste do nome do método, do tipo de cada parâmetro formal.
Em uma classe não pode existir métodos com a mesma assinatura. Por outro lado, numa
classe podem existir métodos como o mesmo nome desde que eles difiram nos parâmetros formais,
seja no número ou no tipo ou em ambos.
Dizemos que métodos estão em sobrecarga (overload) se eles têm o mesmo nome e
pertencem a mesma classe.

Exemplo 9.2

class ASS {
int a ;
int b ;
int c ;

void sum (int x, int y )


{ a = x+y; }

void sum (int h)


{b=h;}

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.

EXERCÍCIO 9.3 - Resolva e depois execute o programa abaixo (ass1.java)


EXERCÍCIO 9.4 - Resolva e depois execute o programa abaixo (ass2.java)

9.4. Restringindo o Acesso aos membros de uma classe


Podemos controlar o acesso aos membros de uma classe através dos especificadores de
acesso. Inicialmente, vamos examinar o significado destes especificadores quando as classes estão
definidas em mesmo arquivo fonte. Depois, daremos a generalização deste assunto.
São os seguintes os especificadores de acesso aos membros

• private- serve para especificar que os membros de uma classe com


este especificador de acesso só poderão ser referenciados (usados) nos
métodos da classe.

• public- serve para especificar que os membros de uma classe poderão


ser referenciados em métodos de quaisquer outras classes mesmo que
estas classes estejam definidas em outros arquivos fontes (isto ficará
claro mais tarde).

• protected- (veremos mais adiante).

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.

A sintaxe de declaração de membro com o especificador de acesso passa a ser:

<especificador de acesso> <declaração do membro>


Exemplo 9.3
class Exemplo93 {
private int a;

private char b;

public int f( )

{ a = a+1;}
}

Na figura, os especificadores de acesso estão dentro dos retângulos sombreados.


pag 80
EXERCÍCIO 9.5 - Resolva e depois execute o programa que está em acess1.java .

9.5. Métodos Construtores

Dada uma classe, sempre é executado um método de instância especial denominado


construtor quando é instanciado um objeto desta classe (usando o operador new).

Características dos métodos construtores


• Tem o mesmo nome da classe.

• Não têm tipo de retorno, diferente do que acontece com os


demais métodos.

• Nunca são aplicados aos objetos da classe com o uso do

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 ;

biometrico (int x, char y)


{ peso = x;
sexo = y ;
}

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.

new biometrico (56,'f')

parâmetros passados para o construtor

9.6. Construtor default

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;

int SUM (int x, int y)


{
return x + y ;
}
}

Na classe acima não é definido explicitamente um construtor portanto, será gerado um


construtor default
Logo a instanciação de um objeto da classe será por exemplo:
CONS j = new CONS( );
Exemplo 9.6

pag 82
class CONS {
int a;
int b;

CONS (int j , int k)


{ a = j; construtor definido
b = k; explicitamente.
}

int SUM (int x, int y)


{
return x + y ;
}
}

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.

EXERCÍCIO 9.6 - Resolva e depois execute o programa abaixo (constru1.java)


EXERCÍCIO 9.7 - Resolva e depois execute o programa abaixo (constru2.java)
EXERCÍCIO 9.8 - Resolva e depois execute o programa abaixo (constru3.java)
EXERCÍCIO 9.9 - Resolva e depois execute o programa abaixo (constru4.java)

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.

Gerado pelo Compilador

pag 83
class Alfa { int a ; class Alfa { int a ;
int b ; int b ;

void ge(int x , int y) static void ge(Alfa this,int x , int y)


{ a = 2*x; { this.a = 2*x;
b = 3*y;
this.b = 3*y;
}
} }
}

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 ;

void met1 ( int x )


{ this.x = x ; }
este é parâmetro formal

este se refere ao membro


void met2 (int y)
{ this. y = y ; }
este é parâmetro formal
}
este se refere ao membro

EXERCÍCIO 9.10 - Resolva e depois execute o programa que está em this1.java .


EXERCÍCIO 9.11 - Resolva e depois execute o programa que está em this2.java .
9.8. Membros Estáticos - Varáveis de Classe

9.8.1. Atributos Estáticos.


Até agora vimos que dada uma classe, uma instância de uma classe é uma composição de
atributos. Para cada instância uma área de memória fabricada em correspondência a cada atributo.
Entretanto, é possível especificar que a área de memória correspondente a um atributo será única
para qualquer instância da classe. Este atributo é denominado de atributo estático.
Para especificar que um atributo é estático basta prefixar à declaração dele a palavra
reservada static.

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

Os atributos estáticos também são conhecidos por variáveis de classe.


Se T é uma classe e k é um atributo estático então, T.k referencia este atributo. Nos
métodos da classe T onde o atributo estático k foi definido ele não precisa ser referenciado como
T.k basta referenciá-lo como k. Por outro lado, caso o atributo estático k da classe T tenha que ser
referenciado em outra classe então temos que referenciá-lo como T.k .

EXERCÍCIO 9.12 - Resolva e depois execute o programa que está em static1.java .


EXERCÍCIO 9.13 - Resolva e depois execute o programa que está em static2.java .

9.8.2. Métodos estáticos


Diferente dos métodos de instância, os métodos estáticos não são aplicados as instâncias da
classe . Assim, no corpo de um método estático, só podem ocorrer membros estáticos. Caso
ocorra um membro não estático então, ele deverá fazer parte de uma expressão de seleção de
membro. Como vimos, os métodos estáticos fazem o papel de sub-rotinas (funções em C).
Para especificar que um método é estático basta prefixar a palavra reservada statitic no seu
"cabeçalho".
A sintaxe de chamada de um método estático é a seguinte

<nome da classe>opc . <nome do método estático>(<lista de parâmetros formais>)

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 ;

static void conta_inst ( )


{ definição do método estático
ninst = ninst + 1;
}

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
}

No exemplo acima, quando se instancia um objeto da classe Mest, o valor armazenado em


ninst é incrementado.

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 inic (int x, String n )


{ nfunc = x;
nome_func = n ;
}

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

As figuras abaixo mostram o desenho de uma instância da classe Funcionario e de uma


instância da classe Motorista.

instância da classe Funcionario

nfunc nome_func

int String

instância da classe Motorista

nfunc nome_func Habilitação

int String int

atributos herdados da
classe Funcionario atributo próprio da
classe Motorista

A classe Motorista terá os seguintes métodos


• Os métodos herdados da classe funcionario
. inic e exibe_func
• Os metodos definidos na classe motorista
. inicHab

pag 88
• Os únicos métodos que não são herdados são os
construtores.

• Outro fato importante é que em Java não existe


herança múltipla, isto é, uma classe ser ao mesmo
tempo subclasse de duas ou mais classes.

EXERCÍCIO 10.1 - Resolva e depois execute o programa que está em her1.java .


EXERCÍCIO 10.2 - Resolva e depois execute o programa que está em her2.java .
EXERCÍCIO 10.3 - Resolva e depois execute o programa que está em her3.java .

10.1. Acesso aos membros da classe Base com super


Nada impede que membros da classe base tenham o mesmo nome de membros da classe
derivada. Suponha que m seja nome de membro da classe base e que na classe derivada também
tenha um membro com mesmo nome. Suponha que num método da classe derivada apareça a
expressão m então, este se refere ao membro da classe derivada por outro lado, se quiséssemos nos
referir ao membro m da classe base a expressão deveria ser super.m caso m seja um atributo ou
super.m(<lista de valores>) caso m seja método de instância. Além disto, o uso do super só pode
ser feito no corpo de métodos de instância.

EXERCÍCIO 10.4 - Resolva e depois execute o programa que está em super1.java .

10.2. A Classe base com construtor

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

onde, <lista de parâmetros> são os parâmetros que deverão ser passados


para o construtor da classe base.
10.3. Herança implícita da classe Object
A classe Object é uma classe que já esta definida no JDK que estudaremos em detalhes mais
adiante.
A classe Object se relaciona com qualquer classe da seguinte forma:
Toda classe que não é explicitamente (usando o extends)
subclasse de outra é automaticamente subclasse da
classe Object.

Desta forma, qualquer classe com exceção de Object, é diretamente ou indiretamente


subclasse de Object. Portanto, qualquer classe vai herdar os métodos e atributos públicos e
proteced da classe Object.
pag 89
Exemplo:

class Beta { int a;


int b;

void inic(int x, int y)


{ a = x;
b = y;
}
}

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;

void inic(int x, int y)


{ a = x;
b = y;
}
}

10.4. Impedindo Herança - final


Em java existe um mecanismo que impede que se estenda de uma classe. Para isto basta
colocar na definição da classe que ela é final.

Exemplo 10.2
final class Gama {

definição de métodos e
atributos
}

Portanto dará erro de compilação a definição de classe abaixo

class Delta extends Gama


{

definição de métodos e
atributos
}

EXERCÍCIO 10.5- Resolva e depois execute o programa que está em super2.java .


EXERCÍCIO 10.6- Resolva e depois execute o programa que está em super3.java .

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:

Xis g = new Xis( );


Ypslon f = new Ypslon( );

Considere agora a seguinte atribuição


g = f;
Desta forma, g passa a referenciar um objeto da classe derivada. Note que a variável g foi
declarada para referenciar objetos da classe Xis (classe base) e não da classe Ypslon (classe
derivada). É automática a conversão da referência da classe derivada (lado direito da atribuição)
para a classe base (lado esquerdo da atribuição). A idéia básica é que todo objeto da classe derivada
também é um objeto da classe base.
Vamos supor que tanto a classe Xis como a classe Ypslon tenham um método M com
mesma assinatura e mesmo tipo de retorno(isto é importante) dizemos então que o método M da
classe Ypslon sobrescreve (overrady) o correspondente método da classe Xis. Vamos supor a
seguinte chamada de método logo após a atribuição acima

g.M( lista de parâmetros );

Qual método M será executado o da classe Xis ou da classe Ypslon.?

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

Ypslon f = new Ypslon( );


g=f;
g.m( ) ; o método m a ser executado é o da classe Ypslon

}
}

Conforme esta assinalado acima, g é usado para referenciar objetos da classe Xis. Depois da
atribuição, g passa a referenciar objeto da classe Ypslon.

EXERCÍCIO 11.1 - Resolva e depois execute o programa que está em poli1.java .


EXERCÍCIO 11.2 - Resolva e depois execute o programa que está em poli2.java .

pag 92
12. Classes Abstratas

A idéia de classes abstratas é de representar o conceito de generalização.


Em termos práticos, isto funciona da seguinte forma: uma classe, mais geral (a abstrata) é
definida com o propósito de que dela serão derivadas as classes mais especializadas. Da classe mais
geral não serão instanciados objetos e sim das mais especializadas.
Na classe abstrata, não serão definidos todos os métodos mas eles serão simplesmente
declarados e as classes derivadas deverão implementá-los.
Por exemplo, seja a classe funcionário, dada anteriormente, vamos fazer com que ela seja
abstrata, isto é, vamos tomá-la como classe base, as classes motorista e secretária são derivadas
dela.

abstract class Funcionario { int nfunc ; /*numero funcional */


String nome; /* nome do funcionario */

abstract void exibe( );

A palavra reservada abstract que aparece prefixando a declaração da classe funcionario


indica que se trata de uma classe abstrata. A palavra reservada abstract que aparece prefixando a
definição do método exibe, indica que este método é abstrato, isto é, ele não tem a definição ( o
corpo do método). Somente classes abstratas podem ter métodos abstratos.
O método exibe será implementado nas classes Motorista e Secretária e será usado para ler
os atributos específicos destas classes além de nfunc e nome (que são herdados). Abaixo são dadas
as definições das classes motorista e secretária

class Motorista extends Funcionario


{
int Hab ; /* numero da habilitação */
void exibe( )
{ System.out.println("numero funcional: "+ nfunc);
System.out.println ("nome: "+ nome);
System.out.println ("habilitação numero: " + Hab);
}
}

Note que na classe Motorista é implementado o método exibe. Na superclasse este método é
abstrato.

A classe Secretária está definida abaixo

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

Na classe Secretária também é implementado o método exibe

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.

abstract <tipo de retorno> <identificador> ;

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>

Isto é, colocamos a palavra reservada abstract prefixando a definição.


É erro de compilaçao instaciar objetos
de uma classe abstrata.

EXERCÍCIO 12.1 - Resolva e depois execute o programa que está em abast1.java .

Somente classes abstratas podem ter métodos


abstratos.

Seja A uma classe abstrata e B uma classe derivada de


A. Para que a classe B não seja abstrata é necessario
que todos os métodos que são abstratos em A devem
ter implementação em B.

EXERCÍCIO 12.2 - Resolva e depois execute o programa que está em abst2.java .


EXERCÍCIO 12.3 - Resolva e depois execute o programa que está em abst3.java .
EXERCÍCIO 12.4 - Resolva e depois execute o programa que está em abst4.java .

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

Suponha agora as seguintes declarações:

pag 95
A1 x = new A1( );
A2 y = new A2( );
A3 z = new A3( );

Prosseguindo, com a seqüência de comandos:


Kw=x ;
w.M( ); (será executado o método M da classe A1 )

Prosseguindo com seqüência:


w = y;
w.M( ); (será executado o método M da classe A2 ).

Prosseguindo com seqüência:


w = y;
w.M( ); (será executado o método M da classe A2 ).

É importante observar no exemplo o seguinte:


• w referenciou objetos de classes que entre elas não existe relação de herança.
• quando fizemos w.M( ) a escolha do método teve como base a classe do objeto e não o tipo da
variável que o referencia, no caso w serve para referenciar objetos da classe K.

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

interface <nome da interface> { <métodos sem implementação> }

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.

Exemplo 13.1- Este exemplo é a concretização da discussão acima

pag 96
interface K {
definição da interface
void M( );
}

class A1 implements K { int s;


public void M( )
{System.out.println(" M da classe A1");}
void incr( )
{ s = s+1;}
}

class A2 implements K { int t;


public void M( )
implementação
{System.out.println(" M da classe A2");}
do método M
void sub( )
{ t = t-1;}
}
class A3 implements K { int d;
public void M( )
{System.out.println(" M da classe A3");}
void dobra( )
{ d = d*2;}
}

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

EXERCÍCIO 13.1 - Resolva e depois execute o programa que está em inter1.java .


EXERCÍCIO 13.2 - Resolva e depois execute o programa que está em inter2.java .

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.

Qual atitude tomar quando o resultado produzido é uma exceção ?

RESPOSTAS POSSÍVEIS

1- Prosseguir no fluxo de execução do programa


3- Desviar o fluxo de execução do programa para rotinas especiais assim que o
resultado seja uma exceção.
2- Parar a execução do programa assim que um resultado seja uma exceção.

Análise das Respostas

Resposta 1- Prosseguir no fluxo de execução do programa pode implicar na propagação da


exceção e também na geração de novas exceções por exemplo: a execução do método de abertura
de arquivo, utilizado no exemplo acima, pode gerar uma exceção caso não seja passado um nome
de arquivo existente. Esta exceção pode ser propagada se em seguida pedíssemos para ler o tal
arquivo.

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.

Resposta 3- Desviar o fluxo de execução do programa para rotinas especiais quando


exceções são produzidas, por exemplo: uma rotina especial que chame novamente o método de
abertura de arquivos quando o nome passado ao método não seja de um arquivo existente. Desta
forma, se dá chance para se ir em frente na execução do programa.

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.

• as rotinas manipuladoras de exceção, para onde será desviado


o fluxo de programa,quando aquelas linhas do código
produzirem exceções.

Como idéia inicial, é mostrado abaixo um esquema de como isto é feito:

----------
---------- linhas de código
----------
----------

try1 { linhas de código que produz exceção}

catch1 ( ){ linhas de código que trata a exceção}

----------
----------
---------- linhas de código
----------
try2 { linhas de código que produz exceção}

catch2 ( ){ linhas de código que trata a exceção}

----------
----------
---------- linhas de código
----------
.
.
.

tryn { linhas de código que produz exceção}

catchn ( ){ linhas de código que trata a exceção}

----------
----------
----------
----------

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.

Podem existir várias espécies de exceções:

. por causa das operações aritméticas


. por causa de operações com arquivos
. acesso à arrays com índices indevidos

Em java, as várias categorias de exceções é expressa através de uma hierarquia de classes de


exceções. A raiz desta hierarquia começa pela classe exception . Por herança, são definidas classes
mais especificas de exceções.

Vamos examinar mais detalhadamente o comando try - catch

14.1. A cláusula catch

A sintaxe da clausula catch é a seguinte:

catch ( <declaração do parâmetro formal>) {<comandos>}

onde <declaração de parâmetro formal> é por sua vez

< classe de execeção> <identificador>

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.

Abaixo mostramos a forma da estrutura try-catch

try{linhas de código que produzem execeçoes de várias classes de execeção }

catch (<classe de exceção1> <identificador> ) { <comandos que tratam a exceção>}


catch (<classe de exceção2> <identificador> ) { <comandos que tratam a exceção>}
catch (<classe de exceção3> <identificador> ) { <comandos que tratam a exceção>}
.
.
.
catch (<classe de exceçãon> <identificador> ) { <comandos que tratam a exceção>}

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.

EXERCÍCIO 14.1- Resolva e depois execute o programa que está em e1.java .


EXERCÍCIO 14.2- Resolva e depois execute o programa que está em e2.java .

14.2. A clausula finally


Pode-se acrescentar a clausula finally à estrutura try-catch. Colocando-se o finally fica
opcional colacar as clausulas catch. Então a estrutura try-catch-funally fica:

try{linhas de código que produzem execeçoes de várias classes de execeção }

catch (<classe de exceção1> <identificador> ) { <comandos que tratam a exceção>}


catch (<classe de exceção2> <identificador> ) { <comandos que tratam a exceção>}
catch (<classe de exceção3> <identificador> ) { <comandos que tratam a exceção>}
.
.
.
catch (<classe de exceçãon> <identificador> ) { <comandos que tratam a exceção>}

finally {comandos}

A estrutura funciona como anteriormente explicado acrescentado o seguinte: o bloco finally


é sempre executado. Assim o uso principal do finally é fazer "house-keeping". Por exemplo, em um
programa que manipula arquivos, devemos sempre fechalos que ocorra ou não exceção. Podemos
então colocar o fechamento de arquivos dentro do bloco finally.

EXERCÍCIO 14.3 - Resolva e depois execute o programa que está em e3.java .


EXERCÍCIO 14.4 - Resolva e depois execute o programa que está em e4.java .

14.3. - Produzindo Exceçoes


Para que um método produza (lançar) um objeto-exceção de uma classe de exceção
especificada, nele é usado o comando throw cuja sintaxe é mostrada abaixo:

throw new <classe de execeção>( <parâmetros do construtor> );

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;

void Atira(int x) throws IOException


{
if (x <0)
throw new IOException( );
else
System.out.println("maior que zero);
}
}

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;

void teste(int k) throws IOException


{ Mostra x = new Mostra( );
x.Atira(k)
}
}

Em resumo, será acusado erro na compilação de:

class Usa {
int d;

void teste(int k)
{ Mostra x = new Mostra( );
x.Atira(k) ;
}
}

Não é obrigatório tratar exceções da classe RuntimeException e de suas subclasses. É


obrigatório o tratamento de exceções de outras classes

14.4. Fazendo uma Classe de Exceção


Para fazer uma classe de exceção basta definir uma classe derivada da classe Exception.

EXERCÍCIO 14.5 - Fazer uma classe de exceção e usá-la


EXERCÍCIO 14.6 - Estudar a hierarquia de classes de exceção do JDK.

pag 103
15. Pacotes - Organização dos Programas

Para facilitar a organização de programas, a linguagem possui um mecanismo que permiti


definir Pacotes.
Um pacote é um mecanismo para especificar um grupo de classes que estão de certa forma
relacionadas num contexto de um projeto. Formalmente, os membros de um pacote podem ser
classes, pacotes ou interface. Portanto, o relacionamento de que um pacote ou classe ou interface é
membro de um pacote é expressa através de uma estrutura hierárquica (árvore) de
classes/interfaces.

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 .

Na árvore abaixo, o símbolo @ é usado para dizer que o nó é um pacote e o símbolo # é


usado para dizer que o nó é uma classe. Adotaremos esta representação nas árvores que repesentam
relacionamentos pacote e classes.

@P

Q
#c1 #c2 #c3 @

# a1

15.1. Nome simples, Nome Completo e ambigüidade

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.

Um pacote é sempre referenciado por seu nome completo

Se um pacote tem um nome simples W qualquer e e ele é raiz da arvore então, o seu nome
completo é W.

Seja a seguinte árvore de pacotes e classes

pag 104
@P P

Q P.Q
#c1 #c2 #c3 @
V P.Q.V
# a1 @

Os nomes dos pacotes assinalados pelas flechas estão a direita delas.

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

Seja a seguinte árvore de pacotes e classes

@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

15.1.2. Unicidade dos Nomes

Unicidade dos nomes Completos


Note que é único o nome completo de um pacote ou classe.
Consequentemente não existem dois nomes simples de pacote e/ou interface e/ou classe
iguais que sejam membros de um mesmo pacote. O princípio é o seguinte: fixado um contexto, um
nome só pode se referir a um só ente (classe, interface, pacote). Assim, no contexto do pacote P.Q
só pode existir uma classe com nome simples 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:

package <nome completo do pacote>;

Exemplo: Seja a hierarquia de pacotes e classes mostrada na figura abaixo

@P

@ F @K

#c1 #c2 #c3 #c4

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á

package P.K; /*declaração do pacote */

class c4{ ----


-----
------
}

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.

Exemplo - as definições da classes c1 e c2 poderiam estar na mesma unidade de


compilação.

pag 106
package P.F; /*declaração do pacote */

class c1 { -----
-----
-----
}

class c2 { -----
-----
-----
}

15.2.1. O escopo de nome de uma classe


Dado um pacote P, o nome simples de uma classe pertencente a este pacote é conhecido nas
unidades de compilação onde são definidas classes membros de P.

Seja a árvore de classe e pacotes abaixo

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

15.2.2. Classe Pública e a declaração import

Vamos supor, como exemplo, a hierarquia de pacotes e classes esquematizada abaixo


pag 107
@P

@ F @K

#c1 #c2 #c3 #c4

Seja a unidade de compilação onde é definida a classe P.F.c1

package P.F;

class c1 {
definições de membros

c3 x ; a classe c3 não pertence ao


pacote P.F
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:

<nome da classe pública>.java

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.

Exemplo: este exemplo mostra como corrigir o erro de compilaçao apontado


anteriormente.
@P

@ F @K

#c1 #c2 #c3 #c4

pag 108
package P.K;

public class c3 { <definiçoes dos membros>}


O nome do arquivo onde está a unidade de compilação acima é c3.java

package P.F;

class c1 {
definições de membros

P.K.c3 x ; a classe c3 não pertence ao


pacote P.F
definições de membros
}

Agora, podemos usar o nome da classe c3 mas pelo nome completo.

15.2.3. Declaração import


Como vimos no último exemplo, tivemos que usar o nome completo de uma classe, isto
pode consumir tempo e pode-se cometer erros de digitação quando se tiver que usar repetidamente
nome de várias classes de um mesmo pacote nas definições de classes de outros pacotes. Para
solucionar isto, existe a declaração import onde se especifica o nome completo de uma classe.
Assim, ao invés de se usar o nome completo de uma classe Xis, pertencente a um pacote Alfa, na
unidade de compilação onde se define uma classe Y( pertencente a um outro pacote), colocamos
nesta unidade de compilação declaração import Alfa.Xis; e usamos o nome da classe Alfa.Xis
somente como Xis.

A sintaxe da declaração import é a seguinte:

import <nome completo da classe>;

A declaração import deve preceder a definição de todas as classes e interfaces da unidade de


compilação.
Em uma unidade de compilação pode existir mais de uma declaração import.
Exemplo: mostramos a definição da classe c1, feita acima, usando a declaração import.

pag 109
package P.F;

import P.K.c3 ; nome completo

class c1 {
definições de membros

c3 x ; usando o nome simples

definições de membros
}

Uma outra sintaxe para a declaração import é quando queremos usar várias classes de um
mesmo pacote.

import <nome completo do pacote> *;


onde o * substitui o nome simples de qualquer classe pertencente ao pacote.

Exemplo: Este exemplo usa o diagrama de classes e pacotes mostrado acima.

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
}

15.3. Repesentação de Pacotes e Unidades de Compilação

A questão é como estarão armazenados os pacotes e as unidades de compilação em um


particular sistema operacional. Em resumo, como estarão representados os pacotes e as unidades de
compilação em um sistema operacional.

Vamos nos restringir em sistemas operacionais onde o sistema de arquivos é hierárquico


(diretórios subdirectórios, etc..) . Assim, a tal representação será feita usando o sistema de arquivos
da seguinte forma:

Unidades de compilação serão armazenadas em arquivos que terão extensão .java.


lembrando que o nome deverá ser o nome da classe que é pública

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

As linhas pretas mostram as sub-árvores onde estão representados as hierarquias de pacotes.


Note que esta hierarquia começa a partir dos diretórios a:\D\G e a:\B\C
Em relação a este diretório o nome do diretório assinalado pelo seta 1 é p1 ele representa o
pacote de nome completo p1. O diretório assinalado pela seta 2 tem nome relativo
p1\t1 eo correspondente pacote tem nome completo p1.t1

A variável de ambiente CLASSPATH especifica o diretório a parir do qual se inicia a a


hirarquia de classes.

Com respeito ao exemplo acima esta especificacao é : classpath = a:\D\G; a:\ B\C

A figura abaixo mostra como a estrutura de pacotes e classes é representada. À esquerda da


linha vertical está desenhada uma estrutura de pacotes e classes. e à direita é a representação desta
estrutura em um sistema de diretórios de num disco que está por exemplo, no driver b

pag 111
b:
@P \

@ F @K
test
e
#c1 #c2 #c3 #c4
pg
c P

K
F

c1.jav c2.jav c3.jav c4.jav


a a a a

As linhas em negrito mostram o mapeamento de pacotes classes (figura a esquerda) em diretórios e


arquivos.
Supondo que a variável de ambiente CLASSPATH tenha sido especificada como
classpath = b:\teste
Temos o seguinte:
a classe cujo nome completo de classe é P.K.c3 é representada pelo arquivo de nome P\K\c3.java
e arquivo armazena o texto em Java que define a classe.

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.

Existem duas formas para se fazer isto:


• manualmente
• ou através da opção -d do compilador que é mais fácil

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
}

a compilaçao seria assim: javac -d teste.java

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

15.4.1. Espeficadores de acesso membro


Se o especificador de acesso a um membro m de X for public então m é acessível em
qualquer unidade de compilação onde X é acessível.
Se o especificador de acesso a um membro m de X for private então m só pode ser
acessado pelos métodos da classe X
Se o especificador de acesso for protected para o membro m
. então m pode ser acessado em qualquer classe do mesmo pacote ao qual X pertence
. m pode ser acessado por qualquer classe T derivada de X

Se o especificador de acesso for inexistente para o membro m


Então, m é acessível em qualquer classe do mesmo pacote ao qual a classe X pertence.

Os exercícios que seguem se referem as hierarquias de classes e pacotes desenhadas abaixo

@w @p
1

#ap2
#ap4 @p #ap5
#ap3 @ #ap0
2
T

#c1 #ap1 #a1


#a2
#c2
#c3

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 .

16.1. A classe java.lang.Object


Todas as classes são derivadas direta ou indiretamente da classe java.lang.Object. Uma
classe que não é derivada de outra é implicitamente derivada da classe java.lang.Object .
Alguns metódos de java.lang.Object são "redefinidos" (override) por suas classes derivadas.
Nesta classe não são definidas variáveis de instância somente construtores e métodos.

EXERCÍCIO 16.1- Localize no JDK a documentação da classe Object e estude os seguintes


métodos e construtores:
public Object ( )
public boolean equals (Object x)

EXERCÍCIO 16.2 - Resolva e execute o programa que está em ob1.java .


EXERCÍCIO 16.3 - Resolva e execute o programa que está em ob2.java .

16.1.1. O método finalize


Diferente da linguagem C++, em Java não existe método destrutor.
Na classe Object é definido um método com a seguinte assinatura:
public void finalize( )
Quando um objeto de uma classe qualquer não é mais referenciado, sobre ele é
automaticamente aplicado o método finalize da classe Object. Este método não faz nada na
classe Object. Tipicamente, este método é redefinido na classe onde se deseja que sejam
devolvidos recursos antes da desalocação de uma instância da classe.

EXERCÍCIO 16.4- Resolva e depois execute o programa que está em fina.java .

16.1.2. Clonagem – o método clone


Na classe Object é definido um método que permite obter cópias de um objeto. Este
método tem a seguinte assinatura: public Object clone( ). Para que um objeto possa ser
clonável, é necessário que sua classe implemente a interface clonable, o número de métodos
especificados é nenhum. Esta interface é usada para indicar que os objetos de uma classe são
clonáveis.
16.2. A classe java.lang.String
Objetos desta classe representam seqüências de caracteres.
Um aspecto importante da classe é que não existe método que altere um objeto da classe.

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)

EXERCÍCIO 16.6- Resolva e depois execute o programa que está em string1.java .


EXERCÍCIO 16.7- Resolva e depois execute o programa que está em string2.java .
EXERCÍCIO 16.8- Resolva e depois execute o programa que está em string3.java .

16.3. Classes Empacotadoras

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.

Para cada tipo básico existe uma classe empacotadora correspondente.

TIPO BASICO CLASSES WRAPER CORRESPONDENTE


Int Integer
Double Double
Float Float
Boolean Boolean
Long Long
Car Character

A class Number é a superclasse das classes Integer, Double, Float, Long

Cada classe Wraper tem métodos que convertem o seu objeto no valor correspondente ao seu tipo
básico.

16.3.1. A classe java.lang.Integer


Objetos desta classe representam um valor de tipo int.
EXERCÍCIO 16.9- Localizar a documentação da classe Integer e estudar os seguintes métodos:

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

EXERCÍCIO 16.10- Resolva e depois execute o programa que está em int1.java .


EXERCÍCIO 16.11- Resolva e depois execute o programa que está em int2.java .

16.4. A classe StringBuffer


Um objeto da classe StringBuffer representa um vetor de caracteres. Diferente da
classe String, um objeto da classe StringBuffer pode ser alterado.

EXERCÍCIO 16.12- Estudar os seguintes métodos construtores da classe StringBuffer:

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)

EXERCÍCIO 16.13- Localize na classe String um método contrutor que transforme um


StringBuffer em um String.

EXERCÍCIO 16.14- Faça um programa com as seguintes etapas:

1- Instancie um StringBuffer usando o seguinte construtor: public StringBuffer( ).


2- Aplique sobre o objeto obtido na etapa 1 os métodos capacity e length e exiba o retorno destes
métodos.
3- Usando o método append(String str), acrescente caracteres ao stringbuffer de forma que a cadeia
resultante seja: EMERGENCIA .
4- Aplique novamente sobre o stringbuffer os métodos capacity e length e exiba os valores de
retorno.
5- Usando o método setCharAt(char c), transforme o stringbuffer para OMERGENCIA.
6- Aplique sobre o stringbuffer o método append(String str) para acrescentar no final a string:
NAVIO AFUNDANDO .
7- Aplique sobre o stringbuffer os métodos length e capacity e exiba os valores de retorno.

A solução deste exercício está no arquivo strin.java .

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.

Вам также может понравиться