Professional Documents
Culture Documents
e Orientao a Objeto
Autor: Lucas Medeiros de Freitas
Verso 1.0
ndice
I - Fundamentos da linguagem Java e Orientao a Objeto
1. Primitivos, Classes, Objetos e Enumeraes
1.1. Variveis
1
1
1
1.1.1. Primitivos
1.2.1. Classes
1.2.2. Objetos
1.3. Array
1.4. Enumeraes
10
10
10
10
12
12
12
4.1.1. Extenso
12
13
14
i
14
14
14
14
15
5. Escopo de variveis
16
16
17
18
19
19
19
20
20
20
21
22
22
23
24
25
25
7. Membros static
26
26
26
ii
8. Membros final
8.1. Variveis final
27
27
27
28
28
9. Controle de fluxo
29
9.1. Condicionais
29
9.1.1. if-else
29
9.1.2. switch
30
9.2. Loops
31
9.2.1. while
31
9.2.2. do-while
31
9.2.3. for
32
10. Construtores
32
32
33
11. Encapsulamento
11.1. Getters e Setters
12. Relacionamento entre classes
34
34
35
12.1. Associao
35
12.2. Agregao
36
12.3. Composio
36
12.4. Herana
36
39
14. Interfaces
40
iii
42
16. Polimorfismo
42
44
49
49
50
II - Referncias bibliogrficas
51
iv
1.1.1. Primitivos
Primitivos so os tipos mais bsicos de dados em Java, por isso possuem este nome. So eles que do origem a todos os
tipos de dados mais avanados, como os objetos. Um espao na memria reservado sempre que um primitivo
declarado, e cada tipo primitivo ocupa um determinado espao em bits na memria.
Variveis primitivas podem ser declaradas como variveis de classe (static), variveis de instncia, parmetros de mtodos
ou variveis locais.
Observao
Diferente das variveis de referncia, as variveis de tipo primitivo recebem como valor o real contedo da varivel.
O valor de um tipo primitivo sempre copiado.
Ex: int x = 1; // x recebe uma cpia do valor 1
int y = x; // y recebe uma cpia do valor de x
x = x + 2; // x vira 3 mas y continua valendo 1
Java possui oito tipos primitivos:
byte
short
int
long
char
double
float
boolean
Uso
Bits
Bytes
boolean
true ou false
N/D
N/D
---
---
char
caractere Unicode
16
\u0000 (0)
\uFFFF (65535)
byte
inteiro
-2 7
2 7 -1
short
inteiro
16
-2 15
2 15 -1
int
inteiro
32
-2 31
2 31 -1
long
inteiro
64
-2 63
2 63 -1
float
ponto flutuante
32
n/d
n/d
double
ponto flutuante
64
n/d
n/d
Tipos inteiros
Todos os tipos inteiros em Java, com exceo do char, so assinalados, ou seja, podem ser positivos ou negativos. O bit
mais esquerda representa seu sinal ( 1 = negativo, 0 = positivo ). Em Java, h trs maneiras de representar inteiros:
decimal (base 10), octal (base 8) e hexadecimal (base 16).
Ex:
00010011: valor positivo
10010011: valor negativo
Declarando inteiros decimais:
int um = 1;
int seis = 6;
Os inteiros octais so representados adicionando um zero no incio e podem ter at 21 posies alm do zero:
int um = 01;
int dois = 02;
int oito = 010;
2011 Lucas Medeiros de Freitas | lucas@hachitecnologia.com.br
Hexadecimais tambm so declarados como int e podem ter at 16 dgitos alm do 0x:
int um = 0x01;
int dois = 0x02;
int oito = 0x08;
int x = 0x7fffffff;
int y = 0xDeadCafe;
Por padro, os literais inteiros so definidos como int. Para se declarar um inteiro como long basta adicionar o sufixo F ou
f.
Ex:
long x = 76098L; // repare o sufixo L no literal
long y = 0xDeadCafel; // repare o sufixo l no literal
Observao
Os hexadecimais no so case sensitive em Java, ou seja, tanto 0xDEAD quanto 0xdead so vlidos.
O primitivo char
O char classificado como um primitivo inteiro no assinalado. O primitivo char recebe como literal um nico caractere
Unicode de 16 bits entre aspas simples.
Declarando um char:
char a = a;
char x = x;
O char tambm pode receber como literal o valor Unicode do caractere. Para isto, basta acrescentar o prefixo \u ao valor.
Ex:
char z = \u005A; // valor Unicode do caractere Z
Observao
Por se tratar de um inteiro de 16 bits no assinalado, o char no aceita valor negativo como literal. Seu intervalo vai
de 0 a 65535.
Ex: char a = 0x982; // literal hexadecimal
char b = 786; // literal inteiro
char c = (char) 70000; // necessrio o typecast devido ao valor 70000 estar fora do intervalo do char
char d = (char) -41; // necessrio o typecast devido ao valor -41 estar fora do intervalo do char
1.2.2. Objetos
Objetos so instncias de classes concretas. Os objetos so tipos de dados mais avanados, que podem conter tipos
primitivos e outros objetos. Em Java, um objeto criado utilizando o operador new.
Ex:
1.3. Array
Em Java, array um objeto que contm um conjunto de variveis de mesmo tipo, que podem ser primitivos ou referncias
a objetos.
No obrigatrio informar o tamanho do array em sua declarao. Declarando um array:
Por ser um objeto, o array guardado no heap da JVM e para inicializ-lo utilizamos o operador new. O array tem tamanho
fixo e para inicializ-lo obrigatrio informar seu tamanho. Inicializando um array:
char[] var4;
a[0] = 1;
a[1] = 1;
a[2] = 1;
String[] var5 = { "conteudo1", "conteudo2", "conteudo3" }; // array de String j construdo, com 3 posies
Carro[] carros = { vectra, new Carro("Astra"), new Carro("Celta") }; // array de Carro j construdo, com 3 posies
Para percorrer os itens de um array podemos, por exemplo, fazer um loop com o for:
1 heap a ra de dados onde todas as instncias de objetos e vetores so alocados, e compartilhada por todos os threads. O heap criado na inicializao
da mquina virtual (JVM). O heap tambm conhecido como Pilha de lixo coletvel.
meuArray[0] = a;
meuArray[0][0] = 1;
meuArray[0][1] = 2;
meuArray[1] = b;
meuArray[1][0] = 1;
meuArray[1][1] = 2;
meuArray[1][2] = 3;
1.4. Enumeraes
Um Enum (enumerao) um tipo especial de classe. basicamente uma lista de constantes enumeradas e est disponvel
a partir da verso 5 do Java. O Enum foi criado com o intuito de impedir que valores inesperados sejam recebidos em um
trecho do seu cdigo, impedindo com isso que erros sejam lanados em tempo de execuo.
Imagine, por exemplo, que voc tenha um Barco no rio Amazonas, no estado do Amap, e que este viaje apenas pelos
municpios deste estado. Voc dever ter na classe Barco um mtodo que recebe como parmetro a cidade para a qual o
barco deve se deslocar. Como voc faria? Bom, voc poderia usar como parmetro um objeto do tipo String, ou talvez um
inteiro com o cdigo da cidade. Seu cdigo ficaria parecido com esse:
class Barco {
public void viajaPara(String cidade) {
System.out.println("Viajando para " + cidade);
}
}
O cdigo funcionar perfeitamente, mas voc correria o risco de um usurio informar uma cidade inesperada, veja:
enum CidadesNavegaveis {
AMAPA, CALCOENE, FERREIRA_GOMES, LARANJAL_DO_JARI, MACAPA, MAZAGAO, OIAPOQUE,
PORTO_GRANDE, SANTANA, SERRA_DO_NAVIO, TARTARUGALZINHO, VITORIA_DO_JARI;
}
class Barco {
public void viajaPara(CidadesNavegaveis cidade) { /* perfeito! Impedimos um valor inesperado em
tempo de execuo! */
System.out.println("Viajando para " + cidade);
}
}
Agora sim podemos assegurar de que nosso barco navegar apenas entre as cidades desejadas.
Um Enum pode ser declarado em um arquivo Java separado ou como um membro de uma classe, mas nunca dentro de
um mtodo.
Declarando um Enum em um arquivo Java separado
Arquivo CidadesNavegaveis.java:
enum CidadesNavegaveis {
AMAPA, CALCOENE, FERREIRA_GOMES, LARANJAL_DO_JARI, MACAPA, MAZAGAO, OIAPOQUE,
PORTO_GRANDE, SANTANA, SERRA_DO_NAVIO, TARTARUGALZINHO, VITORIA_DO_JARI;
}
Arquivo Barco.java:
class Barco {
enum CidadesNavegaveis {
AMAPA, CALCOENE, FERREIRA_GOMES, LARANJAL_DO_JARI, MACAPA, MAZAGAO, OIAPOQUE,
PORTO_GRANDE, SANTANA, SERRA_DO_NAVIO, TARTARUGALZINHO, VITORIA_DO_JARI;
}
public void viajaPara(CidadesNavegaveis cidade) {
System.out.println("Viajando para " + cidade);
Cada item enumerado em um Enum uma instncia do prprio Enum. No exemplo acima, cada cidade enumerada
(MACAPA, MAZAGAO, OIAPOQUE, etc) uma instncia do tipo CidadesNavegaveis. Confuso, no?!? Para que voc
entenda melhor, o Enum algo parecido como isto:
class CidadesNavegaveis {
public static final CidadesNavegaveis AMAPA = new CidadesNavegaveis("AMAPA", 0);
public static final CidadesNavegaveis CALCOENE = new CidadesNavegaveis("CALCOENE", 1);
public static final CidadesNavegaveis FERREIRA_GOMES = new CidadesNavegaveis("FERREIRA_GOMES", 2);
public static final CidadesNavegaveis LARANJAL_DO_JARI = new CidadesNavegaveis("LARANJAL_DO_JARI", 3);
public static final CidadesNavegaveis MACAPA = new CidadesNavegaveis("MACAPA", 4);
// ...
public CidadesNavegaveis(String nome, int indice) {
// ...
}
}
Em um Enum todos os valores enumerados so static e final, portanto so constantes. Os valores so tambm
implicitamente public, e cada valor guarda seu prprio ndice, que definido na ordem em que o item declarado.
Alm de definir constantes enumeradas, no Enum podemos tambm criar construtores, variveis de instncia, mtodos e
algo muito estranho chamado corpo de classe especfico da constante.
Nosso barco agora sabe para quais cidades ele pode se deslocar, mas ainda no inteligente o bastante para saber aonde
fica cada cidade. Vamos ajudar no nosso barco relacionando cada cidade enumerada com sua respectiva coordenada
geogrfica. Podemos, para isto, utilizar um construtor para passar a coordenada como parmetro e preencher uma varivel
de instncia, caso precisemos recuperar este valor mais tarde. Nosso Enum ficaria assim:
enum CidadesNavegaveis {
AMAPA("2.051082,-50.794464"),
CALCOENE("1.933227,-50.736237"),
FERREIRA_GOMES("-0.116043,-51.28315"),
LARANJAL_DO_JARI("0.854155,-51.182556"),
MACAPA("0.034457,-51.066564"),
MAZAGAO("2.497911,-50.947037"),
OIAPOQUE("-0.906334,-51.965332");
CidadesNavegaveis(String coordenada) {
this.coordenada = coordenada;
}
private String coordenada;
Perceba que agora cada item enumerado passa como parmetro uma String contendo a coordenada geogrfica para o
construtor do Enum, e essa String armazenada em uma varivel de instncia. Essa varivel poder ser acessada
posteriormente pelo mtodo getCoordenada que criamos. Veja:
class Barco {
public void viajaPara(CidadesNavegaveis cidade) {
System.out.println("Viajando para " + cidade);
System.out.println("Coordenada: " + cidade.getCoordenada()); /* Agora nossa classe Barco
imprime tambm a coordenada geogrfica da cidade enviada como parmetro. */
}
}
No possvel invocar diretamente um construtor de um Enum, ele acessado automaticamente pelo item enumerado,
que enviar os parmetros necessrios, como fizemos no item enumerado MACAPA("0.034457,-51.066564") que passa
uma String como parmetro ao construtor. O Enum aceita construtores com mais de um parmetro e tambm nos permite
sobrecarregar o construtor. [Falaremos sobre sobrecarga de construtores mais adiante]
Outro recurso importante em um Enum a possibilidade de criar um corpo de classe especfico da constante. Imagine
que nosso barco precise saber qual cidade a capital do estado. Ao invs de criar blocos condicionais com if podemos
criar um mtodo que retorne true caso a cidade seja capital e false caso no seja. Teremos ento um mtodo padro que
retornar sempre false, e para a cidade que capital iremos sobrecarregar este mtodo para que ele retorne true. Veja:
enum CidadesNavegaveis {
AMAPA("2.051082,-50.794464"),
CALCOENE("1.933227,-50.736237"),
FERREIRA_GOMES("-0.116043,-51.28315"),
LARANJAL_DO_JARI("0.854155,-51.182556"),
MACAPA("0.034457,-51.066564") { // corpo de classe especfico da constante
public boolean isCapital() { // mtodo sobrecarregado, para a capital
return true;
}
},
MAZAGAO("2.497911,-50.947037"),
OIAPOQUE("-0.906334,-51.965332");
CidadesNavegaveis(String coordenada) {
this.coordenada = coordenada;
}
private String coordenada;
Agora nosso mtodo viajaPara imprimir true caso a cidade informada como parmetro seja MACAPA, a capital do Amap.
Veja:
class Barco {
public void viajaPara(CidadesNavegaveis cidade) {
System.out.println("Viajando para " + cidade);
System.out.println("Coordenada: " + cidade.getCoordenada());
System.out.println(" capital: " + cidade.isCapital());
}
}
O cdigo acima imprimir na tela todas as cidades enumeradas em nosso Enum CidadesNavegaveis.
10
2.
3.
Ex:
A partir do Java 5 os objetos Wrapper dos tipos primitivos possuem o recurso de auto-boxing, permitindo converter
primitivos para objetos Wrapper (e vice-versa) automaticamente. Desta maneira, o trabalho de fazer boxing e unboxing fica
transparente para o programador.
Na verdade, quando voc escreve o cdigo abaixo (por exemplo):
Integer x = 23;
Integer x = Integer.valueOf(23);
O que o mtodo valueOf faz simplesmente receber um literal primitivo como parmetro e retornar um Wrapper
correspondente a esse primitivo.
Observao
O Wrapper imutvel (no possui um setter), portanto no se pode modificar seu valor literal:
Integer x = 23;
x = 50; // o valor inicial 23 no alterado para 50 mas sim um novo objeto Integer criado e atribudo varivel x
Na verdade o compilador far o auto-boxing nos bastidores:
x = Integer.valueOf(50); // o mtodo valueOf ir retornar um novo objeto Wrapper com o valor 50.
Por questes de otimizao (economia de memria) a JVM inicializa, em cache, os seguintes valores literais para os
Wrappers:
Byte: todo seu intervalo;
Boolean: true e false;
Integer e Short: a range -128 ~ 127;
Character: a range \u000 ~\u007f (ou seja, do decimal 0 ao 127)
11
... {
Integer w = 127;
Integer x = 127;
Integer y = 128;
Integer z = 128;
12
/*
* Nome da classe
*
* Verso
*
* Informao de Copyright
*/
Para classes que estejam dentro de um pacote (package) a declarao do pacote deve ser sempre a primeira linha
no comentada do arquivo de cdigo fonte, seguido das declaraes de import. Veja:
A declarao de classe ou interface deve vir aps as declaraes de import. Pode-se tambm adicionar um
comentrio da classe acima de sua declarao, incluindo tags do javadoc, e aps a declarao class ou interface
pode-se adicionar um comentrio da sua implementao. Veja:
/**
* Comentrios e tags javadoc para a classe
* @author lucasfreitas
*
*/
public class Exemplo1 { // declarao de classe
/*
* Comentrios da implementao
*/
// ...
}
A declarao das variveis de instncia vm logo aps a declarao de classe ou interface, e em seguida declaramos construtores e por ltimo os mtodos. Veja:
/*
* Nome da classe
*
* Verso
*
* Informao de Copyright
*/
package cursojava; // declarao de pacote
import java.math.BigDecimal;
import java.util.List;
/**
* Comentrios e tags javadoc para a classe
* @author lucasfreitas
*
*/
public class Exemplo1 { // declarao de classe
13
/*
* Comentrios da implementao
*/
private BigDecimal var1; // varivel de instncia
private List<String> var2; // varivel de instncia
private long var3; // varivel de instncia
public static void main(String[] args) { // mtodo
// ...
}
class Cachorro
class CarroConversivel
interface Veiculo
interface TelefoneFixo
andar()
andarRapido()
voltar()
String nome;
int tamanhoMaximo;
List<String> listaDeCompras;
String nome;
diferente de:
String Nome;
14
Exemplo de um JavaBean:
class Pessoa {
private String nome;
private int idade;
private boolean maiorDeIdade;
public Pessoa() {} // construtor nulo
15
5. Escopo de variveis
5.1. Variveis de Instncia
Variveis de instncia so variveis declaradas dentro do corpo da classe, mas fora do corpo de mtodo ou de
construtores.
Ex:
// mtodos aqui...
Variveis de instncia so inicializadas automaticamente com seu valor padro sempre que o objeto inicializado, no sendo obrigatrio inicializ-las.
Tipo
Valor padro
referncia a objeto
float, double
boolean
false
char
\u0000
16
if (x > 100) {
break;
}
Utilizar uma varivel local sem antes inicializ-la resultar em erro em tempo de compilao. Veja o exemplo:
public static void main(String[] args) {
String var1;
var1 += "teste"; // no ir compilar pois var1 no foi inicializada
// ..
}
Ao tentar compilar o mtodo acima obteremos o seguinte erro do compilador:
Erro: The local variable var1 may not have been initialized
Tentar utilizar uma varivel local fora do bloco onde ela foi declarada tambm ir gerar erro em tempo de compilao. Veja o
exemplo:
Para entender melhor o tempo de vida das variveis locais, vejamos outro exemplo:
pilha a rea de memria que a JVM utiliza para armazenar as chamadas de mtodos e as variveis locais.
17
Entendendo o cdigo:
O PRIMEIRO bloco tem acesso apenas varivel x;
O SEGUNDO bloco tem acesso s variveis x, i e y;
O TERCEIRO bloco tem acesso s variveis x, i, y e a;
O QUARTO bloco tem acesso s variveis x, i, y e b;
As variveis a e b ao final do SEGUNDO bloco NO so as mesmas do TERCEIRO e QUARTO blocos respectivamente.
No exemplo acima x um parmetro de mtodo, e poder ser utilizado dentro do bloco do mtodo retornaQuadrado.
Sempre que chamarmos o mtodo retornaQuadrado devemos obrigatoriamente passar um int como argumento, justamente porque o mtodo foi declarado esperando um parmetro deste tipo.
Observao
Lembre-se de que Java uma linguagem fortemente tipada, ou seja, aps declarado, um tipo de dado no poder
ser modificado.
18
package com.banco.agencia;
class Conta {
public double saldo;
public double limite;
// getters e setters aqui...
}
A classe Conta acima ficar visvel para todo o pacote com.banco.agencia, ou seja, qualquer outra classe dentro deste pacote poder instanci-la, estend-la ou acessar determinados membros pertencentes a ela.
Veja o que acontece quando tentamos acessar a nossa classe Conta, com acesso default, a partir de outro pacote:
19
at com.banco.teste.TesteAcessoConta.main(TesteAcessoConta.java:8)
package com.banco.agencia;
public class Conta {
public double saldo;
public double limite;
// implementaes aqui...
}
package com.banco.agencia;
public final class Conta {
Veja o que aconteceria se tentssemos estender nossa classe Conta para subscrever o mtodo saca, permitindo que
algum faa um saque acima do limite:
20
package com.banco.teste;
import com.banco.agencia.Conta;
public class TesteConta1 extends Conta {
public void saca(double valor) {
super.saldo = super.saldo - valor;
}
}
Ao compilar a classe TesteConta1 acima, o compilador exibiria um erro informando que no possvel estender a classe
Conta por se tratar de uma classe final.
6.2.2. Modificador abstract
O modificador abstract tem significado exatamente oposto ao modificador final. Enquanto o modificador final impede que
uma classe seja estendida, o modificador abstract define que a classe pode (e deve) ser estendida.
Uma classe abstrata tem o propsito nico de ser... abstrata! Imagine, por exemplo, que queremos criar uma classe
genrica Animal, com mtodos comuns a todos os animais especficos, mas ns no queremos que algum instancie um
objeto genrico do tipo Animal (no faria sentido, no mesmo?!). Para isto, basta declarar nossa classe Animal como
abstract.
Veja como ficaria nossa classe Animal:
Nossa classe Animal acima no poder ser instanciada, mas podemos criar vrios objetos do tipo Animal a partir dela. Para
exemplificar, vamos criar um objeto Cachorro que um Animal:
@Override
public void fazerBarulho() {
System.out.println("Au au");
}
@Override
public void comer(Comida comida) {
System.out.println("Comendo " + comida);
}
21
@Override
public void fazerBarulho() {
System.out.println("Au au");
}
@Override
public void comer(Comida comida) {
System.out.println("Comendo " + comida);
}
Os mtodos fazerBarulho() e comer() so pblicos e podem ser acessados a partir de qualquer classe, independente de seu
pacote. Veja:
Nossa classe TesteAnimal acima ir compilar perfeitamente, gerando o seguinte resultado ao ser executada:
Comendo carne
Au au
22
Perceba que o mtodo trocarMarcha() da nossa classe Carro public e ser herdado pela classe BMW, permitindo-nos
cham-lo diretamente a partir de uma instncia da classe BMW.
private double saldo; // varivel declarada como private: ficar acessvel apenas na prpria classe Conta
private double limite; // varivel declarada como private: ficar acessvel apenas na prpria classe Conta
public Conta(double saldo, double limite) {
this.saldo = saldo;
this.limite = limite;
}
public void saca(double valor) {
if (valor > this.saldo + this.limite) {
System.out.println("Saldo insuficiente.");
} else {
this.saldo = this.saldo - valor;
}
}
}
public class TesteConta2 {
23
Declaramos nossas variveis de instncia saldo e limite como private, impedindo que sejam acessadas diretamente por
outra classe. Criamos tambm o construtor Conta() para inicializar os valores do saldo e do limite na criao do objeto. Desta forma estamos garantindo a segurana para que nenhuma outra classe possa modificar o valor do saldo e do limite,
aps instanciado o objeto.
A classe TesteConta2 est tentando modificar o contedo da varivel saldo que private, logo esta classe no ir compilar,
gerando o seguinte erro no compilador:
package com.veiculo;
O mtodo trocarMarcha() da nossa classe Carro tem controle de acesso default por no possuir explicitamente nenhum
modificador de acesso, podendo ser acessado apenas a partir de classes que estejam no pacote com.veiculo.
Tentaremos acessar o mtodo trocarMarcha() a partir de uma classe que esteja fora do pacote com.veiculo, veja:
24
package com.veiculo;
Nossa classe abstrata Carro possui uma varivel de instncia protected marchaAtual. Iremos agora implementar o mtodo
abstrato trocarMarcha() em uma subclasse da nossa classe Carro, localizada em pacote diferente:
public Corsa() {
super("corsa");
}
@Override
public void trocarMarcha(int marcha) {
super.marchaAtual = marcha; // ir compilar perfeitamente
}
import com.veiculo.Carro;
public class Corsa extends Carro {
A implementao do mtodo trocarMarcha() na classe Corsa acessa normalmente a varivel de instncia marchaAtual de
sua superclasse atravs da herana.
25
A classe acima no ir compilar, pois tentamos utilizar o modificador de acesso private em uma varivel local.
7. Membros static
7.1. Variveis static
Variveis declaradas como static em uma classe so particularmente chamadas de variveis de classe e so diferentes das
variveis de instncia. Uma varivel static pertence classe, e no instncia da classe. Em outras palavras: ns no dependemos de instanciar uma classe para acessar suas variveis static.
Imagine, por exemplo, que precisamos contar o nmero de instncias de uma classe: isso no seria possvel fazer atravs
de uma varivel de instncia, uma vez que esta pertenceria apenas a uma instncia especfica. Para resolver este problema,
podemos simplesmente usar uma varivel static, veja:
class VariavelStatic {
static int contadorDeInstancia = 0;
public VariavelStatic() {
contadorDeInstancia++;
}
}
Note que nossa classe VariavelStatic possui uma varivel de classe chamada contadorDeInstancia que independe de qualquer instncia dessa classe. Vamos, ento, testar a nossa classe:
Perceba que a varivel static resolveu o nosso problema: registrar o nmero de instncias da nossa classe VariavelStatic.
26
class Util {
public static int geraInteiroRandomico() {
Random r = new Random();
return r.nextInt();
}
}
Nossa classe Util nos disponibilizou um mtodo static para reutilizarmos em outras classes, sem a necessidade de termos
que instanciar a classe. Veja:
Perceba que chamamos o mtodo geraInteiroRandomico() diretamente, sem precisarmos instanciar a classe Util.
8. Membros final
8.1. Variveis final
Declarar uma varivel como final significa impedir que esta seja reutilizada depois de inicializada com um valor explcito. Em
outras palavras: uma constante!
class Circulo {
final double PI = 3.141592;
final double RAIO;
public Circulo(double raio) {
this.RAIO = raio;
}
public double calculaCircunferencia() {
return 2 * PI * RAIO;
}
public double calculaArea() {
return PI * Math.pow(RAIO, 2);
}
}
Nossa classe Circulo acima possui duas variveis de instncia declaradas como final. Ambas as variveis, por serem final,
devem ser inicializadas antes de utilizadas. Veja agora o que acontece se tentarmos modificar o valor j inicializado de uma
varivel final:
27
O cdigo da classe TestaCirculo no ir compilar, pois tentamos modificar o valor da varivel RAIO que j havia sido inicializada explicitamente.
class Moto {
28
Nossa classe Moto tem um mtodo final que no poder ser subscrito por uma subclasse. Vamos agora testar isso na prtica:
Perceba que nossa classe HondaBiz (subclasse da classe Moto) tenta subscrever o mtodo ligar(), e isto ir causar um erro
ao tentar compilar a classe.
9. Controle de fluxo
9.1. Condicionais
9.1.1. if-else
O if um dos elementos mais utilizados em uma linguagem de programao e tem o objetivo de testar se uma condio
verdadeira para executar (ou no) um trecho de cdigo.
A sintaxe bsica de um if-else a seguinte:
if (expressoBooleana) {
// cdigo aqui...
} else {
// outro cdigo aqui...
}
A expresso entre parnteses deve resultar obrigatoriamente em um booleano (true ou false). O bloco else opcional.
Veja abaixo um exemplo utilizando if em Java:
int x = 16;
if (x > 10) {
System.out.println("x maior que 10");
} else {
System.out.println("x menor que 10");
}
29
boolean x = false;
if (x = true) {
System.out.println("x true");
} else {
System.out.println("b false");
}
int x = 10;
if (x = 10) { // No ir compilar
System.out.println("x vale 10");
} else {
System.out.println("b no vale 10");
}
O cdigo acima no ir compilar, pois estamos utilizando uma varivel no-booleana em um if com atribuio.
9.1.1.2. if com mltiplas condies
possvel tambm fazer um if com mltiplas condies. Veja:
int x = 10;
if (x > 10) {
System.out.println("x maior que 10");
} else if (x == 10) {
System.out.println("x igual a 10");
} else {
System.out.println("x menor que 10");
}
9.1.2. switch
Uma maneira de simular mltiplas condies com if usando o switch. A sintaxe bsica de um switch a seguinte:
switch (expresso) {
case constante1:
cdigo
case constante2:
cdigo
default:
cdigo
}
int x = 10;
switch(x) {
case 1:
System.out.println("x igual a 1");
break;
case 2:
System.out.println("x igual a 2");
30
break;
case 10:
System.out.println("x igual a 10");
break;
case 20:
System.out.println("x igual a 20");
break;
default:
System.out.println("no sabemos o valor de x");
O cdigo acima ir imprimir: x igual a 10. Note a presena do break dentro da instruo case: o break opcional mas,
nesse nosso caso, devemos utiliz-lo para evitar que os blocos seguintes (aps a condio verdadeira) sejam executados.
A expresso de um switch deve resultar sempre em um char, byte, short, int ou, a partir do Java 6, um enum. No podemos utilizar um tipo diferente de um inteiro ou um enum como resultado da expresso de um switch. Sendo assim, o cdigo abaixo no valido:
String t = "teste";
switch (t) { // no ir compilar
case "testa":
System.out.println("t = testa");
case "teste":
System.out.println("t = testa");
default:
System.out.println("no sabemos o valor de t");
}
O cdigo acima no ir compilar, pois estamos tentando utilizar uma String como expresso em um switch.
9.2. Loops
9.2.1. while
O while nos possibilita executar um loop enquanto uma expresso for vlida. A sintaxe bsica de um while a seguinte:
while (expresso) {
// faa algo
}
int x = 0;
while(x <= 3) {
System.out.println(x);
x++;
}
do {
}
System.out.println("Imprima isto");
31
while(false);
O cdigo acima ir imprimir perfeitamente a String Imprima isto mesmo a condio sendo false.
9.2.3. for
O for um tipo especial de loop. A sintaxe bsica de um for a seguinte:
int i = 0;
for (;i<10;) {
i++;
System.out.println(i);
}
10. Construtores
10.1. Declarando construtores
Em Java todas as classes tm um construtor, mesmo que voc no declare um explicitamente. Sempre que criamos um
objeto, pelo menos um construtor invocado.
Um construtor se parece com um mtodo, com a diferena de que um construtor nunca possuir um tipo de retorno.
Pode-se usar qualquer um dos modificadores de acesso em construtores, mas nunca podemos declarar um construtor
como final, abstract ou static.
Vejamos o exemplo de um construtor:
class Cachorro {
private String raca;
private String nome;
public Cachorro() { } // construtor sem argumentos
// mtodos aqui...
}
Nossa classe Cachorro tem um construtor sem argumentos. Sempre que criarmos um objeto do tipo Cachorro, este construtor ser chamado. Voc deve estar pensando: mas o construtor da classe Cachorro no faz sentido algum, ele no recebe argumentos e muito menos tem alguma implementao!. Sim, concordamos com voc, afinal utilizamos este cons-
32
class Cachorro {
private String raca;
private String nome;
public Cachorro(String raca, String nome) { // construtor
this.raca = raca;
this.nome = nome;
}
// mtodos aqui...
}
Nesse caso, a classe Cachorro tem um construtor que recebe dois parmetros do tipo String. Em Java todo construtor
deve ter o mesmo nome da classe em que foi declarado, e pode receber argumentos assim como os mtodos. Tenha em
mente que os objetos so construdos e no possvel criar um objeto sem chamar um construtor.
Agora nossa classe no possui nenhum construtor sem argumentos e sempre que formos criar um objeto a partir desta
classe seremos obrigados a passar os dois parmetros para o construtor. Veja:
Se tentssemos criar um objeto do tipo Cachorro sem passar os parmetros do construtor, obteramos um erro ao tentar
compilar a classe. Veja:
Agora voc deve estar pensando: mas o Java no cria automaticamente um construtor sem argumentos e sem implementao?. A resposta : depende! Um construtor padro s ser criado automaticamente caso a classe no tenha nenhum
construtor declarado.
Os construtores servem basicamente para inicializar as variveis de instncia, como pde ser visto no nosso ltimo exemplo
da classe Cachorro.
class Carro {
33
A classe acima nos permite instanci-la passando uma String como parmetro ou sem informar parmetro algum. Veja:
public class TesteCarro1 {
public static void main(String[] args) {
Carro astra = new Carro("Astra");
Carro carroGenerico = new Carro();
}
}
Na nossa classe TesteCarro1 as duas maneiras de instanciar a classe Carro esto corretas.
11. Encapsulamento
Encapsulamento uma tcnica utilizada para proteger os dados armazenados em seus objetos, disponibilizando mtodos
para controle e proteo destes dados. tambm uma forma de prover modularizao e fexibilidade do cdigo. O encapsulamento nos permite ocultar detalhes da implementao do nosso cdigo, evitando a exposio de certas informaes.
Imagine, por exemplo, um telefone celular: se pudssemos ter acesso direto aos seus componentes internos e precisssemos saber como um celular funciona internamente para utiliz-lo, poderamos burlar o sistema ou modificar algo no desejado, o que acarretaria em um retorno ou resposta inesperada do aparelho. O teclado do celular o mtodo de acesso s
suas funcionalidades e foi criado justamente para interagirmos com o aparelho e consequentemente obtermos as respostas
desejadas, sem expor detalhes internos de seu funcionamento. Este o propsito do encapsulamento.
class Pessoa {
private String nome;
private int idade;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public int getIdade() {
return idade;
}
public void setIdade(int idade) {
34
this.idade = idade;
Atravs dos setters e getters da classe Pessoa podemos modificar e ler o contedo das variveis nome e idade facilmente.
Veja:
Definir as variveis como private e permitir seu acesso apenas atravs dos setters e getters nos d maior flexibilidade, facilitando pequenas modificaes em nossa classe. Se utilizssemos essa classe Pessoa em um cadastro e quisssemos restringir o cadastro apenas para pessoas maiores de idade, poderamos facilmente modificar o mtodo setter para aceitar
apenas idade maior ou igual a 18 anos. Veja como ficaria nosso setter modificado:
Note que no teramos a mesma flexibilidade se permitssemos o acesso direto varivel idade, ou seja, se ela fosse public.
12.1. Associao
A associao possui uma relao de acoplamento mais fraco, onde um objeto no depende do ciclo de vida do outro, ou
seja, se a relao entre os objetos associados for rompida ambos os objetos continuam tendo um sentido lgico. usada
quando um objeto A usa um objeto B ou quando um objeto A tem um objeto B. Veja o exemplo abaixo:
Neste exemplo o Navio tem um Container. Se a relao entre eles for rompida, ambos os objetos continuam tendo um
sentido lgico, pois um no depende do outro para ter um significado.
Veja outro exemplo:
35
Neste exemplo o Trem usa uma EstradaDeFerro. Ambos os objetos fazem sentido separadamente.
12.2. Agregao
A agregao considerada como um tipo de associao, onde um objeto faz parte de outro objeto. A agregao tambm
possui uma relao de acoplamento mais fraco, onde um objeto no depende do outro para ter um sentido lgico. Veja o
exemplo:
Neste exemplo o Farol faz parte da Locomotiva. Ambos os objetos fazem sentido separadamente.
12.3. Composio
A composio um tipo especial de associao, onde um objeto composto por outro objeto. A composio uma
relao de forte acoplamento, onde um objeto gerencia o ciclo de vida do objeto composto, de forma que se um objeto
deixar de existir o outro no ter mais um sentido lgico. Veja o exemplo abaixo:
Neste exemplo o Trem composto por: um objeto do tipo Locomotiva e um ou mais objetos do tipo Vago. Um Trem no
existe sem estes dois objetos, ou seja, se a relao for perdida o objeto Trem perder seu sentido lgico.
12.4. Herana
Herana um conceito fundamental em linguagem de programao orientada ao objeto, como Java. A herana uma
relao do tipo um e trata-se de uma relao de acoplamento forte, menos flexvel que a composio e a associao.
Ela permite que classes mais especficas herdem estado e comportamento (variveis e mtodos) de classes mais genricas,
provendo dois benefcios:
Reutilizao de cdigo;
Uso do polimorfismo.
A herana uma relao do tipo um, e expressa quando se utiliza a palavra reservada extends (herana de classe) ou
implements (implementao de interface).
Veja o cdigo abaixo:
public class Carro {
2011 Lucas Medeiros de Freitas | lucas@hachitecnologia.com.br
36
}
O cdigo acima ir compilar sem erro, e ao execut-lo obteremos o seguinte resultado:
Objetos diferentes!
Astra um Carro!
Astra um Object!
Voc deve estar pensando: Ok, realmente astra e vectra so variveis que apontam pra objetos diferentes, logo no
poderiam mesmo serem iguais. Mas... de onde veio esse mtodo equals? Ele no foi declarado na classe Carro!!! E como o
objeto da varivel astra um Object se ele do tipo Carro?!?!
A verdade que em Java todas as classes estendem Object implicitamente (herana), ou seja, todos os objetos em Java
so tambm do tipo Object. E a classe Object de Java possui o mtodo equals para fazer a comparao entre objetos, logo
a classe Carro tambm possuir esse mtodo, j que ela tambm do tipo Object. Voil!
A classe Object possui tambm outros mtodos utilitrios para facilitar nosso trabalho (mas isso assunto para outro
tpico). Se no tivssemos estes recursos que Object prov, teramos o trabalho de implementar o mtodo equals, por
exemplo, em nossas classes se quisssemos fazer a comparao de objetos.
Entendendo...
Se uma classe B estende uma classe A, ento a classe B uma classe do tipo A. Logo, a classe B ir possuir
todas as variveis e mtodos no privados da classe A.
Veja o cenrio abaixo:
37
Na Figura 2, tanto Carro quanto Bicicleta herdam a classe Veculo. Dizemos ento que a classe Veculo uma
superclasse e as classes Carro e Bicicleta so suas subclasses. Todas as classes que herdam de Veculo iro possuir
suas variveis e mtodos no privados.
Vejamos outro exemplo de herana:
Implementao:
Java no suporta herana mltipla, portanto s possvel estender uma nica classe. O exemplo abaixo no possvel
implementar em Java:
Implementao:
38
}
public class Carro extends Veiculo {
}
public class Astra extends Carro { // ... }
No exemplo acima impedimos que a classe Veiculo seja instanciada ao declar-la como abstrata usando a palavra
reservada abstract. Permitimos que apenas as classes mais especficas (Carro e Astra) sejam instanciadas.
As classes abstratas podem conter tanto mtodos abstratos como no abstratos. Suas subclasses devem
obrigatoriamente implementar todos os seus mtodos abstratos. J os mtodos no abstratos no necessitam ser
implementados: toda sua implementao herdada da superclasse, porm os mtodos no abstratos podem ser
subscritos pelas subclasses.
A vantagem de se utilizar uma classe abstrata que podemos obter a vantagem do polimorfismo e ter implementaes
genricas para classes mais especficas.
39
14. Interfaces
Uma interface semelhante a um contrato que deve ser seguido por todas as classes que a implementam. A diferena
entre uma classe abstrata e uma interface que a interface 100% abstrata. Para declarar uma interface basta usar a
palavra reservada interface.
Exemplo:
}
public class TelefoneFixo implements Telefone {
A classe que implementa a interface deve obrigatoriamente implementar todos os seus mtodos. Perceba que na interface
Telefone os mtodos no possuem corpo, mas no foram declarados como abstract. Estranho, no? Na verdade todos os
40
41
16. Polimorfismo
Tudo bem, mencionamos sobre polimorfismo alguns tpicos antes nesta apostila mas, afinal de contas, o que o
polimorfismo? Polimorfismo o princpio pelo qual duas ou mais classes derivadas de uma mesma superclasse podem
invocar mtodos que tm a mesma identificao (assinatura) mas comportamentos distintos, especializados para cada
classe derivada, usando para tanto uma referncia a um objeto do tipo da superclasse. (Ivan Luiz Marques Ricarte, 2002,
Unicamp). No entendeu? Tudo bem, vamos mostrar na prtica! Veja o cdigo abaixo:
abstract class Animal {
public abstract void fazBarulho();
}
class Cachorro extends Animal {
}
42
au au
miau
Perceba neste exemplo que declaramos uma varivel de tipo Animal e atribumos objetos de tipo Cachorro e Gato a ela, ou
seja, a referncia diferente do objeto. Isto polimorfismo! Quando voc declarar uma varivel de referncia, qualquer
objeto que passar no teste -UM quanto ao tipo declarado para ela poder ser atribudo a essa referncia. Em outras
palavras, qualquer coisa que estender o tipo declarado para a varivel de referncia poder ser atribuda a ela. (Java - Use
a Cabea, 2005).
Podemos nos beneficiar do poder do polimorfismo para deixar nosso cdigo bastante flexvel, como por exemplo:
Criar matrizes polimrficas:
Neste modelo, desenvolvido no Tribunal de Justia do Amap, temos uma interface AtoMagistrado e algumas
classes mais especficas para cada tipo de ato que um magistrado (Juiz, Desembargador) possa realizar. O usurio (nesse
caso, um Magistrado) ir solicitar ao sistema o tipo especfico de AtoMagistrado que ele deseja e o sistema se encarregar
de chamar o objeto especfico de acordo com a requisio do usurio, em tempo de execuo. Na prtica, o cdigo seria
algo como:
// ...
AtoMagistrado ato = null;
switch (tipoAtoRequisitado) {
case ACORDAO:
ato = new Acordao();
break;
case DECISAO:
ato = new Decisao();
break;
case DECISAOTERMINATIVA:
ato = new DecisaoTerminativa();
break;
case DESPACHO:
ato = new Despacho();
43
break;
case MANIFESTACAO:
ato = new Manifestacao();
break;
case PARECER:
ato = new Parecer();
break;
case SENTENCA:
ato = new Sentenca();
break;
// ...
No exemplo, percebemos que um objeto especfico criado e atribudo a uma varivel de um tipo mais genrico
AtoMagistrado. Ao fazer uma chamada de mtodo de AtoMagistrado, a JVM se encarregar de escolher o mtodo correto
contendo a implementao especfica para o tipo requisitado.
Podemos tambm beneficiar do polimorfismo em parmetros e tipo de retorno. Veja o cdigo abaixo:
class Veterinario {
public void alimentar(Animal animal) { // aceita como parmetro qualquer objeto que seja um Animal
// ... implementao aqui
}
}
Perceba neste caso que um Veterinrio tem um mtodo para alimentar qualquer tipo de Animal, ou seja, qualquer
objeto que estenda (ou implemente, caso seja uma interface) a classe Animal.
44
Figura 5. Herana
Figura 6. Composio
45
O cdigo acima ir compilar sem erro, e, ao executar o mtodo main da classe Astra, teremos impresso na sada padro a
marcha atual de acordo com a velocidade do carro (trata-se de um carro automtico). O mtodo retornaMarcha retorna um
tipo inteiro (int) representando a marcha atual do carro. Se por algum motivo precisssemos mudar o retorno do mtodo
retornaMarcha para outro tipo primitivo ou para um objeto, o cdigo da classe Astra quebraria.
Para exemplificar, vamos criar uma classe para a marcha, chamada (coincidentemente) de Marcha:
public class Marcha {
private int marcha;
46
Agora vamos modificar o tipo de retorno do mtodo retornaMarcha, para que este retorne um objeto do tipo Marcha ao
invs de um primitivo int:
public abstract class Automovel {
public Marcha retornaMarcha(int velocidade) { // o mtodo agora ir retornar um objeto Marcha
if (velocidade >= 0 && velocidade < 40)
return new Marcha(1); // retorna objeto Marcha referente a marcha 1
else if (velocidade >= 40 && velocidade < 60)
return new Marcha(2); // retorna objeto Marcha referente a marcha 2
else if (velocidade >= 60 && velocidade < 80)
return new Marcha(3); // retorna objeto Marcha referente a marcha 3
else if (velocidade >= 80 && velocidade < 100)
return new Marcha(4); // retorna objeto Marcha referente a marcha 4
else if (velocidade >= 100)
return new Marcha(5); // retorna objeto Marcha referente a marcha 5
else
return new Marcha(-1); // retorna objeto Marcha referente a marcha r
}
}
47
}
Agora vamos modificar a classe Automvel para que seu mtodo retornaMarcha retorne um objeto do tipo Marcha ao invs
de um primitivo int:
public class Automovel {
public Marcha retornaMarcha(int velocidade) { // mtodo modificado para retornar um objeto do tipo Marcha
if (velocidade >= 0 && velocidade < 40)
return new Marcha(1);
else if (velocidade >= 40 && velocidade < 60)
return new Marcha(2);
else if (velocidade >= 60 && velocidade < 80)
return new Marcha(3);
else if (velocidade >= 80 && velocidade < 100)
return new Marcha(4);
else if (velocidade >= 100)
48
else
Devemos modificar tambm a classe Carro, que contm um forwarding do mtodo retornaMarcha:
public class Carro {
private Automovel automovel = new Automovel();
public int retornaMarcha(int velocidade) {
return automovel.retornaMarcha(velocidade).getMarcha(); // linha alterada, para retornar um tipo int
}
}
Note que na classe carro alteramos apenas a linha de retorno, permanecendo sua assinatura e tipo de retorno como int.
Perceba agora como ficou a classe Astra:
public class Astra {
public static void main(String[] args) {
Carro carro = new Carro();
int marcha = carro.retornaMarcha(180);
System.out.println("Marcha atual: " + marcha);
}
}
Note que o cdigo da classe Astra no teve nenhuma alterao, assim como centenas de outras possveis classes que
utilizam a classe Carro, como Celta, Corsa, Montana, tambm no necessitariam de alteraes.
Perceba, pelo exemplo acima, que quando no se deseja utilizar o polimorfismo, a composio uma tima maneira de
tornar o seu cdigo mais flexvel e menos acoplado.
class Animal {
}
49
Nossa classe Cobra estende a classe Animal e subscreve o mtodo mover(). Perceba que em nossa classe Animal temos
um mtodo representando a forma genrica de mover dos animais. Mas sabemos que a cobra uma exceo e, ao invs
de andar, ela rasteja. Para implementar isto de forma correta ento ns subscrevemos o mtodo mover() para representar a
forma correta de se mover da cobra, que rastejando. Veja o resultado que obtemos ao executar mtodo mover() de um
objeto do tipo Cobra:
class OperacoesMatematicas {
public int soma(int x, int y) { // soma dois primitivos int
return x + y;
}
public double soma(double x, double y) { // soma dois primitivos double
return x + y;
}
}
A nossa classe OperacoesMatematicas possui dois mtodos de mesmo nome mas com argumentos diferentes. Para o
Java os mtodos so diferentes, que por uma mera coincidncia possuem nomes parecidos. Enquanto um mtodo executa
a soma de dois nmeros do tipo int, outro executa a soma de dois nmeros do tipo double. Veja o resultado obtido ao testar nossa classe:
System.out.println(resultado1); // ir imprimir 5
System.out.println(resultado2); // ir imprimir 3.7
Exatamente como espervamos! Fizemos duas chamadas: uma para o mtodo soma(int x, int y) que retornou um int e outra para o mtodo soma(double x, double y) que retornou um double.
50
II - Referncias bibliogrficas
Caelum
Apostila FJ 11 - Java e Orientao a Objetos. <Disponvel em http://www.caelum.com.br>.
Apostila FJ 34 - Desenvolvimento para Web com Jboss Seam. <Disponvel em http://www.caelum.com.br>.
Argonavis
Gerncia de memria em Java, Edio 1.0, 2005. Helder da Rocha. <Disponvel em http://www.argonavis.com.br>.
Reuso com herana e composio. Helder da Rocha. <Disponvel em http://www.argonavis.com.br>.
iMasters
Java Wrappers. Camilo Lopes. <Disponvel em http://imasters.com.br/artigo/11801/java/wrappers>.
Artima Developer
Composition versus Inheritance. Bill Venners. <Disponvel em http://www.artima.com/designtechniques/compoinh.html>.
51