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

Cap.

1 - Fundamentos Linguagem


Captulo 1 - Fundamentos da Linguagem

Esse captulo bastante significativo para a assimilao dos demais contedos, pois ataca todos
os conceitos iniciais da linguagem Java, portanto estude-o com bastante cuidado e ateno !

Palavras-Chave

Na linguagem Java, 49 so as palavras chaves e voc dever memoriz-las. No tente fazer
como fazamos no ensino fundamental para decorar a tabuada (como era difcio a do 9,
lembra?), essa assimilao ser com o tempo, mesmo assim, d uma olha na lista a seguir, e
observe que TODAS as palavras chaves so definidas em letras minsculas:

byte - short - int - long - char - boolean
double - float - public - private - protected
static - abstract - final - strictfp - transient
synchronized - native - void - class - interface
implements - extends - if - else - do
default - switch - case - break - continue
assert - const - goto - throws - throw
new - catch - try - finally - return
this - package - import - instaceof
while - for - volatile - super

No tente decorar todas elas, tente entender o que elas fazem, isso ser possvel com o
desenvolver dos captulos.

LEMBRE-SE: null, false, true (No so palavras chaves, so valores literais!)


Tipos primitivos:

byte- Inteiro de 8 bits com sinal
short- Inteiro de 16 bits com sinal
int- Inteiro de 32 bits com sinal
long- Inteiro de 64 bits com sinal
char- Caracter Unicode (16 bits sem sinal)
float- Ponto flutuante de 32 bits com sinal
double- Ponto flutuante de 64 bits com sinal
boolean- Valor indicando true ou false

Modificadores de acesso:

private- Define que um mtodo ou variavel seja acessada somente pela prpria classe
protected- Faz com que uma subclasse acesse um membro da superclasse, mesmo estando
em pacotes diferentes
public- Faz com que um identificador possa ser acessado de qualquer outra classe.

Modificadores de classe, mtodos e varivel:

abstract- Define uma classe abstrata
class- Define a implementao de uma classe
extends- Define qual a hierarquia de classes, quem a superclasse
final- Faz com que um identificador no possa ser alterado
implements- Faz com que uma classe implemente todos os mtodos de uma interface
interface- Define uma interface
native- Define que o mtodo ser escrito em linguagem nativa como C, C++
new- Instancia um novo objeto na pilha
static- Defina um identificado de classe e no de instncia
strictfp- Define que o mtodo esta segundo o padrao IEE754
synchronized- Define que um mtodo s poder ser acessado por uma nica thread por vez
transient- Faz com que uma varivel no seja serializada
volatile- Indica que uma varivel pode no ficar sincronizada ao ser usada por threads

Controle de Fluxo:

break- Faz com que o fluxo seja desviado para o fim do bloco
continue- Muda o curso do fluxo para a proxima iteracao do loop
if- Testa o valor lgico de uma condio
else- Indica qual o bloco que dever ser executado caso o teste feito pelo if seja falso
default- Bloco que ser executado caso nenhuma condio case satisfaa o swicth
switch- Iniciar uma sequencia de testes para uma variavel a ser testada pelo case
case- Testa o valor de uma variavel indicada pelo switch
for- Usado para executar um bloco quantas vezes forem necessrias para satisfazer sua
condio
do- Executa um bloco quantas vezes a condio se fizer verdadeira. A condio testada
depois do bloco
while- Executa um bloco quantas vezes a condio se fizer verdadeira. A condio testada
antes do bloco
return- Finaliza a execuo de um mtodo, podendo opcionalmente retornar um valor
instanceof- Testa se um objeto instancia de uma classe qualquer


Tratamento de erros:

catch- Define o bloco de deciso que executar se por acaso ocorrer no bloco try uma exceo
pr-definida
finally- Bloco que sempre ser executado, mesmo que uma exceo seja lanada
throw- Lana uma exceo
throws- Indica que um mtodo pode lanar algum tipo de exceo
try- Iniciar um bloco com auditoria
assert- Usado no projeto, testa uma expresso para verificar alternativas para o programador.

Controle de pacotes:

import- Importa uma ou todas as classes de um pacote
package- Define que a(s) classes faro parte de um pacote;


Variveis/Herana:

super- Refere-se a superclasse imediata
this- Refere-se a instncia do objeto

Retorno:

void- Define que um mtodo no retorna nada

Reservadas mas no utilizadas:

const- No use para definir uma varivel, use final
goto- No serve para nada


Tipo primitivos:

Voc precisar saber "tudo" sobre os tipos primitivos, suas faixas de valores, valores padres,
converses implicitas e explcitas, e muito mais. Por isso, prepare-se o seu pesadelo comeou!
Mas no se preocupe, com um pouco de f e perseverana, tudo se resolve!

A Java composta por 8 (oito) tipos primitivos, e como voc j deve ter percebido, todos
comeam com letras minsculas (pois tambm so palavras chaves), portanto se voc for tiver
que responder uma pergunta onde aparece perguntando por exemplo se String um tipo
primitivo, no hesite em responder que NO!
Outro conceito importante sobres os tipos primitivos em Java que todos os tipos numricos
tem sinal. Mas o que isso significa? - deve ter vindo sua mente! Significa que podem ser
negativos ( - ) ou positivos ( + ), ou seja, o tipo int pode ter o numero -1 como tambem o
numero +1. Observe a tabela de valores abaixo:


1. tipo bits frmula faixa
2. byte 8 -2^7 2^7 -1 -128 ~ +127
3. short 16 -2^15 2^15 - 1 -32768 a +32767
4. int 32 -2^31 2^31-1 -
2147483648 a +2147483647
5. long 64 -2^63 2^63-1 -
9223372036854775808 a +9223372036854775807


Dica sem nus: Lembre-se da palavrinha bsil (j est no aurlio), que indica os tipos
b-byte, s-short, i-int, l-long ! Pois "1 byte representado por 8 bits", isso at Hitler
morreu sabendo!


Entendendo essa frmula maluca...

Voc deve estar se perguntando, porque deve elevar a 7 (sete) no caso do byte e no a 8
(oito), certo ? 1 Bit usado para guardar o sinal. E porque s subtrai -1 da faixa positiva ?
Porque o zero includo no intervalo tambm.
Se ainda ficou confuso, vamos fazer um teste. Um regra ns sabemos: o tipo byte em Java
representado por oito bits. Se 1 bit usado para guardar o sinal (+) ou (-), ento sobrou 7 bits
para representar um nmero. Se convertermos o nmero +125 em bits teremos 1111101 e
ficaria representado da seguinte forma: 01111101 (observe que o zero inicial indica que um
numero positivo, estranho mas se o primeiro digito fosse um 1, seria um numero negativo).
Agora se convertermos o numero +128 em bits, teremos 10000000, como esse numero
composto por oito bits no possvel adicionar o bit do sinal portanto o numero 128 positivo
no est no intervalo do tipo byte, e est na faixa negativa pois o bit mais significativo a
esquerda 1 que indica sinal negativo. Quais os bits representam o numero 127 ?


Tipos primitivos (no acabou):

Os demais tipos primitivos so: char, float, double, boolean !

char- representado por caracter Unicode de 16 bits (sem sinal). Tambem pode ser
representado por um numero inteiro de 16 bits sem sinal, ou seja, pode-se atribuir uma
variavel char o valor 100 ou 14555 ou 65535, mas no 65536 ! Pois essa a faixa de valores da
tabela Unicode para representao de caracteres de qualquer idioma. Mas a unica coisa que
voc precisa saber a faixa de valores do tipo char. 2 ^ 16 - 1 = 65535 (valores possveis).

float- um tipo numrico ponto flutuante de 32 bits (COM SINAL) !! Apesar de ter um
tamanho definido por 32 bits, no necessrio saber a faixa de valores.

double- um tipo numrico ponto flutuante de 64 bits (COM SINAL) ! Apesar de ter um
tamanho definido por 64 bits, no necessrio saber a faixa de valores.

boolean- Um valor que indicado pelos valores literais: true ou false.


Converses implicitas/explcitas:

Voc pode sempre que precisar, fazer converses entre os tipos numricos, mas uma regra no
pode ser quebrada: nunca voc poder convertar um tipo de maior valor (bits) em um nmero
de menos valor.

Por exemplo:
1. 1. public class Conversao {
2. 2. public static void main(String[] args) {
3. 3. int x = 10;
4. 4. long y = 20;
5. 5. y = x; // perfeitamente possvel
6. 6. x = y; // no possvel
7. 7. x = (int)y; // quero correr o risco e deixa eu queto !
8. 8. }
9. 9. }


Na linha 5 houve um converso implicita perfeitamente possvel pois o tipo da variavel y long,
ou seja, maior que o tipo da variavel x.
Na linha 6 houve um tentativa de converso, mas o compilador no permitira essa operao,
pois o tipo long maior que int.
Na linha 7,uma converso explcita foi realizada e o compilador gentilmente atendeu a
solicitao do programador.


Literais Inteiros:

Um valor literal em Java um valor escrito no cdigo fonte e identificado como um tipo
primitivo como por exemplo:

1. int x = 10; // literal inteiro
2. char u = 'k'; // literal char
3. boolean b = false; // literal boolean
4. double d = 9832.11; // literal double


H trs maneiras de representar valores inteiros em Java: octal (base 8), decimal (base 10) e
hexadecimal (base 16) ! Ser bom voc estudar um pouco sobre esses sistemas de numerao,
pode-se que os sacanas dos caras que fazem a prova, possa testar voc em alguma questo!
Mas observe o cdigo abaixo e veja como se representam valores literais em octal e
hexadecimal (pois decimal voc viu acima):

1. public class Octal {
2. public static void main(String[] args) {
3. int seis = 06; // idem ao decimal 6
4. int sete = 07; // idem ao decimal 7
5. int oito = 010; // idem ao decimal 8
6. int nove = 011; // idem ao decimal 9
7. }
8. }


Ou seja, se voc ver o numero 0 antes de um nmero, saiba que est representando um
nmero octal.

1. public class Hexadecimal {
2. public static void main(String[] args) {
3. int quinze = 0xF; // 15 (decimal)
4. int vinte_e_nove = 0x1D; // 29 (decimal)
5. int vinte_e_nove = 0x1D; // 29 (decimal)
6. int valor = 0xBAFAFA; // 12253946 (decimal)
7. int valor = 0XBaFaFa; // 12253946 (decimal)
8. }
9. }


Deve vir precedido do sufixo (0x) ! um dos poucos casos na linguagem em que no importa
se as letras forem maisculas ou minsculas. Todos os tipos inteiros literais (tanto octal quanto
hexa) so por padro definidos como int, portanto se ver no exame um questo que atribui a
uma variavel menor que int (em bits) isso dar erro de compilao. Veja o cdigo a seguir:

1. 1. public class ConversaoHexa {
2. 2. public static void main(String[] args) {
3. 3. int a = 0xbafa; // ok, sem converso
4. 4. long b = 0xfff; // ok, converso implicita
5. 5. long c = 0xfffL; // ok, converso explcita
6. 6. byte d = 0xf; // ok, converso implcita
7. 7. byte e = 0xff; // erro! - 255 no comportado
8. 8. byte f = (int)0xff; // erro! - 255 no comportado
9. 9. }
10. 10.}


Na linha 6 o compilador sabe que F em hexa equivale a 15, o que pode ser perfeitamente
suportado no tipo byte, ento ele realiza a converso.
Na linha 7 o compilador sabe que FF em hexa equivale a +255 o que no pode ser suportado,
por isso, erro!
Na linha 8 o compilador s no chinga o programador por conflito de drivers entre seu sistema
operacional com sua placa de som, ou seja, mas intimamente ele fala: CARA OLHA O QUE
VOC EST QUERENDO ME FORAR A FAZER !!! (%#%$!#%)


Literais de ponto flutuante:

Um valor literal de ponto flutuante por padro em Java definido comdoublede 64 bits,
portanto de voc quiser atribuir um valor literalfloatvoc dever adicionar o sufixofno final do
valor como o exemplo:

1. 1.public class Teste {
2. 2.public static void main(String[] args) {
3. 3.double a = 9223372036854775807.0; // ok tipo double
4. 4.float b = 2147483647; // ok tipo int para float conv implicita
5. 5.float c = 2147483647.0; // erro! double -> float
6. 6.float d = (float)2147483647.0; // ok - converso
7. 7.float e = 2147483647.0f; // ok
8. 8.}
9. 9.}


Na linha 4, funciona pois 2147483647 um literal int e no double! No tem decimal !
Na linha 5, o compilador reclamar pois 2147483647.0 um tipo double (o padro dos literais
de ponto flutuante) no pode ser atribudo a uma varivel float.
Na linha 6 feito uma converso explcita.
Na linha 7 atribudo um valor float por causa do sufixo f

Literais booleanos:

Os valores literais booleanos so compreendidos entre true ou false e s !

1. public class LitBoo {
2. public static void main(String[] args) {
3. boolean a = true; // ok
4. boolean b = false; // ok
5. boolean c = 1; // erro de compilacao
6. }
7. }


Cuidado que em Java diferentemente de C e outras linguagens no se pode atribuir
o valor 0 ou 1 para literais booleanos.

Literais Caracteres:

Os valores literais caracteres so compreendidos com um nico caracter entre apstrofo - se
voc no sabe o que apstrofo, o mesmo que aspas simples'

1. public class Carac {
2. public static void main(String[] args) {
3. char a = 'a'; // ok
4. char b = '@'; // ok
5. char c = '\u004E'; // refere-se a letra N
6. }
7. }


Como foi falado, o tipo char nada mais do que um tipo inteiro sem sinal de 16 bits, portanto
voc poder atribuir 2 ^ 16 - 1 = 65535. Veja no cdigo abaixo:

1. public class A {
2. public static void main(String[] args) {
3. char a = 65;
4. char b = (char)-65; // fora do intervalo, precisa de converso
5. char c = (char)70000; // fora do intervalo, precisa de converso
6. }
7. }


O tipo char pode aceitar valores fora de sua faixa, desde haja uma converso explcita.

ARRAY

Um array em Java um objeto criado na pilha (mmoria), usado para armazenar e trabalhar
com elementos semelhantes por seu tipo.
Para que se possa utilizar um array voc dever:

Declarar - Especificar um nome e o tipo do array.
Construir - Informar o tamanho do array, ou seja, numero de elementos.
Inicializar - Atribuir valores aos elementos do array.

Declarando um array

int[] a; // Recomendado
Thread b[];
String []c;

Observe que ainda no se sabe quantos elementos esses array armazenar, ou seja, no sabe
qual ser o custo para a memria desse array. Nunca coloque a quantidade de elementos do
array no passo de declarao, a no ser que voc faa tudo em uma nica linha (isso ser
mostrado posteriormente). Se voc ver uma questo onde aparece algo como no trecho a
seguir, marque sempre erro de compilao.

int[3] a; // s pode mencionar a quantidade de elementos, na construo :shock:

Construindo um array

int[] a = new int[3]; // Recomendado :o
Thread b[] = new Thread[1];
String []c = new String[19];

Usa-se a palavranewconjugada com o tipo do array. Nunca se esquea, em Java a contagem
dos elementos SEMPRE COMEAR EM 0 (ZERO), portando uma referncia ao elemento a[3]
(no array a acima) causar um erro, pois s existem os elementos 0, 1, 2 -> com um total de 3
elementos. Esse passo reserva espao na memria para os elementos do objeto array, pois
somente na construo que a JVM saber quantos elementos sero composto o array, com isso
cria-se um objeto na pilha com espao necessrio para armazenar os elementos do objeto. No
passo de construo, todos os elementos so inicializados com seus valores padro. Veja a
tabela a seguir:

TIPO VALOR PADRO
byte 0
short 0
int 0
long 0
float 0.0
double 0.0
boolean false
char '\u0000'
Object null

Inicializando um array

Atribuir valores aos elementos de um objeto array. Quando um array contrudo, seus
elementos so automaticamente inicializados com seus valores padro.

int[] x; // declarado
x = new int[2]; // construindo
x[0] = 10; // inicializando
x[1] = 20; // inicializando

Observe o seguinte cdigo:

1. 1.public class ArrayInicia {
2. 2.public static void main(String[] args) {
3. 3.float[] f;
4. 4.f = new float[1];
5. 5.System.out.println("valor antes "+f[0] );
6. 6.f[0] = 9.0;
7. 7.System.out.println("valor depois "+f[0] );
8. 8.}
9. 9.}


O que ser impresso na linha 5 e 7 ??? ( Feche os olhos e responda !!, No vale olhar...) Se
voc respondeu 0.0 e 9.0, parabns por voc ser uma pessoa de opnio! Mas infelizmente voc
errou !!! Lembra-se que todo valor literal ponto flutuante em Java por padro double,
portanto esse cdigo no compila. Se alterarmos esse cdigo e adicionar o sufixo f na linha 6
=> f[0] = 9.0f;, o resultado seria 0.0 e 9.0, por isso: PRESTE MAIS ATENO !!! :x

Os trs passos para a utilizao de um array: declarao, construo e inicializao podem ser
realizados em uma nica linha de cdigo. EUREKA !!! :!:

boolean[] c = { false, true, false };
int[] a = {0,1,1,1};
char[] b = {'a','b','c'};

Observe que a palavra chave new no foi utilizada, visto que est implcito o tipo no incio, o
nmero de elementos entre as chaves { }. Caso voc se depare com uma questo (como o
cdigo abaixo) que especifica o nmero de elementos juntamente com a inicializao na mesma
linha, no hesite em marcar a resposta: Erro de compilao !!!

int[3] a = {1, 2, 1}; // erro de compilao :x

Array Multidimensional

Um array multidimensional um array com mais de uma dimenso (isso ridculo de dizer!),
ou seja, uma coleo de objetos array dentro de um objeto array. Portanto um array definido
como: int[][] i = new int[3][]; nada mais do que um objeto array i que contm trs objeto
array (ainda no construdo) dentro. (Complicado?)

int[][] i = new int[2][];

O que isso significa ? O que so os elementos de i ?? Significa que foi criado um objeto na pilha
chamado a, e seus elementos ainda no foram contrudos. Para utilizar seus elementos, voc
dever constru-los como mostra o cdigo a seguir:

i[0] = new int[2]; // construdo o elemento 0 do array i
i[1] = new int[3]; // construdo o elemento 1 do array i

Quantos objetos foram criados na pilha ?

1 referenciado por a
2 referenciados por a[0] e a[1]

Total de objetos criados: 3 (trs)

Agora observe o seguinte cdigo:

1. public class TestArray {
2. public static void main(String[] args) {
3. String s = new String("Kuesley");
4. String[] nomes = { s, null, new String("Kuesley") };
5. }
6. }


Quantos objetos foram criados na pilha ?? :shock:

1 obj String referencido por s
1 obj array de String referenciado por nomes
1 obj String referenciado por nomes[2]

Observe que o elemento 0 apenas uma referncia para s portanto no criado um novo
objeto. O elemento 1 no tem um objeto referenciado, j o elemento 2 um objeto String.


Array Annimo

Como o prprio nome j diz, um objeto array criado sem a definio de um nome. Imagine
que voc precise passar um objeto array como parmetro para um mtodo, e voc no queira
criar um array, basta passar anonimamente. Veja como no cdigo abaixo:

1. public class A {
2. public static void main(String[] args) {
3. A obj_a = new A();
4. int soma = obj_a.somarArray( new int[] { 0,1,2,3 } );
5. System.out.println("Soma do array : "+soma);
6. }
7. public int somarArray( int[] a ) {
8. int rc = 0;
9. for ( int i=0; i < a.length; i++) {
10. rc += a[i];
11. }
12. return rc;
13. }
14. }


Observe que no foi criado um objeto array com um identificador especfico e passado como
parmetro, foi criado no momento em que se passar o argumento.

Outro exemplo:

int[][] numeros = new int[3][];
numeros[0] = new int[10];
numeros[1] = numeros[0];
numeros[2] = new int[] { 0,1,2,3 };


LEMBRE-SE: NUNCA ESPECIFIQUE O TAMANHO ENTRE OS COLCHETES, ISSO SER DEDUZIDO
DOS ELEMENTOS ENTRE O PAR DE CHAVES !!!

Array - Observaes

Algumas regras devem ser consideradas no uso de array que referenciam objetos!

Dado as classes:

1. class Car implements CarMove { }
2. class Mazda extends Car { }
3. class Fusca extends Car { }
4. class VMax { }
5. interface CarMove { }
6.
7. 1. public class Test {
8. 2. public static void main(String[] args) {
9. 3. Car[] cars = new Car[3];
10. 4. Fusca f = new Fusca(); // instanciando um obj do tipo Fusca
11. 5. cars[0] = f;
12. 6. }
13. 7. }


Observe que na linha 5, um objeto Fusca foi armazenado em um array do tipo Car. Por que isto
possivel ?
Existe um pergunta que voc sempre dever fazer, para saber se uma classe X pode ser
armazenada em um array do tipo Y.

X membro de Y

Em nosso contexto: Fusca membro de Car ?
Em outras palavras, Fusca uma subclasse de Car ?
Se a resposta for positiva, essa atribuio perfeitamente possvel !

Agora observe o seguinte cdigo (baseando-se nas mesmas classes Car, Fusca ):


1. 1. public class Test {
2. 2. public static void main(String[] args) {
3. 3. Fusca[] fuscas = new Fusca[3];
4. 4. Car c = new Car();
5. 5. fuscas[0] = c;
6. 6. }
7. 7. }


Isso possvel ?? Se tem dvida, faa voc mesmo e faa o teste e sem preguia !!!

Aproveite e teste o seguinte:


1. 1. public class Test {
2. 2. public static void main(String[] args) {
3. 3. Car[] c = new Fusca[1];
4. 4. Fusca[] f = new Car[1];
5. 5. }
6. 6. }


O que acontecer com o cdigo acima ?

Mudando um pouco de assunto!

Um objeto array de uma interface, pode receber referencias de instncias de classes que
implementem essa interface.

1. public class Test {
2. public static void main(String[] args) {
3. CarMove[] cm = new CarMove[4];
4. cm[0] = new Car(); // ok! Car implementa CarMov
5. cm[1] = new Fusca(); // ok! Fusca implementa CarMov
6. cm[2] = new Mazda(); // ok! Mazda implementa CarMov
7. cm[3] = new VMax(); // erro de compilao
8. }
9. }


LEMBRE-SE: Vmax membro de CarMove ???

Cuidado com detalhes de atribuies tais como:

int[] n = new int[10];
int[] m = new int[] {8,2,1,2,0};
n = m; // ok! mesmo tipo

int[][] n = new int[3][];
int[] m = new int[] {1,2,3};
n = m; // erro! objetos diferentes

A JVM no elimina o objeto n da pilha e subtitui pelo valor de m!
Observe tambm que o array n tem 2 dimenses, enquanto que m tem apenas uma!

Porm o seguinte cdigo seria perfeitamente possvel:

n[0] = m; // ok!

As questes relacionadas com array multidimensionais so esdrxulas, portanto ESTUDE! :D
Se achas que estou brincando imagine a seguinte questo ?

1. 1. public class Test {
2. 2. public static void main(String[] args) {
3. 3. int[][][] nums = new int[2][][];
4. 4. int[] simple = new int[] {1,2,3,4,5};
5. 5. nums[0] = new int[1][];
6. 6. nums[0][0] = new int[10];
7. 7. nums[1] = new int[3][];
8. 8. nums[1][0] = simple;
9. 9. nums[1][1] = new int[] { 3,3,3 };
10. 10.nums[1][2] = new int[] { 1,2,3 };
11. 11.????
12. 12.}
13. 13.}


1) Qual das linhas abaixo podero ser colocadas na linha 11 do cdigo acima sem que d erro
de compilao ?? (marque mais de uma) :shock:

a) nums[1][0] = nums[0][0];
b) nums[1][0] = 10;
c) nums[1][0][3] = 9;
d) nums[1][0][2] = 9;
e) nums[0][0][3] = 9;
f) nums[0][0] = nums[2][1]

[color=green:8dd638c6bd]Resposta no final do captulo !!![/color:8dd638c6bd]

No sacanagem, os caras do questes da pra pior !!!

Variveis de Instncia

Declarada no escopo da classe, e tem um valor padro conforme o seu tipo. (Mesmos valores
atribudos na inicializao de um array estudado anteriormente):

1. public class Book {
2. String title;
3. public static void main(String[] args) {
4. Book b = new Book(); // instanciando a classe
5. System.out.println("O titulo "+b.title);
6. }
7. }


Resultado: O titulo null ! String um objeto e no um tipo primitivo!

Para utilizar um varivel primitiva, voc SEMPRE ter que inicializ-la, caso contrrio o
compilador lhe tratar de forma inescrupulosa !


1. public class TheBookonTheTable {
2. public static void main(String[] args) {
3. int i;
4. System.out.println("o valor de i "+i);
5. }
6. }


O cdigo acima gerar um conflito entre o programador e o compilador! No tente !
irreparvel!!!

Objeto Local

Um Objeto locai (varivel declarada dentro de um mtodo) tem comportamento distinto de uma
varivel de instncia. Quando um objeto declarado como membro de uma classe, e uma
instncia dessa classe criada, esse membro inicializado com null (pois em Java null um
valor) e quando declarado no escopo de um mtodo, o objeto no inicializado, portanto
qualquer ousadia de uso, relaes cortadas com o compilador!

1. 1. import java.util.*;
2. 2. public class Test {
3. 3. public static void main(String[] args) {
4. 4. Date data;
5. 5. Periodo p = new Periodo();
6. 6. if (data == null) System.out.print("inicio nulo"); // erro de compilao

7. 7. if (p.inicio == null) System.out.print("inicio nulo"); // ok -
membro nulo
8. 8. if (p.fim == null) System.out.print("fim nulo"); // ok - membro nulo
9. 9. }
10. 10.}
11. 11.class Periodo {
12. 12.Date inicio;
13. 13.Date fim;
14. 14.}


O compilador mostrar um erro na linha 6, pois o objeto local data no foi inicializado !

Mtodo main

Voc j deve estar cansado de ver as declaraes public static void main(String[] args), porm
saiba que essa a chave para a JVM executar uma aplicao em Java. Maiores detalhes sobre
modificadores sero vistos no captulo 2, mas algumas observaes devem ser ressaltadas
nesse captulo. Observe:

public static void main(String[] args) { ... } // vlido - recomendado
static public void main(String[] args) { ... } // vlido
public static void main(String[] a) { ... } // vlido
public static void main(String [] a) { ... } // vlido
public static void main(String a[]) { ... } // vlido
public static void main(String a []) { ... } // vlido
public static void main([]String args) { ... } // no vlido

Mas o que esse array de String que o mtodo main recebe ?
Esse array usado para receber parmetros da linha de comando, quando um programa Java
est sendo executado.

c:\>java Test Kuesley Fernandes

Nesse caso, dois parmetros esto sendo passados: Kuesley Fernandes

Portanto com o seguinte cdigo:

1. public class Test {
2. public static void main(String[] args) {
3. System.out.println("Meu nome : "+args[0]+args[1]);
4. }
5. }


O Resultado seria: Meu nome Kuesley Fernandes :o
E se fosse executado: c:\>java Test Kuesley
Qual seria o resultado ?? TESTE !!! :o

QUESTO:

2) O que far o seguinte cdigo ?

1. public class Array {
2. int[] a;
3. public static void main(String[] args) {
4. Array obj = new Array();
5. if (obj == null) {
6. System.out.println("ERRO");
7. } else {
8. System.out.println("OK");
9. }
10. }
11. }

a) Mostrar ERRO na tela
b) Mostrar OK na tela
c) Programa no ir compilar
d) Uma exceo ser lanada
e) Mostrar null na tela

Resposta no final do captulo !!!

Bom acho que chagamos ao final do captulo 1, esse captulo fundamental para o
entendimento dos seguintes !!! :!: :!:

Respostas dos exerccios propostos:

1) a, c, d, e, f

Lembre-se compilar at compila, porm a respostafgerar um exceo em tempo de
execuo.
2) b

Cap. 2 - Modificadores



Captulo 2 - Modificadores e Controle de Acesso

Como em todas as linguagens de programao, a acessibilidade a uma classe/mtodo deve
seguir algumas regras, e de extrema necessidade que voc as saiba para no vacilar na hora
do exame!

Modificadores

public
private
protected
abstract
static
final
transient
strictfp
synchronized
volative
native
padro


LEMBRE-SE: com exceo do modificador PADRO, todas as demais so palavras chaves em
Java.

1 - MODIFICADORES PARA CLASSES:

1.1 - padro

Um modificador de acesso determina como ser a visibilidade de uma classe/mtodo a partir de
outras classes ou mtodos.

Dado o arquivo Car.java:

1. class Car {
2. // cdigo da classe
3. }


Observe que no foi definido nenhum modificador para a classe, portanto o modificador de
acesso nesse caso padro (default ou friendly)! O modificador padro define que a classe s
poder ser acessada por outra classes dentro do mesmo pacote. Uma tentativa de acesso a
classe Car a partir de uma classe de outro pacote resultar em um erro de compilao.

Dada as classes:

1. Car.java
2. package carros;
3. class Car { ... }
4.
5. Oficina.java
6. package oficina;
7. import carros.*;
8. class Oficina extends Car { ... } // Erro de compilao
9.
10. Conserto.java
11. package conserto;
12. import carros.*;
13. class Conserto {
14. public static void main(String[] args) {
15. Car c = new Car(); // Erro de compilacao
16. }
17. }


Observe que na classe Oficina houve uma tentativa de acesso por herana, mas como a classe
Car tem acesso padro e a classe Oficina est em um pacote diferente do pacote da classe Car,
causou erro de compilao. Semelhantemente o erro ocorreu na classe Conserto, apesar de que
a forma de tentativa de acesso classe Car foi atravs de referencia. Agora observe:

1. Car.java
2. package carros;
3. class Car { ... }
4.
5. Oficina.java
6. package carros;
7. class Oficina extends Car { ... } // ok
8.
9. Conserto.java
10. package carros;
11. class Conserto {
12. public static void main(String[] args) {
13. Car c = new Car(); // ok
14. }
15. }


Observe que uma classe com modificar padro pode ser acessada somente por classes/mtodos
do mesmo pacote.

1.2 - public

O modificador public o mais liberal, ou seja, faz com que a classe possa ser acessada por
qualquer classe independente de estarem ou no no mesmo pacote.

1. Car.java
2. package carros;
3. public class Car {
4. String getColor() {
5. return "yellow";
6. }
7. }
8.
9. Oficina.java
10. package oficina;
11. import carros.*;
12. public class Oficina {
13. public static void main(String[] args) {
14. Car c = new Car(); // ok
15. }
16. }


Observe que a classe Car publica e visvel por qualquer classe, portanto muito cuidado ao
definir uma classe como pblica, pode cair na vista do inimigo.

1) O que acontecer com o seguinte cdigo:

1. Car.java
2. package carros;
3. public class Car {
4. String getColor() {
5. return "yellow";
6. }
7. }
8.
9. Oficina.java
10. package oficina;
11. import carros.*;
12. public class Oficina {
13. public static void main(String[] args) {
14. Car c = new Car();
15. System.out.println("A cor e "+c.getColor());
16. }
17. }


a) Mostrar: A cor e yellow
b) Erro de compilao
c) Exceo na hora da execuo
d) Mostrar: A cor e null
e) Mostrar: A cor e

[color=green:0fc8cb2b92]Resposta no final do captulo !!![/color:0fc8cb2b92]

Caso vc tenha errado, no se preocupe, pois os modificadores aplicados a membros sero
discutidos posteriormente.

1.3 - abstract

Uma classe definida como abstract no permite criar instncias dessa classe, ou seja, no
podemos ter objetos de uma classe abstrata. O modificador abstract aplica o mesmo conceito
de abstrao que conhecemos no mundo real, ou seja, parta do pressuposto que uma classe
abstrata no sabe qual seja o seu "inteiro" comportamento.
Voc deve estar se perguntando, por que ento eu usaria uma classe abstrata se no posso
instanci-la ? Esse e um recurso interessantssimo das linguagens orientadas a objetos, a
extensibilidade, voc pode definir uma classe Car com comportamentos (mtodos) abstratos e
deixar que as subclasses definam esses comportamentos de forma diferente, mesmo porque a
forma de acelerao de um Mazda RX7 bem diferente de um Fusca 1300 (putz que
comparao mais esdrxula!)

1. Car.java
2. package carros;
3. public abstract class Car { ... }
4.
5. Oficina.java
6. package carros;
7. public class Oficina {
8. public static void main(String[] args) {
9. Car c = new Car(); // Erro de compilao
10. }
11. }


[color=red:0fc8cb2b92]Erro de compilao: // carros.Car is abstract; cannot be
instantiated[/color:0fc8cb2b92]

No se preocupe se voc ver uma declarao: abstract public class Car
No erro de sintaxe colocar o modificar abstract antes do public.

Podemos concluir que uma classe abstrata no est pronta para ser usada como uma classe
concreta, ou seja, ainda no sabe "coisas" sobre a classe, que muito provavelmento ser
implementado em subclasses (a no ser que algum programador resolva criar uma classe
abstrata e no us-la - puro capricho!)

1.3 - final

Um classe final no permite que se tenha subclasses, ou seja, no se pode aplicar a herana
em uma classe que seja final. Novamente voc como curioso quer saber porque usaria uma
classe final ? Pense em um contexto que se tenha uma classe "perfeita" que faz tudo
exatamente como voc definiu, e no precise que sua classe seja herdada por ningum, para
evitar que Programadores Juniores faam cacas !!! Tem mais um detalhe tcnico mais
importante que o citado anteriormente: uma classe final, mais rpida que classes no final,
isso porque a mquina virtual sabe que no haver nenhuma herana (nem pelos prprios
caras da Sun) por isso o processo de execuo mais rpido. Um exemplo disso a classe
String ! Porque deveramos mexer nessa classe ? Se voc ja achou alguma implementao para
ela, mande seu currculo para a Sun, o endereo : pretensao@sun.com (no sei porque est
em portugus, sendo que so americanos):

1. Car.java
2. package carros;
3. public final class Car { ... }
4.
5. Oficina.java
6. package carros;
7. public class Oficina extends Car { // erro de compilao
8. public static void main(String[] args) {
9. Car c = new Car();
10. }
11. }


[color=red:0fc8cb2b92]Erro de compilao: cannot inherit from final
carros.Car[/color:0fc8cb2b92]

Se voc um cara esperto, j deve ter percebido que o modificador final no deve ser usado
com o modificador abstract, visto porque no faz sentido temos uma classe final e abstrata !
Como faramos a herana sendo que a classe final !

1. Car.java
2. package carros;
3. public abstract final class Car { ... } // erro de compilao


[color=red:0fc8cb2b92]Erro de compilao: illegal combination of modifiers: abstract and
final[/color:0fc8cb2b92]


1.4 - strictfp

Define que membros/variveis da classe sigam as normas do padro IEE754 de ponto
flutuante. Se voc no tiver o que fazer, poder estudar esse padro, mas saiba que para o
exame no ser necessrio saber nada sobre o padro, simplesmente o que o modificador faz.
Como seu escopo a classe, todos os mtodos seguiram o mesmo padro. Voc tambem
poder definir esse modificador para um mtodo especifico, mas isso ser discutido
posteriormente.

1. Car.java
2. package carros;
3. public strictfp class Car { ... } // ok


Todos os mtodos seguiram o padro IEE754

2 - MODIFICADORES PARA MTODOS:

2.1 - padro

No ser necessrio falar muito, pois semelhante ao conceito de classe, ou seja, um mtodo
definido como padro s poder ser acessado por classes dentro do mesmo pacote.

1. Car.java
2. package carros;
3. public class Car {
4. String getColor() { mtodo com acesso padro
5. return "red";
6. }
7. }
8.
9. Oficina.java
10. package carros;
11. public class Oficina {
12. public static void main(String[] args) {
13. Car c = new Car();
14. System.out.println("a cor do carro e "+c.getColor()); // ok
15. }
16. }


Nenhum problema de acesso pois as classes esto no mesmo pacote

Se definirmos a classe Oficina da seguinte forma:

1. package oficina;
2. import carros.*;
3. public class Oficina {
4. public static void main(String[] args) {
5. Car c = new Car();
6. System.out.println("a cor do carro e "+c.getColor()); // erro de compilao
7. }
8. }


[color=red:0fc8cb2b92]Erro de compilao: getColor() is not public in carros.Car; cannot be
accessed from outside package[/color:0fc8cb2b92]

2.2 - public

Um mtodo pblico pode ser acessado por qualquer classe em qualquer pacote. bvio que o
acesso a um mtodo s permitido se voc tiver primeiro acesso classe, portanto uma
tentativa de acesso a um mtodo pblico de uma classe com acesso padro no ser possvel a
classes pertencentes a pacotes diferentes da classe que est se desejando o acesso! Se ficou
confuso, no se preocupe, vai piorar !!

1. Car.java
2. package carros;
3. class Car {
4. public String getColor() {
5. return "red";
6. }
7. }
8.
9. Oficina.java
10. package oficina;
11. import carros.*;
12. class Oficina {
13. public static void main(String[] args) {
14. Car c = new Car();
15. System.out.println("a cor e "+c.getColor()); // erro de compilao
16. }
17. }


[color=red:0fc8cb2b92]Erro de compilao: carros.Car is not public in carros; cannot be
accessed from outside package[/color:0fc8cb2b92]

Portanto, mesmo que o mtodo seja pblico (como o caso de getColor()), a classe (nesse
caso Car) tambm dever ser visvel ao mtodo que est chamando !

2.3 - private

Um mtodo private restringe o acesso do mtodo somente classe que o definiu, ou seja, um
mtodo privado s poder ser acesso dentro da classe que o definiu e ponto final!

1. Car.java
2. package carros;
3. class Car {
4. private String getColor() { // Nota 1
5. return "red";
6. }
7.
8. public void imprimirCor() {
9. System.out.println( "a cor do carro e "+getColor()); // Nota 2
10. }
11. }
12.
13. Oficina.java
14. package carros;
15. class Oficina {
16. public static void main(String[] args) {
17. Car c = new Car();
18. System.out.println("a cor e "+c.getColor()); // Nota 3
19. c.imprimirCor(); // Nota 4
20. }
21. }


Nota 1: O mtodo foi definido como private
Nota 2: O acesso ao mtodo getColor est sendo feito dentro da prpria classe. Isso no
ocasiona erro de compilao!
Nota 3: Uma tentativa de acesso a um mtodo private - erro de compilao!
Nota 4: Acesso a um mtodo pblico que acesso um mtodo private, funciona como uma
interface entre o mtodo getColor e a classe Oficina, isso perfeitamente possvel.

Esse modificador o mais restringvel, os inimigos tremem quando ele usado!

2.4 - protected

Ele um pouco mais liberal que o modificador padro, pois ele permite que um mtodo de uma
classe X definida em um pacote PX possa ser acessado por uma classe Y de um pacote PY
desde que a classe Y estenda da classe X ( que confuso !!!) No esquenta isso bem fcil!

1. Car.java
2. package carros;
3. public class Car {
4. protected String getColor() { // Nota 1
5. return "red";
6. }
7. }
8.
9. Oficina.java
10. package oficina;
11. import carros.*;
12. class Oficina extends Car { // Nota 2
13. public void imprimirCor() {
14. System.out.println("a cor e "+getColor()); // Nota 3
15. }
16. }


Nota 1: O mtodo foi definido com protected
Nota 2: A classe Oficina estende de Car - por isso os mtodos protegidos podem ser acessados.
Nota 3: O mtodo est sendo acessado por herana, mesmo que a classe Oficina esteja
definido em pacotes diferentes!

Observe agora:

1. Car.java
2. package carros;
3. public class Car {
4. protected String getColor() {
5. return "red";
6. }
7. }
8.
9. Oficina.java
10. package oficina;
11. import carros.*;
12. class Oficina { // Nota 1
13. public void imprimirCor() {
14. Car c = new Car();
15. System.out.println("a cor e "+c.getColor()); // Nota 2
16. }
17. }


Nota 1: A classe Oficina no estende de nenhuma superclasse.
Nota 2: H um tentativa de acesso por referncia ao mtodo getColor que protegido, o que
causar um erro de compilao: [color=red:0fc8cb2b92]getColor()has protected access in
carros.Car[/color:0fc8cb2b92]

Uma classe que herda um mtodo protegido torna-o private para suas subclasses. Complicou ?

1. Car.java
2. package carros;
3. public class Car {
4. protected String getColor() {
5. return "red";
6. }
7. }
8.
9. Passeio.java
10. package passeio;
11. import carros.*;
12. class Passeio extends Car {
13. public void imprimirCor() {
14. System.out.println("a cor e "+getColor()); // Nota 1
15. }
16. }


1. Mazda.java
2. package esportivo;
3. import carros.*;
4. class Mazda extends Passeio {
5. public void mostrarCor() {
6. System.out.println("a cor e "+getColor()); // Nota 2
7. }
8. }


Nota 1: O mtodo pode ser acesso, pois herda de uma classe que o definiu como protegido.
Nota 2: Erro de compilao, nessa hierarquia, o direito de acesso da classe Passeio ao mtodo
protegido da classe Car, no outorgado a classe Mazda pois essa herda de Passeio, ou seja,
um mtodo protected se torna private para suas subclasses quando h herana, no permitindo
que as subclasses de Passeio herdem os mtodos protegidos que herdou.

2.5 - abstract

Um mtodo abstrato no implementa nenhuma funcionalidade, somente assina o mtodo e faz
com que a primeira subclasse concreta seja obrigada a implementar o mtodo. Uma classe que
possua um mtodo abstrato deve obrigatoriamente ser abstrata!

1. Car.java
2. package carros;
3. public abstract class Car { // Nota 1
4. public abstract String getColor(); // Nota 2
5. }
6.
7. Oficina.java
8. package oficina;
9. import carros.*;
10. public class Oficina extends Car { // Nota 3
11. public String getColor() {
12. return "red";
13. }
14. }


Nota 1: A classe Car tambm teve que ser definida com abstract, uma vez que uma classe
contenha um mtodo abstract
Nota 2: A definio de um mtodo abstrato no pode ter implementao, veja que nem as
chaves foram colocadas, e assim que deve ser!
Nota 3: A classe Oficina uma classe concreta (no abstrata) portanto deve implementar
todos os mtodos abstratos da sua superclasse, se no fizer, o compilador insultar o
programador, melhor no brincar!

Erros comuns

1 - Tentar implementar um mtodo abstrato:

1. Car.java
2. package carros;
3. public abstract class Car {
4. public abstract String getColor() { ... } // Erro
5. }


[color=red:0fc8cb2b92]Erro de compilao: abstract methods cannot have a
body[/color:0fc8cb2b92]

LEMBRE-SE: Um mtodo abstrato deve terminar com ";" e no ter as chaves !

No definir a classe como abstrata

1. Car.java
2. package carros;
3. public class Car {
4. public abstract String getColor(); // Nota 1
5. }


[color=red:0fc8cb2b92]Erro de compilao: carros.Car should be declared abstract; it does not
define getColor() in carros.Car[/color:0fc8cb2b92]

No implementar os mtodos abstratos na primeira subclasse concreta

1. Car.java
2. package carros;
3. public abstract class Car {
4. public abstract String getColor();
5. public abstract String getSize();
6. public double getPrice() {
7. return 24000.00;
8. }
9. }
10.
11. Passeio.java
12. package carros;
13. public class Passeio extends Car { // Nota 1
14. public String getColor() { // Nota 2
15. return "red";
16. }



Nota 1: A classe Passeio estende de Car (classe abstrata) por isso, deve implementar todos os
mtodos abstratos, o que no est acontecendo, se tertarmos compilar essa classe:
carros.Passeio should be declared abstract; it does not define getSize() in carros.Car
Nota 2: O mtodo foi implementado.

A regra simples: todos os mtodos abstratos devem ser implementados na primeira subclasse
concreta, se definssemos a classe Passeio como abstract no caso anterior, no teria problemas
de compilao, pois o mtodo abstratos (getSize, getColor) no precisavam ser implementados
na classe Passeio e sim na primeira subclasse concreta.
O modificador abstract no pode ser conjugado com modificador private, visto porque um
mtodo abstrato deve ser implementado em uma subclasse e um mtodo private no visvel a
nenhuma outra classe.

2.6 - final

Um mtodo final define que no pode ser sobreposto, estudaremos mais afundo o que
sobreposio de mtodos no captulo 8.

1. Car.java
2. package carros;
3. public class Car {
4. public final String getColor() { // Nota 1
5. return "red";
6. }
7. }
8.
9. class Mazda extends Car {
10. public String getColor() { // Nota 2
11. return "yellow";
12. }
13. }


Nota 1: Mtodo definido com final no pode ser sobreposto.
Nota 2: Tentativa de sobrepor um mtodo final - o que ocasiona um erro de compilao:
[color=red:0fc8cb2b92]getColor() in carros.Mazda cannot override getColor()in carros.Car;
overridden method is final[/color:0fc8cb2b92]

2.7 - static

Um mtodo esttico define que esse pode ser executado ser que exista uma instncia da classe
- um objeto. Voc s deve us-lo se tiver certeza do que est fazendo.

1. Car.java
2. package carros;
3. public class Car {
4. public static String getColor() { // Nota 1
5. return "red";
6. }
7. }


1. Oficina.java
2. package oficina;
3. import carros.*;
4. class Oficina {
5. public static void main(String[] args) {
6. System.out.println("a cor e "+Car.getColor()); // Nota 2
7. }
8. }


Nota 1: Mtodo definido com static, no h necessidade de um objeto para acess-lo.
Nota 2: Note que no foi preciso criar um objeto para acessar o mtodo getColor

2.8 - native

Define que a implementao do mtodo foi escrita em uma linguagem nativa com por exemplo
C ou C++.

2.9 - strictfp

Define que os valores de ponto flutuante do mtodo devem seguir o padro I33754, no se
preocupe com esse padro agora - saiba somente o que o modificar faz.

2.10 - synchronized

Faz com o mtodo seja acessado por uma thread de cada vez, esse estudo ser discutido no
captulo 9, ou seja, quando um mtodo sincronizado estiver sendo executado por uma thread
as demais devero aguardar para iniciar a sua execuo.

3 - Modificadores para variveis de instncia:

Apesar de muitos acharem que atributos, varivel de instncia e propriedades so as mesmas
coisas, gostaria de deixar bem claro que existem diferenas sutis, mas que no sero relevantes
nesse estudo. Por conveno chameremos de varivel de instncia por achar que o termo
mais correto que define esse conceito.

3.1 - padro

Segue as mesmas regras de um mtodo, ou seja, o acesso s permitido a classes dentro do
mesmo pacote.

1. Car.java
2. package carros;
3. public class Car {
4. double preco; // Nota 1
5. }
6.
7. Oficina.java
8. package carros;
9. class Oficina {
10. public static void main(String[] args) {
11. Car c = new Car();
12. c.preco = 13990.00; // Nota 2
13. }
14. }


Nota 1: No foi definido nenhum modificado, portanto assume o modificador padro
Nota 2: Acesso a varivel de instncia (VI) de uma classe dentro do mesmo pacote

Observe agora:

1. Car.java
2. package carros;
3. public class Car {
4. double preco; // Nota 1
5. }
6.
7. Oficina.java
8. package oficina;
9. import carros.*;
10. class Oficina {
11. public static void main(String[] args) {
12. Car c = new Car();
13. c.preco = 13990.00; // Nota 2
14. }
15. }


Nota 1: No foi definido nenhum modificado, portanto assume o modificador padro
Nota 2: Acesso no permitido para classes de pacotes diferentes. Erro de compilao:
[color=red:0fc8cb2b92]preco is not public in carros.Car; cannot be accessed from outside
package[/color:0fc8cb2b92]

3.2 - public

O acesso a uma varivel de instncia pblica, segue as mesmas regras de um mtodo. S uma
dica ( sem nenhum nus) cuidado ao definir um VI pblica, pois com isso voc estar liberando
o acesso a todo o mundo, e isso pode enfraquecer sua classe, essa deciso deve ser bem
estudada, e no podemos esquecer do encapsulamento. dentro do mesmo pacote.

1. Car.java
2. package carros;
3. public class Car {
4. public double preco; // Nota 1
5. }
6.
7. Oficina.java
8. package oficina;
9. import carros.*;
10. class Oficina {
11. public static void main(String[] args) {
12. Car c = new Car();
13. c.preco = 13990.00; // Nota 2
14. }
15. }


Nota 1: Varivel definida como pblica, todo mundo pode acessar.
Nota 2: Acesso a uma VI pblica, compilao sem nenhum contratempo.

3.3 - private

Um varivel private restringe o acesso somente a prpria classe, o modificador que mais
limita o acesso a um membro de classe.

1. Car.java
2. package carros;
3. class Oficina {
4. private String endereco; // Nota 1
5. }
6.
7. public class Car {
8. public static void main(String[] args) {
9. Oficina o = new Oficina();
10. System.out.println("o endereco "+o.endereco); // Nota 2
11. }
12. }


Nota 1: Varivel definida como private, acesso somente dentro da prpria classe
Nota 2: Tentativa de acesso a uma membro privado, erro de compilao:
[color=red:0fc8cb2b92]endereco has private access in carros.Oficina[/color:0fc8cb2b92]

O modificador private usado para proteger uma classe do acesso direito a seus membros,
com isso podemos garantir uma classe bem segura, e deve ser usado para implementao do
conceito: encapsulamento.

3.4 - protected

Semelhante aos mtodos protegidos, uma varivel de instncia com esse modificador, limita o
acesso subclasses para classes de outros pacotes.

1. Pessoa.java
2. package p1;
3. public class Pessoa {
4. protected String nome = "Kuesley"; // nota 1
5. }
6.
7. Diretor.java
8. package p2;
9. import p1.*;
10. public class Diretor extends Pessoa { // subclasse de Pessoa
11. public String getNome() {
12. return nome; // nota 2
13. }
14. }


Nota 1: Membro protegido, pode ser acessador por uma subclasse, ou seja, herana.
Nota 2: Acesso ao membro herdado, apesar da classe Diretor estar em outro pacote, note que
nome foi definido como protected.

Vamos mudar um pouco a classe Diretor (definida logo acima) para:

1. Diretor.java
2. package p2;
3. import p1.*;
4. public class Diretor { // classe sem herana
5. public String getNome() {
6. Pessoa p = new Pessoa();
7. return p.nome; // nota 1
8. }
9. }


Nota 1: Se tentarmos compilar a classe Diretor o compilador mostrar a mensagem: nome has
protected access in p1.Pessoa

3.5 - final

Uma varivel de instncia do tipo final usada para armazenar valores constantes que no
sero e nem podem ser alterados (caso algum resolva cair em tentao) durante o escopo de
utilizao da classe.
Voc deve estar se perguntando, porque usar variveis que nunca sero alteradas ? E se no
meio do contexto da classe eu precisar alterar o valor de uma variavel final ? ESQUEA !! Uma
vez inicializada uma varivel com esse modificador nunca mais poder ser alterada. Imagine
que voc tenha uma classe chamada Pessoa e resolva arbitrariamente definir uma altura e peso
ideal - para qualquer pessoa os valores so idnticos e no podem ser alterados, pronto, ta
uma utilizao para uma varivel final. Talvez no tenha sido muito feliz no exemplo, mas
vamos v-lo na prtica.

1. Modelo.java
2. package p1;
3. public class Modelo {
4. public final int ALTURA_IDEAL_CM = 175;
5. public final int PESO_IDEAL_KG = 75;
6. }


Como os valores de ALTURA_IDEAL_CM e PESO_IDEAL_KG so finais, voc poder
implementar mtodos que usem esses valores para calcular por exemplo se uma pessoa, est
ou no fora de forma, sem que algum engraadinho fora de forma aumente o PESO_IDEAL_KG
para 100 kilos. Qualquer tentativa de mudana de uma varivel final resultar em alerta do
compilador.

O cdigo abaixo resultar em um erro de compilao:

1. package p2;
2. import p1.*;
3. public class Diretor {
4. public static void main(String[] args) {
5. Pessoa p = new Pessoa();
6. p.PESO_IDEAL_KG = 100;
7. }
8. }


[color=red:0fc8cb2b92]Erro de compilao: cannot assign a value to final variable
PESO_IDEAL_KG[/color:0fc8cb2b92]

Como estamos falando de uma variavel de instncia e j discutimos no captulo 1 sobre
variveis que so inicializadas automaticamente, saiba que uma VI deve ser inicializada
EXPLCITAMENTE pelo programador e no esperar que o compilador faa isso por voc!
Voc pode realizar essa inicializao de duas maneiras: a primeira junto com a declarao como
em nosso exemplo anterior e a segundo no mtodo constructor!

Primeira Forma:
1. package p1;
2. public class Pessoa {
3. public final int ALTURA_IDEAL_CM = 175;
4. public final int PESO_IDEAL_KG = 75;
5. public Pessoa() { ... } // mtodo construtor
6. }
7.
8. Segunda Forma:
9.
10. package p1;
11. public class Pessoa {
12. public final int ALTURA_IDEAL_CM;
13. public final int PESO_IDEAL_KG;
14. public Pessoa() {
15. ALTURA_IDEAL_CM = 75; // definido no mtodo construtor
16. PESO_IDEAL_KG = 75;
17. }
18. }


O compilador paciente e aguarda que voc inicialize at que o mtodo construtor seja
concludo, caso voc tenta esquecido ou tentado engan-lo, aguente as conseqencias.

1. package p1;
2. public class Pessoa {
3. public final int ALTURA_IDEAL_CM;
4. public final int PESO_IDEAL_KG;
5. public Pessoa() {
6. ALTURA_IDEAL_CM = 75; // Nota 1
7. }
8. }


Nota 1: Observe que somente o membro ALTURA_IDEAL_CM foi inicializado no construtor, e
como o membro PESO_IDEAL_KG no foi inicializado explicitamente na declarao, o
compilador mostrar a seguinte mensagem: variable PESO_IDEAL_KG might not have been
initialized

Portanto no conte com a idia de inicializao automtica mesmo que sejam tipos
primitivos para variveis com modificador final !

Uma interface tambm pode conter variveis de instncia, e mesmo que no sejam definida
explcitamente como final, ele assim ser!

1. FuncionarioPublico.java
2. package p1;
3. public interface FuncionarioPublico {
4. int tempoEstabilidade = 2; // Nota 1
5. }


1. ProcuradorEstado.java
2. package p2;
3. import p1.*;
4. public class ProcuradorEstado implements FuncionarioPublico {
5. public ProcuradorEstado() {
6. tempoEstabilidade = 10; // Nota 2
7. }
8. }


Nota 1: Membro de uma interface implicitamente public e final, observe que no foi preciso
defin-lo como public para se ter o acesso a outra classe mesmo estando em outro pacote!
Nota 2: Tentativa de alterar um membro de uma interface, como final, o compilador mostrar
a seguinte mensagem de erro: [color=red:0fc8cb2b92]cannot assign a value to final variable
tempoEstabilidade[/color:0fc8cb2b92]

3.6 - static

Esse modificador muito simples de se entender! Voc como um cara esperto sabe a
diferena de uma classe e um objeto certo ? (Se sua resposta for negativa, procure saber antes
de prosseguir!) Uma varivel de instncia com esse modificador compartilhada com todas as
instncias (objetos) dessa classe, ou seja, se voc tiver uma classe com um atributo esttico
voc no ter uma cpia desse atributo para cada objeto e sim uma nica cpia para todos,
portanto uma alterao do valor desse atributo em qualquer dos objetos, causar efeitos sobre
esse atributos para todas as instncia. Por isso, um membro esttico um membro da classe e
no do objeto!

1. Pessoa.java
2. package p1;
3. public class Pessoa {
4. public static int count = 0; // Nota 1
5. private String nome; // Nota 2
6.
7. public Pessoa(String n) { // Nota 3
8. nome = n; // Nota 4
9. count += 1; // Nota 5
10. }
11. public static int getCount() { // Nota 6
12. return count;
13. }
14. }



1. Clientes.java
2. package p2;
3. import p1.*;
4. public class Clientes {
5. public static void main(String[] args) {
6. System.out.println("Antes: "+Pessoa.getCount());
7. Pessoa p1 = new Pessoa("Kuesley");
8. Pessoa p2 = new Pessoa("Jose");
9. System.out.println("Depois: "+Pessoa.getCount());
10. }
11. }


Nota 1: Observe que foi criado uma variavel de instncia count esttico, ou seja, nico para
todas as intncias dessa classe!
Nota 2: A VI nome no static portando, cada instncia ter um nome distinto.
Nota 3: A classe Pessoa tem um modificador parametrizado!
Nota 4: Atribui VI 'nome' o valor informado na instanciao do objeto
Nota 5: Cada vez que o construtor chamado, acrescentado 1 variavel count
Nota 6: Mtodo que retorna o valor da varivel count. Talvez voc esteja se perguntando mas
porque esse mtodo static ? Imagine que voc precise chamar o mtodo getCount sem ter
nenhuma instncia de Pessoa, no h problema algum em nosso exemplo tirarmos o
modificador static do mtodo getCount, mas voc no poder cham-lo sem haver pelo menos
1 instncia ! Observe tambm que foi usado o nome da classe para chamar os mtodos e no o
objetos ('Pessoa.getCount()' ) , apesar de que no haveria problema pois a JVM saberia que se
trata de um modo static e se reportaria a classe para saber as informaes sobre a varivel
count.

Observe a definio das seguintes classes:

1. Pessoa.java
2. package p1;
3. public class Pessoa {
4. public static int count = 0;
5. private String nome;
6.
7. public Pessoa(String n) {
8. nome = n;
9. count += 1;
10. }
11. public int getCount() { // Removido o modificador static
12. return count;
13. }
14. }
15.
16. Clientes.java
17. package p2;
18. import p1.*;
19. public class Clientes {
20. public static void main(String[] args) {
21. Pessoa p1 = new Pessoa("Kuesley");
22. Pessoa p2 = new Pessoa("Jose");
23. System.out.println("Depois p1: "+p1.getCount()); // Nota 1
24. System.out.println("Depois p2: "+p2.getCount()); // Nota 2
25. System.out.println("Depois Pessoa: "+Pessoa.getCount()); // Nota 3
26. }
27. }


// Nota 1/2: Ambos retornaro 2 no mtodo getCount()
// Nota 3: [color=red:0fc8cb2b92]Erro de compilao: non-static method getCount() cannot be
referenced from a static context[/color:0fc8cb2b92]

OBSERVAO: Voc NUNCA poder referenciar de um contexto esttico, uma varivel ou
mtodo no esttico! Apesar de que isso j foi falado anteriormente, no estudo dos mtodos
estticos, mas sempre bom lembrarmos, pois os caras das provas de certificao. gostam de
pegar no nosso p quando se trata de contexto esttico!

Observe:

1. package p1;
2. public class Clientes {
3. int count = 0;
4. public static void main(String[] args) {
5. System.out.println(""+count);
6. }
7. }


[color=red:0fc8cb2b92]Erro de compilao: non-static variable count cannot be referenced
from a static context[/color:0fc8cb2b92]

Se voc quiser enganar o compilar da seguinte forma:

1. package p1;
2. public class Clientes {
3. int count = 0;
4. public void imprimirLista() {
5. System.out.println(""+count);
6. }
7. public static void main(String[] args) {
8. imprimirLista(); // Nota 1
9. }
10. }


Nota 1: O compilador saber que est tentando ser enganado e xingar:
[color=red:0fc8cb2b92]Erro: non-static variable count cannot be referenced from a static
context[/color:0fc8cb2b92]


3.7 - transient

Esse modificador indica a JVM para no esquentar a cabea com as variveis transient quando
for realizar a serializao de um objeto! Calma! Calma! Calma! Se voc no sabe o que
serializar um objeto, no se preocupe, por enquanto a Sun no est exigindo que voc tenha
esse conhecimento - apesar de ser um dos recursos mais brilhantes da linguagem Java, e
usado para a programao em ambientes distribudos! Por isso, apresse seus estudos!
Mesmo assim, gostaria que voc tivesse uma idia do que serializar um objeto, pois assim
acredito que fique mais fcil a compreenso desse modificador.
Imagine que voc esteja desenvolvendo uma aplicao em um ambiente de rede e precise que
um objeto Pessoa seja enviado para um outra mquina da rede, e l continue o processo com
esse objeto, esse processo conhecido como serializao, ou seja, transformar um objeto em
uma sequencia de bytes e envi-lo para outra mquina (consequentemente, outra JVM) que
deserializar essa seqencia de bytes, obtendo o objeto como na mquina de origem! Quem
disse que no h milagres na informtica!!!

1. public class Pessoa {
2. public String nome;
3. public String endereco.
4. transient public Image Foto; // Nota 1
5. }


Nota 1: Imagine que sua conexo de rede seja muito ruim! E voc no precise ficar
transportanto a foto da pessoa na rede, com o modificador transient o membro Foto no ser
serializado!

3.8 - volatile

Quando uma variavel de instancia com esse modificador alterada, a threads dever
sincronizar sua cpia com a cpia principal.No se preocupe em saber como isso funciona,
estudaremos com exatido isso no captulo 9!

Uma analogia a esse modificador o caso dos programadores que quando alteram um projeto
devem sempre alterar a documentao para que todos os demais membros da equipe estejam
atualizados!

IMPLEMENTAO DE INTERFACE:

Voc ter que saber algumas regras sobre interface para se certificar, e dever saber de "cor e
salteado" (nunca tinha citado isso) como funciona a interface Runnable ! Uma interface uma
espcie de contrato que uma classe deve fazer e cumprir para que todos fiquem felizes! Veja
como a implementao de uma interface:

1. public interface FuncoesPublicas {
2. void assinarPonto();
3. void executarResponsabilidade();
4. }


Uma interface nada mais que uma classe totalmente abstrata, ou seja, s existe as
assinaturas de mtodos!
Apesar de no terem sidos definidos como abstract e public, convencionalmente os mtodos de
uma interface o so. Portanto o compilador os enxerga:

1. public interface FuncoesPublicas {
2. public abstract void assinarPonto();
3. public abstract void executarResponsabilidade();
4. }


Apesar de no existir herana mltipla em Java para classe em Java, as interfaces podem
herdar de multiplas interface, veja o cdigo a seguir:

1. public interface FuncaoAnimal {
2. void nascer();
3. }
4.
5. interface FuncaoAve extends FuncaoAnimal {
6. void voar();
7. }
8.
9. interface FuncaoReptil extends FuncaoAnimal {
10. void rastejar();
11. }
12.
13. interface FuncaoCobraVoadora extends FuncaoAve, FuncaoReptil { // Nota 1
14. }


Nota 1: Um interface pode herdar mais de uma interface! No pense em fazer isso com uma
classe!
Apesar de que uma classe pode implementar vrias interfaces:

Vejamos:

1. class CobraViva implements FuncaoAnimal, Runnable { ... }


Voc deve saber algumas regras quanto declarao de constante de interface:

1. public interface FuncoesPublicas {
2. int tempoServico = 0;
3. }


Apesar de no estar explcitamente definido mas a varivel tempoServico :

public
final
static

O equivalente a:

1. public interface FuncoesPublicas {
2. public static final int tempoServico = 0;
3. }



CONSIDERAES FINAIS:

Modificadores de acesso:

- Os modificadores de acesso: (padro, public, private e protected) nunca podero ser
combinados !

Mtodos
- Nunca poder ser definido como (transient, volative)
- Um mtodo nunca poder ser abstract e final
- Um mtodo nunca poder ser abstract e strictfp
- Um mtodo nunca poder ser abstract e native
- Um mtodo nunca poder ser abstract e synchronized
- Um mtodo nunca poder ser abstract e private
- Um mtodo final nunca poder ser sobreposto
- Um mtodo abstrato nunca poder ser implementado
- Se um mtodo for abstrato a classe tambm ser

Varivel de Instncia
- Pode ter qualquer um dos quatro modificadores de acesso
- Podem ser (volative, transient, final, static)
- No pode ser (abstract, native, synchronized, strictfp) -

Interfaces
- Uma interface nunca herda uma classe
- Uma classe nunca herda uma interface
- Uma interface nunca implementa outra interface
- Uma classe nunca implementa outra classe
- Uma interface pode herdar vrias interfaces
- Uma variavel de uma interface sempre ser implcitamente: (public, final, static)
- Um mtodo de uma interface sempre ser (public, abstract)

Lembre-se da Interface: java.lang.Runnable

Apesar de que veremos ela com mais detalhes no captulo 9 (esse o captulo) !

Ela s tem um mtodo: public void run();

Este o final do captulo 2 !!!

Respostas dos exerccios propostos:

1) b


Cap. 3 - Operadores e atribuies



Captulo 3 - Operadores e atribuies

3.1 - Introduo

A compreenso desse captulo muito importante pois trata de um assunto essencial em
qualquer linguagem de programao, as diversas formas de se atribuir e manipular valores de
uma varivel. Alm de ser um dos elementos fundamentais de uma linguagem de programao,
as variveis tem um papel importante na gerao de programas e suas peculiaridades sero
abordadas nesse captulo (pelo menos o que esperamos) !

A forma mais elementar de se atribuir um valor a uma varivel :

x = 0;

Mas no espere que no exame, haja perguntas com esse desprezo de complexidade, muito pelo
contrrio, o que normalmente voc no utiliza ou nunca utilizou com certeza estaro l
(naquela bendita prova)!!!

byte x = 10;

Lembra-se do captulo 1 ? Que na linha anterior 10 um valor literal int, composto por 32 bits e
que um tipo byte s tem capacidade para armazenar 8 bits. Voc deve estar se perguntando e
o que acontece com o resto dos bits ? Calma, para todas essas perguntas em algum lugar no
universo haver uma resposta. Nesse caso o compilador generoso e executa a converso
implicitamente para voc. Portanto uma varivel nada mais do que um repositrio de bits
para a representao de algum valor. O que est armazenado na varivel x ? Se voc
respondeu 00001010 est no caminho certo para o sucesso de sua certificao ! Como o
compilador realizou a converso de int para byte, os 24 bits de diferena foram desprezados.

byte x = 19; // ok
byte y = x; // ok
byte z = x + y; // deveria aceitar, mas necessita de uma converso explcita.

Toda operao envolvendo dois tipos inteiros sejam eles (byte e short, long e byte) retornaram
um tipo int

Falando em Objetos:

Button b = new Button();

O que b armazena ? Se voc pensou em dizer que b armazena um objeto do tipo Button, sua
resposta est errada ! b armazena um conjunto de bits usados para acessar (referenciar) o
objeto na memria. Portanto, podemos dizer a rigor que b no um objeto do tipo Button e
sim uma forma (atravs de uma sequncia de bits) usada para acessar esse objeto na
memria.

Falando um pouco sobre atribuies de nmero primitivos

Atribuio Observao

byte a = 19; byte a = (byte)19;
byte b = 128; // No possvel sem uma converso explcita
byte c = (byte)128; // Ok

O valor 128 no pode ser atribudo varivel b por ultrapassar a capacidade em bits do tipo
byte - uma converso se faz necessria. Mas devemos ressaltar um acontecimento muito
interessante nesse caso. Qual o valor da varivel c da atribuio anterior ?

Entenda o que acontece:

0000 0000 0000 0000 0000 0000 1000 0000 <--> +128

Como o compilador despreza os primeiros 24 bits (pois o tipo byte s comporta 8 bits) ficamos
com:

1000 0000

Se voc um cara esperto sabe que o bits da extrema esquerda dever ser usado para
armazenar o sinal (nesse caso negativo), como temos um nmero negativo agora desejamos
saber qual ! Existe uma regra que voc dever se familiarizar que usada para decobrir o
valor de um nmero negativo em bits:

Primeiro inverta todos os bits do nmero, assim temos:

0111 1111

Transforme esse nmero em decimal e acrescente 1

127 + 1 = 128

Aplique o bit do sinal e ter o valor: -128 !

Exercite isso com o nmero 140, 147 !

Voc dever obter: -116, -109

3.2 - Atribuio de Tipos Primitivos


Atribuies elementares no precisam ser discutidas, pois voc j deve est familiarizado, agora
um regrinha deve ser lembrada para sempre: toda atribuio que resultada de uma operao
(seja ela qual for: soma, diviso, deslocamento de bits....) envolvendo tipos inteiros (byte,
short, int, long) SEMPRE RESULTAR EM UM TIPO INT !!!

Portanto:

byte x = 1; // ok
byte y = 2 + 3; // ok
byte z = x + y; // deveria aceitar pois 6 cabe perfeitamente em um tipo byte, porm
necessrio uma convero explcita
byte z = (byte)x + y; // agora sim

3.3 - Deslocamento de Bits

Deslocar bits em nmero e alterar sua sequencia de armazenamento e s poder ser feito em
TIPOS INTEIROS !!

>> deslocamento de bits direita com sinal
<< deslocamento de bits esquerda com sinal
>>> deslocamento de bits direita sem sinal

Deslocamento a direita com sinal ( >> )

int x = 16;
x = x >> 2;

A varivel x estar armazenando ao final da linha de cdigo anterior o valor 4 ! O que o cdigo
anterior faz simplesmente descolar dois bits para a direita, assim temos:

x antes do deslocamento

0000 0000 0000 0000 0000 0000 0001 0000 (base 2)
16 (base 10)

x depois do deslocamento

0000 0000 0000 0000 0000 0000 0000 0100 (base 2)
4 (base 10)

O sinal sempre ser mantido com esse operador. Um regra bem simples que quando se
desloca direita o mesmo que aplicar a seguinte regra matemtica:

Para o caso anterior:
Frmula: 16 dividido por 2 elevado a x (onde x a quantidade de bits a deslocar)

Deslocamento a esquerda com sinal ( << )

int x = 16;
x = x << 2;

x antes do deslocamento

0000 0000 0000 0000 0000 0000 0001 0000 (base 2)
16 (base 10)

x depois do deslocamento

0000 0000 0000 0000 0000 0000 0100 0000 (base 2)
64 (base 10)

Outra regrinha que voc j deve ter deduzido :
Frmula: 16 multiplicado por 2 elevado a x (onde x a quantidade de bits a deslocar)

Observe o comportamento em caso de nmero negativos:

int x = -200;
x <<= 3;

O resultado de x ser: -1600

Note que o sinal mantido, observe o deslocamento dos bits:

1000 0000 0000 0000 0000 0000 1100 1000 equivale a -200

Aps o deslocamento:

1000 0000 0000 0000 0000 0110 0100 0000 equivale a -1600


Deslocamento a direita sem sinal ( >>> )

Nesse caso o bit do sinal no mantido, sendo preenchido com zero no bit da extrema
esquerda, portanto exceto em um caso particular que logo logo explicaremos, todo numero
deslocado com esse sinal (mesmo que seja um nmero negativo) fica positivo.

int x = 200;
x >>>= 2;

O valor de x ser 50 aps o deslocamento, veja porque:

0000 0000 0000 0000 0000 0000 1100 1000 equivale a 200

Aps o deslocamento:

0000 0000 0000 0000 0000 0000 0011 0010 equivale a 50

Agora vamos examinar um nmero negativo:

int x = -200;
x >>>= 2;

O valor de x ser aps o deslocamento, veja porque:

1000 0000 0000 0000 0000 0000 1100 1000 equivale a -200

Aps o deslocamento:

0010 0000 0000 0000 0000 0000 0011 0010 equivale a 1073741774

Existe uma particularidade que voc deve estar atento no caso de quando for tentado a
deslocar uma quantidade superior a capacidade do tamanho. Por exemplo, o que aconteceria se
voc tentar deslocar 35 bits em uma variavel do tipo int que comporta 32 ? Ou at mesmo 9
em uma varivel byte ? Se isso acontecer o compilador far uma clculo nuclear para descobrir
como deslocar:

int x = 90 >> 35;

Veja que no exemplo anterior, h um tentativa de deslocar 35 bits em um tipo int ! O
compilador far uma diviso entre a 35 quantidade de bits a deslocar e 32 que a capacitade
do tipo em questo e o resto dessa diviso ser a quantidade deslocada, nesse caso: 3 !!

byte y = (byte) 8 >> 12;

12 % 8 = 4 (quatro bits a deslocar)

Isso nos levanta um caso particular. E se for um mltiplo de 8 (no caso do tipo byte), por
exemplo, tente deslocar 16 ou 32 em um tipo byte, quantos bits sero deslocados ?
Exatamente nenhum pois o resto da diviso ser 0 (nenhum bit) ser deslocado. Portanto nem
sempre o deslocamento de bits com o operador ( >>> ) ser positivo, ou seja, tente deslocar
32 bits ou 64 bits em um tipo int que armazena o valor -300 e ter o mesmo valor -300 !!
Talvz voc no esteje lembrado, mas um nmero se diz mltiplo de outro se o resto entre sua
diviso for 0, veja o exemplo:

64 multiplo de 32 pois, 64 / 32 = 2 e resta 0
32 mltiplo de 32 pois, 32 / 32 = 1 e resta 0 (evidentemente)

No se irrite, foi s pra relembrar!!!

Portanto nem sempre o deslocamento com o operador ( >>> ) resulta em um nmero positivo
!!!

3.3 - Atribuio de Objetos

1) Dado as classes:

1. class Carro {
2. public double preco = 0;
3. }
4.
5. class Audi extends Carro { }
6.
7. 1. public class Teste {
8. 2. public static void main(String[] args) {
9. 3. Carro a = new Carro();
10. 4. Audi b = new Audi();
11. 5. Carro c = new Audi();
12. 6. Audi d = new Carro();
13. 7. }
14. 8. }


Qual das linhas anteriores esto incorretas e no permitiriam que o programa fosse compilado ?

a) 1, 3
b) 2, 3
c) 5
d) 6
e) o cdigo ser compilado

Resposta no final do captulo !!!

No se esquea da regra: X membro de Y ??

3.4 - Passagem de Parmetro em Java por Valor

Muito discusso existe quando o assunto a forma como a Java passa um varivel (primitiva ou
referncia) para um mtodo, mas acalme-se estamos aqui para descomplicar sua vida e lhe dar
um nova oportunidade!!
Quando uma varivel passada para um mtodo, SEMPRE SEMPRE E SEMPRE ser passado um
cpia dos seus bits!!

3.4.1 - Varivel Primitiva

1. public class Teste {
2. public static void main(String[] args) {
3. byte x = 10;
4. System.out.println("X antes: "+x);
5. altera(x);
6. System.out.println("X depois: "+x);
7. }
8. public static void altera(byte a) {
9. a = 2;
10. }
11. }


No caso anterior o que passado para o mtodo altera : 00001010 que nada mais que o
valor decimal 10, porm observe que no escopo do mtodo altera o valor recebido alterado e
quando o fluxo retorna ao mtodo main o valor da varivel x est intacta. Isso fcil de
entender, voc deve pensar errneamente que se o mtodo alterar modificasse o valor de x,
ento x teria sido passado como referncia ! Essa forma no correta de se pensar, pense
simplesmente que o mtodo altera recebeu um cpia dos bits da variavel x que era: 00001010.

Portanto o resultado do cdigo acima :

X antes: 10
X depois: 10

3.4.2 - Varivel Referncia

Agora o bicho pega!
Uma varivel de referncia nada mais que um repositrio de bits que representam um forma
de se acessar um objeto na memria. A varivel uma coisa o objeto que est na memria
outra, tente colocar isso na sua cabea!

1. public class Teste {
2. public static void main(String[] args) {
3. Carro c = new Carro();
4. c.preco = 13990.00;
5. System.out.println("preo antes: "+c.preco);
6. anula(c);
7. System.out.println("preo depois: "+c.preco);
8. }
9. public static void anula(Carro p) {
10. p = null;
11. }
12. }


Resultado:
preo antes: 13990.0
preo depois: 13990.0

No trecho de cdigo anterior acontece um fenmeno muito interessante e que nos d a idia de
como funciona toda essa parafernalha:

Premissas:
- c um varivel de referncia a um objeto do tipo Carro
- o mtodo anula, recebe uma varivel p do tipo Carro
- o mtodo anula, diz para a varivel p no referenciar nada (null)
- se a varivel c fosse passada como referncia, quando o fluxo retornasse ao mtodo main, c
estaria referenciando null
- se houver uma alterao do objeto que a varivel p est referenciando, essa alterao
tambm ser visvel varivel c (quando o fluxo retornar claro) veja o trecho a seguir:

1. public class Teste {
2. public static void main(String[] args) {
3. Carro c = new Carro();
4. c.preco = 13990.00;
5. System.out.println("preo antes: "+c.preco);
6. aumento(c);
7. System.out.println("preo depois: "+c.preco);
8. }
9. public static void aumento(Carro p) {
10. p.preco *= 1.05;
11. }
12. }


Resultado:
preo antes: 13990.0
preo depois: 14689.5

Talvz voc esteja se perguntando porque ento que o valor foi alterado se em Java um
varivel passada como valor ???? ERRADO, o que passado como valor so os bits que
referenciam o objeto, portanto p no mtodo aumento referencia exatamente o mesmo objeto
que c referencia no mtodo main, ou voc acha que a Java sai criando objetos na memria
assim sem mais nem menos ?

3.5 Operadores Bit a Bit

Existem trs operadores bit a bit:

& e

| ou inclusivo

^ u exclusivo

3.5.1 - Aplicando o operador &

O operador & compara dois bits e ser um se ambos o forem ! Calma que voce ver um
exemplo :

int x = 10 & 9;

Conventendo para bits os nmeros 10 e nove temos:

1010
1001
------
1000

O Resultado em decimal 8 !

3.5.2 - Aplicando o operador | ou inclusivo

int x = 10 | 9;

1010
1001
------
1011

Resultado: 11

3.5.3 - Aplicando o operador ^ ou exclusivo

int x = 10 ^ 9;

1010
1001
------
0011

Resultado: 3

3.6 - Operador Bit Complementar

Esse operador unrio, ou seja, envolve somente uma varivel e deve ser usada quando se
deseja inverter todos os bits de um nmero use o operador ( ~ )

int x = 8; // 1000
x = ~x; // Passa a valer 0111


3.7 - Operador Condicional

O operador condicional um operador ternrio, ou seja, trs operandos (bvio) e deve ser
usado quando se necessita realizar uma condio em uma nica linha. Veja o cdigo abaixo:

int tamanho = 19;
String texto = (tamanho>=10)?"Maior ou igual a 10":"Menor que 10";
System.out.println(texto);

No precisa nem perguntar o que vai sair na tela que todos j sabem !!!
Mas para os que ainda ficaram em dvida, l vai: o primeiro operando a condio, ou seja, se
ela for verdadeira (true) atribui o valor da segunda variavel texto em sendo falsa (false)
atribui o valor da terceira! Mais um exemplo:

1. class Teste {
2. public static void main(String[] args) {
3. int x = 10 ^ 8;
4. int y = ~x;
5. System.out.println(( x > y )?"x maior que y":"x menor que y");
6. }
7. }


No tente fazer algo do tipo:

( x > y )?System.out.println("x maior que y"): System.out.println("x menor que y");

Um operador condicional s pode ser usado para atribuir valores, ou seja, para ser usado
quando se necessite fazer uma atribuio condicional....

Mas algo assim perfeitamente possvel:

2) Dado o cdigo a seguir, o que acontecer ?

1. public class Teste {
2. public static void main(String[] args) {
3. int x = 10 ^ 8;
4. int y = ~x;
5. if ( ((x>y)?x:y) > 10 ) {
6. System.out.println("x maior que b e maior que 10");
7. } else {
8. System.out.println("x maior que b mas no maior que 10");
9. }
10. }
11. }


a) imprimir " x maior que b e maior que 10"
b) imprimir "x maior que b mas no maior que 10"
c) No imprimir nenhum resultado
d) Erro de compilao
e) Uma exceo ser lanada

Resposta no final do captulo !!!

3.8 - Operador instanceof

Operador binrio (dois operandos) que utilizado para saber se um objeto instncia de uma
classe.

String nome = "kuesley";
if (nome instanceof String) {
System.out.println("nome do tipo String");
} else {
System.out.println("nome no do tipo String");
}

Voc tambm poder compara subclasse veja o exemplo a seguir:

1. public class Veiculo { }
2.
3. public class Audi extends Veiculo { }
4.
5. public class Teste {
6. public static void main(String[] args) {
7. Audi a = new Audi();
8. Veiculo v = new Veiculo();
9. if (a instanceof Audi) System.out.println("a do tipo Audi");
10. if (v instanceof Veiculo) System.out.println("v do tipo Veiculo");
11. if (v instanceof Audi) System.out.println("v do tipo Audi");
12. if (a instanceof Veiculo) System.out.println("a do tipo Veculo");
13. }
14. }


Nesse cdigo ser exibido:

a do tipo Audi // a que instncia da classe Audi membro de Audi (isso bvio)
v do tipo Veiculo // v que instncia da classe Veiculo membro de Veiculo (bvio)
a do tipo Veiculo // a que uma instncia da classe Audi membro de veculo, pois a classe
Audi uma sub-classe de Veiculo!

Isso porque aplica-se sempre aquela regra: x MEMBRO y ???

Esse operador tambm pode ser aplicado as interfaces, ou seja, uma classe membro de uma
interface sempre que ela a implementa.

1. public interface Acao { }
2. public class Veiculo implements Acao { }
3. public class Audi extends Veiculo { }
4. public class Moto { }
5.
6. public class Teste {
7. public static void main(String[] args) {
8. Audi a = new Audi();
9. Veiculo v = new Veiculo();
10. Moto m = new Moto();
11. if (a instanceof Acao) System.out.println("a membro de Acao");
12. if (v instanceof Acao) System.out.println("v membro de Acao");
13. if (m instanceof Acao) System.out.println("m membro de Acao");
14. }
15. }


Resultado do cdigo anterior:

a membro de Acao
v membro de Acao

Lembra-se do primeiro captulo quando estudamos os arrays, e foi dito que um array um
objeto, agora comprovaremos essa afirmao para que no fique dvida em sua cabea.

1. public class Teste {
2. public static void main(String[] args) {
3. boolean c = (new int[] { 1,2,3 } instanceof Object);
4. System.out.println(c);
5. }
6. }


O resultado ser true.
Foi criado um array annimo (estudado no captulo 1) e verificado se um tipo Object e atribui-
se a varivel c o resultado true

Importante: Voc poder se deparar com questes que abordam se um objeto de um tipo de
classe que esteja fora da hierarquia, por exemplo:

1. class Veiculo { }
2. class Audi extends Veiculo { }
3.
4. public class Teste {
5. public static void main(String[] args) {
6. Audi a = new Audi();
7. Veiculo v = new Veiculo();
8. boolean b1 = (a instanceof Audi); // ok - b1 true
9. boolean b2 = (a instanceof Veiculo); // ok - b2 true
10. boolean b3 = (v instanceof Audi); // ok - b3 false
11. boolean b4 = (a instanceof String); // erro de compilao
12. }
13. }


3.9 - Sombreando variveis

Uma rea interessante da Java a forma como trata os sobreamentos de variveis. Talvez voc
esteja se perguntando "o que sobrear uma varivel ???", pense em uma classe com um
membro inteiro chamado tamanho, imagine ainda que voc crie um mtodo e internamente
voc tambm crie um varivel local chamada tamanho, o que acontecer ? A classe pirar ?
No a Java esperta e sabe tratar isso, veja como:

1. public class Teste {
2. static int tamanho = 0;
3. public static void main(String[] args) {
4. tamanho = 9;
5. System.out.println("Antes: "+tamanho);
6. crescer(2);
7. System.out.println("Depois: "+tamanho);
8. }
9. public static void crescer(int tamanho) {
10. tamanho = tamanho + 1;
11. }
12. }


O resultado do cdigo anterior ser:

Antes: 9
Depois: 9

A varivel tamanho dentro do escopo do mtodo que est sendo usada, no a mesma
declarada como membro da classe, agora se alterarmos um pouco o cdigo como segue
teremos um resultado diferente:

1. public class Teste {
2. int tamanho = 0;
3. public static void main(String[] args) {
4. Teste t = new Teste();
5. t.tamanho = 9;
6. System.out.println("Antes: "+t.tamanho);
7. t.crescer(2);
8. System.out.println("Depois: "+t.tamanho);
9. }
10. public void crescer(int tamanho) {
11. this.tamanho = tamanho + 1;
12. }
13. }


O resultado ser:

Antes: 9
Depois: 3

OBS: VOC NO PODE SIMPLESMENTE COLOCAR A PALAVRINHA this no mtodo crescer,
porque uma varivel static nunca poder ser referenciado por um contexto no-esttico, e a
palavra this quer dizer que de um objeto !!!

O mesmo comportamento tem os objetos, mas preste bastante ateno pois estive
conversando com o pessoal da Sun e eles me falaram que para a sua prova eles vo caprichar
em questes que tratar esse assunto.

3.10 - Operadores matemticos

No precisa falar muito sobre esse operadores, pois sei que voc bom em matemtica e
apesar de ter errados algumas respostas quando a professora da 4 srie lhe perguntava.
Uma observao que importante ser ressaltada que toda operao envolvendo nmeros
inteiros resultaro em um tipo int, mesmo sendo byte * short, ou byte / int. Como voc sabe
no possvel realizar diviso por zero para nmeros inteiros, mas em nmero de pontos
flutuantes isso possvel podendo retornar um 0 positivo ou um 0 negativo.

Os operadores so:

Unrios: -- ++
Binrios: + - / * %

int x = 10 + 10;
int y = 10 / 0; // Uma exceo ser lanada ! java.lang.ArithmeticException

3.10.1 - Diviso por zero

Veja o cdigo a seguir:

1. public class Teste {
2. public static void main(String[] args) {
3. double sal = 140 / 0;
4. System.out.println("Salario: "+sal);
5. }
6. }


O resultado ser uma exceo java.lang.ArithmeticException
Pois observe que 140 um inteiro e no um double, por isso a exceo. Agora observe o
cdigo a seguir:

1. public class Teste {
2. public static void main(String[] args) {
3. double sal = -140.0 / 0;
4. System.out.println("Salario: "+sal);
5. }
6. }


Resultado: Salario: -infinity (isso mesmo infinito negativo)

Olhe o comportamento estranho da Java quando os dois operadores forem zero

1. public class Teste {
2. public static void main(String[] args) {
3. double sal = -0.0 / 0;
4. System.out.println("Salario: "+sal);
5. }
6. }


Resultado: Salario: NaN (atenha-se a saber o que resulta e no o porqu)


3.10.2 - Incremento e Decremento

Os operados unrios incremento e decremento so bastante utilizados e devem ser
aprendidos para a obteno da to sonhada certificao, veja como funciona:

Operador pr-fixado

int x = 10;
System.out.println("x "+(++x));

No tente fazer em casa esse trecho sem os parenteses " System.out.println("x
"+++x);" o compilador pira !!!
o equivalente a dizer: "Por favor, incremente 1 a varivel x depois exiba o valor da
varivel, continue o seu trabalho"

O resultado ser: x 11

Operador ps-fixado

int x = 9;
System.out.println("x vale: "+x--);
System.out.println("o valor final de x "+x);

O resultado ser:

x vale: 9
o valor final de x 8

Bom acho que chagamos ao final de mais um captulo, e espero ter colaborado para
o seu crescimento da linguagem Java !!!


Respostas dos exerccios propostos:

1) d

2) b


Cap. 4 - Controle de Fluxo
Captulo 4 - Controle de fluxo, excees e assertivas

4.1 - Introduo

O controle do fluxo um elemento essencial em qualquer linguagem de programao. Mesmo
com os paradigmas da programao orientada a objetos, controlar o fluxo de um algoritmo
uma necessidade imprescindvel. Quem j desenvolveu software em linguagens estruturadas
como clipper, cobol, c entre outras, sabe que se esse recurso no existisse, um algoritmo no
poderia ser condicionado e testado para prever por exemplo, eventos inerentes a falhas em um
recurso ou dispositivo do computador, ou at mesmo se um usurio entrou com um valor
correto em um campo de entrada de dados.

if

Esse comando um dos mais conhecido dentre as linguagens de programao, sua funo
testar se uma condio verdadeira, em sendo, executa o bloco seguinte sua escrita, veja o
exemplo:

if ( 2 > 1) {
....
}

Fcil isso ? Pode crer que no exame no cair questes que abordem essa complexidade, ou
melhor essa simplicidade. Veja agora o trecho a seguir :

1. 1. byte x = 10;
2. 2. if (x<0) {
3. 3. if (x == 11) {
4. 4. System.out.println("x igual 11");
5. 5. }
6. 6. else if (x==x--) {
7. 7. System.out.println("x menor que 11");
8. 8. }}
9. 9. else
10. 10. System.out.println("x no menor que 0");


O que resultar do seguinte cdigo ? Complicou um pouquinho ??

Se passasemos agora para o mundo compilatrio (nem sei se isso existe), mas encarne o
compilador agora.
A primeira coisa que ele vai checar se na linha 2 o x menor que 0 ? - como uma condio
falsa, iremos para a linha 9 pois esse
else referente ao if (x<0) (pode contar as chaves) e exibir a mensagem "x no menor que
0" .
Veja agora o trecho a seguir, apesar de muito parecido, existe um diferena do cdigo anterior:

1. 1. byte x = 10;
2. 2. if (x<0)
3. 3. if (x == 11) {
4. 4. System.out.println("x igual 11");
5. 5. }
6. 6. else if (x==x--) {
7. 7. System.out.println("x menor que 11");
8. 8. }
9. 9. else
10. 10. System.out.println("x no menor que 0");


O que resultar esse cdigo ? Se voc respondeu NADA ! Est correto ! Vamos entender - como
(x<0) uma condio falsa e no existe else para esse if nenhum resultado ser gerado -
nesse caso o else da linha 9 ficou pertencente ao conjunto de condies iniciados pelo if da
linha 3, tanto que se as condies das linhas 3 e 6 no forem verdadeiras o else ser
executado como mostra o cdigo a seguir:

Com sua licena, uma observao, o if da linha 2 tambm foi alterado seno, no entrar na
demais condies:

1. 1. byte x = 10;
2. 2. if (x>0)
3. 3. if (x == 11) {
4. 4. System.out.println("x igual 11");
5. 5. }
6. 6. else if (x==--x) {
7. 7. System.out.println("x menor que 11");
8. 8. }
9. 9. else
10. 10. System.out.println("x no menor que 0");


Acho que isso j deve te alertar para as pegadinhas que os crpulas tentaro te colocar para
saber o seu conhecimento quanto a sequencia do fluxo que um algoritmo deve obedecer,
observe tambem que a identao ou rcuo no foi colocada para confundir mais ainda sua
cabea e pode ter certeza que eles tem muito mais para lhe apresentar, por isso ESTUDE !

if com atribuio

Quando tem as chaves tudo fica mais fcil !

1) O que o cdigo acima resultar ?

1. boolean b = false;
2. if (b = true) { System.out.println("b verdadeiro") }
3. else { System.out.println("b false") }


a) Erro de compilao !
b) Uma exceo ser lanada
c) b false
d) b verdadeiro
e) nenhum resultado

[color=green:b01166bcbb]Resposta no final do captulo !!![/color:b01166bcbb]

Loko isso no ! O que acontece que b sendo uma varivel boolean o compilador entende que
(b = true) uma atribuio varivel b e depois faz a comparao, mas no tente fazer isso
com qualquer outro tipo de varivel, veja a seguir:

byte x = 10;
if (x = 7) { ... } // erro de compilao
else { ... }

Agora, assim permitido:

byte x = 10;
if (x == 7) { ... } // ok
else { ... }

switch

Esse comando tambm muito utilizado para checagem de valores em uma varivel,mas
existem algumas particularidades que devem ser observadas, veja sua sintaxe:

O switch s poder ser aplicado a variveis:int short byte char
Portanto qualquer tentativa de utilizar em outras variaveis como: boolean, long, double, float ou
um objeto resultar em erro de compilao !!!

1. byte x = 3;
2. switch (x) {
3. case 1 :
4. System.out.println("x vale 1");
5. break;
6. case 2:
7. System.out.println("x vale 2");
8. break;
9. default:
10. System.out.println("x maior que 2");
11. break;
12. }


O uso das chaves entres os cases opcional pois no faz nenhuma diferena, veja o cdigo:

1. byte x = 3;
2. switch (x) {
3. case 1 : {
4. System.out.println("x vale 1");
5. break;
6. }
7. case 2:
8. System.out.println("x vale 2");
9. break;
10. default:
11. System.out.println("x maior que 2");
12. break;
13. }


O uso do break necessrio, se for omitido o fluxo seguir normalmente para o outro case,
como voc pode ver no trecho a seguir:

1. byte x = 2;
2. switch (x) {
3. case 1 :
4. System.out.println("x vale 1");
5. System.out.println("x vale 1");
6. break;
7. case 2:
8. System.out.println("x vale 2");
9. default:
10. System.out.println("x maior que 2");
11. System.out.println("x maior que 2");
12. break;
13. }


O cdigo a seguir resultar :

x vale 2
x maior que 2
x maior que 2

Pos entrar no segundo case e por no existir o break, tambm seguir para o default !

Provavelmente voc se deparar com questes que abordam o uso do switch de forma invlida,
como por exemplo:


No colocar a varivel entre parenteses

1. int x = 10;
2. switch x { // Erro de compilao: '(' expected
3. case 1:
4. ...
5. break;
6. case 2:
7. ...
8. break;
9. }


Uso de duas opes case iguais

1. int x = 10;
2. switch (x) {
3. case 1: { ... }
4. case 2: { ... }
5. case 1: { ... } // Erro de compilao: duplicate case label
6. }


Uso de varivel invlida

1. long x = 100;
2. switch (x) { // Erro de compilao: possible loss of precision
3. case 1: { ... }
4. case 2: { ... }
5. }


Uso de objeto

1. String x = new String("teste");
2. switch (x) { // Erro de compilao: incompatible types
3. case "aaa": { .... }
4. }


Uso de varivel no final

1. final int op1 = 1;
2. final int op2 = 2;
3. int op3 = 3;
4. int opcao = 2;
5.
6. switch (opcao) {
7. case op1: { ... } // ok, op1 final
8. case op2: { ... } // ok, op2 final
9. case op3: { ... } // Erro de compilao: constant expression required
10. default: { ... }
11. }


Bom acho que o switch isso, mas vamos ratificar nossa linha de pensamento para ver se voc
entendeu tudo direitinho. Observe o trecho de cdigo a seguir:

1. int x = 1;
2. switch (x) {
3. case 1: System.out.println("1");
4. default: System.out.println("default");
5. case 2: System.out.println("2");
6. case 3: System.out.println("3");
7. case 4: System.out.println("4");
8. }


O que resultar ?

1
default
2
3
4

Lembre-se sempre, uma vez que um case for verdadeiro, todos subsequentes sero se
nenhuma palavra chave break for encontrada.
Agora observe esse outro cdigo:

1. int x = 3;
2. switch (x) {
3. case 1: System.out.println("1");
4. default: System.out.println("default");
5. case 2: System.out.println("2");
6. case 3: System.out.println("3");
7. case 4: System.out.println("4");
8. }

O que resultar ?

3
4

Observe que como a condio default est antes da primeira condio verdadeira (case 3), ela
no executada.

Extremamente importante saber

2) O que esse cdigo resultar ?

1. public static void main(String[] args) {
2. final int x = 2;
3. for (int i = 0; i < 2; i++) {
4. switch (i) {
5. case x-1: System.out.print("1 ");
6. default: System.out.print("def ");
7. case x: System.out.print("2 "); break;
8. case x+1: System.out.print("3 ");
9. }
10. }
11. }


a) No ser compilado
b) def 2 def 2 1
c) def 2 1 def 2
d) def 2 1 def 1
e) def 1 2 def 1

[color=green:b01166bcbb]Resposta no final do captulo !!![/color:b01166bcbb]

Agora observe o mesmo cdigo alterando simplesmente a localizao da palavra default

1. public static void main(String[] args) {
2. final int x = 2;
3. for (int i = 0; i < 4; i++) {
4. switch (i) {
5. case x-1: System.out.print("1 ");
6. case x: System.out.print("2 "); break;
7. case x+1: System.out.print("3 ");
8. default: System.out.print("def ");
9. }
10. }
11. }


O resultado ser: def 1 2 2 3 def

Entendendo o primeiro cdigo

O mais interessante e que deve ser ressaltado como o switch faz suas comparaes, vamos
tentar entender. Em nosso primeiro cdigo sabemos que ocorrem duas iteraes - isso todos
concordam. O switch vai ao primeiro case - (case x-1), ou seja, se 0 (valor de i) igual a 1, no
o caso, vai ao prximo que em nosso caso um default, como um default o swicth
pergunta: "Existe algum case abaixo que atenda a minha necessidade (i=0) ???? - e uma voz
do alm "No senhor, nenhum caso que atenda essa condio", bom nesse caso o switch
executa o default exibindo a palavra def na tela e como no existe break, executa tambm o
case x imprimindo o valor 2 onde encontra o break e para a execuo do switch. Na segunda
iterao o i vale 1 portanto na primera condio case x -1 atendida imprimindo 1 na tela, em
seguida def consecutivamente o nmero 2, onde a palavra break encontrada encerrando o
switch.

Falando um pouco em loops

while

Quando voc desejar executar um bloco uma quantidade desconhecida de vezes, esse
comando normalmente utilizado, veja sua sintaxe:

1. int x = 10;
2. while (x==10) {
3. System.out.println("entrou");
4. x++;
5. }


Resultado desse cdigo:

entrou

Esse cdigo ser executado somente uma vez, visto que na segunda iterao o valor de x
estar valendo 11, o que resultar em falso na condio do while, isso no d uma dica de que
uma iterao while pode no acontecer se a condio testada primeiramente for falsa, como
voc poder ver o cdigo a seguir:

1. int x = 11;
2. while (x==10) {
3. System.out.println("entrou");
4. x++;
5. }


Nenhum resultado ser exibido.

do-while

Outro comando de iterao que pode ser usado do-while, veja sua sintaxe:

1. int x = 0;
2. do {
3. System.out.println(""+x);
4. x++;
5. } while (x < 1);


Resultado:

0

Esse comando SEMPRE ser executado pelo menor uma vez, pois a condio verificada aps
a iterao.

for

O comando for utilizado normalmente quando voc sabe quantas vezes voc precisa fazer as
iteraes. Apesar de que ele tambm pode ser usado exatamente como o while mas no uma
boa prtica de programao.

1. for ( int i = 0; i < 10; i++ ) {
2. System.out.print(""+i);
3. }


Resultado: 0123456789

O comando for composto por trs expresses:

a) declarao e inicializao
b) expresso condicional
c) expresso de iterao


a) declarao e inicializao

executado uma nica vez antes da primeira iterao, normalmente se usa para criar e
inicializar um varivel para controlar as iteraes - voc pode inicializar outras variveis nessa
parte como mostra o cdigo a seguir:

1. int s = 9;
2. for ( int i = 0, s = 10; i < 10; i++ ) {
3. System.out.println(""+(s+i));
4. }


Observe que a variavel s foi redefinida com o valor 10 no bloco de inicializao (separado por
vrgula). O escopo de uma varivel criada nessa parte somente dentro do escopo do comando
for no tente usar uma varivel como i em nosso exemplo anterior aps o trmino do comando
for que voc magoar o compilador.

1. for ( int i = 0; i < 10; i++ ) {
2. System.out.println(""+i);
3. }
4. System.out.println(" apos o for: "+i); // erro de compilao: cannot resolve
symbol


b) expresso condicional

S pode haver UMA expresso condicional (no tente separar condies por vrgula que voc
ter um erro do compilador), ser
testada antes de cada iterao.

1. for (int i = 0; i < 1; i++) {
2. System.out.println(""+i);
3. }


Nesse exemplo uma iterao ser executado pois i vale 0 e antes de executar a primeira
iterao a JVM testa se i < 1 ou seja se 0 menor que 1, como true, executa a iterao. J
na segunda iterao a "expresso de iterao" ser executada incrementando 1 a variavel i
portanto i valer 1, o que tornar a condio falsa, por isso esse cdigo resultar:

0

Voc poder ter uma condio composta como mostra o cdigo a seguir:

1. for (int i=0; i < 10 | (i%2) == 0; i++) {
2. System.out.println(""+i);
3. }


Mas lembre-se, quando essa condio for false o loop encerrado, e no pense que vai para a
prxima iterao, funciona como o while, mesmo que exista uma condio como o cdigo
anterior i < 10.

c) expresso de iterao

Essa expresso executada sempre aps a execuo de uma iterao, ou seja, quando um
bloco termina, a expresso de iterao executada. Por isso o cdigo a seguir executado pelo
menos uma vez:

1. for (int i = 0; i < 1; i++) {
2. System.out.println(""+i);
3. }


Porque se a expresso ( i++ ) fosse executada antes da execuo da primeira iterao,
nenhum resultado seria mostrado na tela.

break

Essa palavra chave dentro de uma iterao seja ela (for, while, do) faz com que o fluxo ser
reportado para a primeira linha aps o bloco de iterao como voc pode ver no cdigo a
seguir:

1. int x = 0;
2. for (int i = 0; i < 10; i++ ) {
3. x = i;
4. if ( i > 3 ) break;
5. }
6. System.out.println("ultimo valor de i: "+x);


Esse cdigo resultar:

ultimo valor de i: 4


continue

Interrompe a iterao atual indica para iniciar a prxima iterao. Para exemplificar vamos
imaginar um algoritmo onde se deseja lista todos os nmeros mpares menores que 10:

1. for (int i = 0; i < 10; i++ ) {
2. if ((i%2)==0) continue;
3. System.out.print(""+i);
4. }


O cdigo acima resultar:

13579

No vamos discutir se esse o melhor algoritmo para esse problema mas uma soluo! Saiba
que todas as linhas aps o continue (que no o nosso caso) no seria executada.

Funciona exatamente igual para os comandos de iterao: ( do e while )

Outras formas de se utilizar o comando for

Voc no obrigado a definir nenhuma das trs expresses, podendo usar o comando for da
seguinte forma:

1. for ( ; ; ) {
2. ...
3. }


Esse cdigo comporta-se exatamente igual ao:

1. while (true) {
2. ....
3. }


Saiba que palavra break dever estar contida dentro de qualquer um desses blocos, caso
contrrio isso causar um loop infinito, talvez no seja infinido porque seu computador ser
desligado por orientao da ANAEL (lembra-se do APAGO) !

3) Quantas iteraes sero executadas com esse cdigo ?

1. for (int i=0; i < 10; ++i) {
2. System.out.println(""+i);
3. continue;
4. }


a) erro de compilao
b) uma exceo ser lanada
c) 10
d) 9
e) loop infinito

[color=green:b01166bcbb]Resposta no final do captulo !!![/color:b01166bcbb]

Explicao: A palavra-chave continue nesse cdigo no faz nada de mais alm do que o prprio
comando j faria, visto que ele no est em nenhuma condio e tambm no existe nenhum
cdigo abaixo dele, portanto, natural que mesmo sem ter o continue o comando j passaria
para a prxima iterao.

loops rotulados

Apesar de ser um assunto crtico, os loops rotulados devem ser entendidos para a obteno da
sua certificao, mas no posso deixar de expressar minha opinio pessoa, um recurso (se
assim me permitem dizer) feio como prtica de programao, lembram-se daquelas linguagens
que usavam goto (como basic, etc.) ou arquivos de lote (.bat), pois ento, no use essa prtica
- espero que nenhum programador basic ou de arquivos de lote do DOS leia isso. Veja como
criar um loop rotulado:

1. int x=0;
2. for (int i=0; i < 4; i++) {
3. :foo
4. for (int j=0; j <= 4; j++ ) {
5. if (i == j) {
6. System.out.println(i+"x"+j);
7. break foo;
8. }
9. }
10. }


Esse cdigo resultar:

0x0
1x1
2x2
3x3

No precisa falar muito sobre o que aconteceu com esse cdigo, pois essa seria uma ao
normal mesmo se no existisse o rtulo no loop interno ( for j ), mas se voc precisar cancelar
as iteraes do for exterior ( for i ) ???

Trabalhando com excees

Esse recurso muito importante para a garantia de um cdigo seguro, ou seja, trabalhar com
excees em uma linguagem uma forma de tentar honrar seu programa contra erros que
inconvenientemente aparecem se serem chamados.

1. try {
2. // primeira linha vigiada
3. }
4. catch (Exception e) {
5. // primeira linha que ser executada caso haja um exceo do tipo Exception
6. }
7. finally {
8. // bloco que ser executado, havendo ou no uma exceo (sempre!)
9. }


try

O bloco try inicia uma regio vigiada, ou seja, qualquer exceo que ocorrer nesse trecho
modificar o fluxo do programa para um bloco catch (se houver) e/ou finally (se houver). Um
bloco try deve obrigatoriamente ter ou um catch ou um finally, pode ter os dois, mas nunca um
bloco try sozinho.

1. Vlido
2.
3. try {
4. }
5. catch (MyException e) {
6. }
7.
8. Vlido
9. try {
10. }
11. finally {
12. }
13.
14. Invlido
15.
16. try {
17. }
18.
19. Erro: 'try' without 'catch' or 'finally'


catch

Bloco que define uma exceo e sua ao caso venha ocorrer. Voc poder ter mais de um
catch em um bloco try.

1. try {
2. // algoritmo
3. }
4. catch (MyException e) {
5. // soluo caso ocorra
6. }


Nesse caso MyException a exceo que pode acontecer, no que seja um desejo ardente do
corao do programador, mas uma cautela !

finally

Bloco que ser executado aps o try ou catch, ou seja, se um bloco try tiver um subbloco
finally, este sempre ser executado, independente se ocorrerem excees ou no. Talvez voc
tenha se perguntado, "porque no coloque o cdigo do bloco finally no try ou no catch ?" como
mostra o pseudo-cdigo a seguir:

Vejamos um pseudo-codigo:

1. try {
2. 1. Aloca memria para abertura de um arquivo
3. 2. Abre um arquivo
4. 3. Imprime arquivo na porta da impressora
5. 4. Fecha arquivo
6. 5. Desaloca memria
7. }
8. catch (ArquivoNaoExisteException e1) {
9. 1. Desaloca Memria
10. 2. Mostra mensagem que arquivo no foi encontrado
11. }
12. catch (PortadaImpressoraNaoResponde e2) {
13. 1. Desaloca Memria
14. 2. Fecha Arquivo
15. }


Observe que o cdigo de desalocar memria est redundante (t!! sei que poderia alocar
somente se abrisse o arquivo, mas no vamos complicar)

Veja o pseudo-cdigo:

1. try {
2. 1. Aloca memria para abertura de um arquivo
3. 2. Abre o arquivo
4. 3. Imprime arquivo na porta da impressora
5. 4. Fecha arquivo
6. 5. Desaloca memria
7. }
8. catch (ArquivoNaoExisteException e1) {
9. 1. Mostra mensagem que arquivo no foi encontrado
10.
11. }
12. catch (PortadaImpressoraNaoResponde e2) {
13. 2. Fecha Arquivo
14. }
15. finally {
16. 1. Desaloca memria
17. }



Hierarquia de classes de exceo:



Pode parecer estranho, mas existe uma diferena singular entre Erro e Exceo. Por mais que
voc tenha achado esquisito essa colocao, saiba que um erro algo que no tem "remdio" e
exceo um evento que deveria acontecer normalmente mas por algum motivo de fora
maior no conseguiu se completar.

Erro
Falta de memria do computador


Exceo
Tentar consultar um coluna em um banco de dados que no exista
Tentar abrir um arquivo que foi apagado
Tentar trocar informaes com um outro computador que por algum motivo for desligado

Isso nos leva a seguinte concluso:


Todas as subclasses de Exception (com exceo as subclasses RuntimeException)
so excees e devem ser tratadas !!!
Todos os erros provenientes da classe Error ou RuntinmeException so erros e no
precisam serem tratados !!!


Voc deve estar se perguntando, "p! mas tudo no so erros ?" ! So, mas somentes as
excees precisam ser tratadas ! Vamos ver alguns cdigo a seguir que o ajudar a entender
esses conceitos.

1. 1. public class Erros {
2. 2. public static void main(String[] args) {
3. 3. metodoDoMal();
4. 4. }
5. 5. public static void metodoDoMal() {
6. 6. throw new IOException("eu fiz um erro");
7. 7. }
8. 8. }


Esse cdigo lana uma exceo dentro do metodoDoMal(). Normalmente voc no precisar
lanar excees pois Murphy se encarregar de fazer isso pra voc, porm imagine uma
situao em que voc precise gerar um exceo. Apesar da sintaxe est correta na gerao da
exceo, esse cdigo no ser compilado. Quem est tratando a exceo IOException que foi
gerada no mtodo metodoDoMal() ?? Se uma exceo ocorrer ela deve ser tratada (se no for
Erro ou RuntimeException claro), e existem duas maneiras de se fazer isso:

1 - Usando um bloco try/catch

O cdigo poderia ser remediado da seguinte forma:

1. 1. public class Erros {
2. 2. public static void main(String[] args) {
3. 3. metodoDoMal();
4. 4. }
5. 5. public static void metodoDoMal() {
6. 6. try {
7. 7. throw new IOException("eu fiz um erro");
8. 8. }
9. 9. catch (IOException e) {
10. 10. // cdigo que solucionar o problema
11. 11. }
12. 12. }
13. 13. }


2 - Usando a propagao de exceo atravs de mtodos

1. 1. public class Erros {
2. 2. public static void main(String[] args) {
3. 3. metodoDoMal();
4. 4. }
5. 5. public static void metodoDoMal() throws IOException {
6. 6. throw new IOException("eu fiz um erro");
7. 7. }
8. 8. }


Esse cdigo tambm no ser compilado, pois o compilador esperto e sabe que uma exceo
pode ocorrer em metodoDoMal (pois foi declarado em throws IOException) e est sendo
propagado para o mtodo mais que no est tratando, pois nenhum bloco try existe no mtodo
chamado. Talvez isso tenha complicado um pouco mais olhe o cdigo a seguir:

1. import java.io.*;
2. import java.awt.print.*;
3.
4. public class Teste {
5. public static void main(String[] args) {
6. try {
7. metodoDoMal();
8. }
9. catch (IOException e) {
10. }
11. catch (PrinterException p) {
12. }
13. }
14. static void metodoDoMal() throws IOException, PrinterException {
15. metodoPiorAinda();
16. }
17.
18. static void metodoPiorAinda() throws PrinterException {
19. }
20. }


Isso o que chamamos de pilha de mtodo, mas acalme-se fcil. O mtodo main() chama o
mtodo metododoMal() que por sua vez chama o mtodoPiorAinda(), criando um pilha de
mtodos

Pilha:

MetodoPiorAinda() throws PrinterException

metodoDoMal() throws IOException, PrinterException

main(String[] args)

Observe que o mtodo MetodoPiorAinda() declara a exceo PrinterException, isso que dizer
que essa exceo poder ocorrer dentro desse mtodo. Como essa exceo no est sendo
tratada em nenhum bloco try/catch, ela dever propagada para o mtodo superior na pilha
"metodoDoMal()", Se nesse mtodo no houver um tratamento com try/catch ou propagao
atravs de throws na cabea do mtodo, haver um erro de compilao (pode testar, tire a
declarao PrinterException de metodoDoMal() que esse cdigo no ser compilado). Quando o
metodoDoMal() for encerrado, seguindo a ordem da pilha o fluxo ser retornando para o
mtodo main, se esse mtodo no tratar as excees declaradas em metodoDoMal(), o cdigo
tambm no ser compilado (tente tirar qualquer um dos blocos catchs que o cdigo ser
extinguido do planeta).

Voc ter que saber a diferente entre um exceo declarada e no-declarada. Lembre-se
sempre que os erros (subclasses de Error e RuntimeException) no precisam ser tratadas como
mostra o cdigo a seguir:

1. public class Teste {
2. public static void main(String[] args) {
3. metodoDoMal();
4. }
5. static void metodoDoMal() throws Error {
6. }
7. }


Observe que o mtodo metodoDoMal declara/propaga uma exceo (erro) e o mtodo
chamado (main) no trata e nem propaga.

Assertivas

O uso de assertivas um recurso adicionado somente na verso 1.4 que permite ao
programador testar a consistncia de seu cdigo. Voc dever sempre usar assertiva quando
quiser testar se uma varivel est em um dado momento com um valor apropriado, se no
gerar um AssertionError, isso em tempo de desenvolvimento, embora quando o programa for
distribudo e entregue ao cliente, nenhuma anormalidade ocorrer visto que as assertivas nunca
so ativadas por padro. Considere o pensamente de que as assertivas foram incrementadas
para auxiliar ao programador gerar cdigo mais robustos, mas nunca podero alterar o
comportamento do programa.

1. private int foo(int i) {
2. assert (i>0);
3. return i * i;
4. }


Observe que o cdigo anterior nada mais faz do que testar se o valor de i passado
como parmetro maior que 0 se for o programa no faz nada, agora se o valor de i
no for maior que 0, ento um AssertionError ser lanada - com isso o
programador poder saber que em algum lugar algum engraadinho est passando
um valor incorreto para o mtodo foo. Mas nenhuma consequencia isso teria se o
cdigo fosse entregue, visto que nenhum resultado seria afetado no cliente.
Existem duas maneiras de se usar assertivas:

muito simples

assert ( i < 0 );


simples

assert ( i > 0 ) : "Valor do i "+i;

A segunda forma, incrementa o valor aps os dois pontos na mensagem de erro de
AssertionError, com isso voc poder depurar seu cdigo com mais detalhes.
Voc precisar saber a diferena entre usar uma assertiva de forma vlida e de
forma apropriada ou correta, visto que, vlida est relacionada com o cdigo ser
compilado, mas nem sempre a maneira como deve ser.


Assertivas - uso incorreto/inapropriado

1) Nunca manipula um AssertionError

No use um catch e manipula um erro de assertiva

2) No use assertiva para validar argumentos em mtodos pblicos

Voc no pode garantir nada em mtodos pblico, portanto usar assertiva nesse
caso, no uma boa prtica

3) No use assertiva para validar argumento da linha de comando

Isso uma particularidade de um mtodo pblico, mas segue a mesma regra

4) No use assertivas que possam causar efeitos colaterais

Voc no pode garantia que as assertivas sempre sero executadas, portanto o seu
programa deve executar independentemente das assertivas, e nunca de forma
diferente simplesmente porque as assertivas foram ativadas.


Uso Apropriado/Correto

1) Use assertiva para validar argumentos em mtodos privados

Como a visibilidade privada, voc consegue detectar se algum (voc) t fazendo
caca.

2) Use assertiva sem condio em um bloco que pressuma que nunca seja
alcanado.

Se voc tem um bloco que nunca seria alcanado, voc pode usar uma assert false,
pois assim saberia se em algum momento esse bloco est sendo alcanado.

3) Lanar um AssertionError explicitamente

4) Se um bloco switch no tiver uma instruo default, adicionar uma assertiva
considerado uma boa prtica


Consideraes finais:

- Mesmo que um cdigo tenha sido compilado com o uso de assertivas, quando
executar, vc dever explicitamente forar a utilizao, pois por padro as assertivas
no so ativadas;

- Assertivas no so compiladas nem executadas por padro;

- possvel instruir a JVM desativar assertivas para uma classe e ativar para um
dado pacote em uma mesma linha de comando;

- flags:

java -ea java -enableassertion // habilita assertion
java -da java -disableassertion // desabilita assertion
java -ea:br.com.Atimo // habilita para o pacoto br.com.Atimo
java -ea -das // habilita assertion em mbito geral e desabilita nas classes do
systema
java -esa // habilita nas classes do sistema


Bom acho que chagamos ao final de mais um captulo !

Respostas dos exerccios propostos:

1) d

2) c

3) c




Cap. 5 - Orientao a Objetos


Captulo 5 - Orientao a Objetos, sobreposio e
substituio, construtores e tipos de retorno

5.1 - Escapsulamento, relacionamentos -UM e TEM-UM

Escapsular - tem a funo bsica de proteger uma classe de "coisas estranhas", ou seja, mant-
la de forma mais protegida contra o uso indevido de certos usurios. Vamos ver o seguinte
cdigo para entender isso:

1. public class Carro {
2. private float motor = 1.0f;
3.
4. public setMotor( int value ) {
5. this.motor = value;
6. }
7.
8. public float getMotor() {
9. return this.motor;
10. }
11. }


O cdigo acima mostra a forma mais trivial de se proteger os membros de uma classe, ou seja,
mantenha seus atributos com o modificador private (com isso o acesso se restringe a classe), e
crie mtodos sets e gets para modificar e acessar seus membros - os padres mundiais
dizem que voc deve nominar seus mtodos da forma acima setNomedoAtributo e
getNomedoAtributo.
Talvez voc deve esta se perguntando: "p, mas se eu pude setar diretamente a varivel
motor, porque eu no posso acess-la diretamente ???" Esse um racioco muito bom, mas se
no o teve no se preocupe, vamos entender. Imagine que a classe acima foi criada liberando o
acesso direto a seus membros, dois anos aps a sua criao, descobre-se que ningum pode
setar o valor de motor inferior a 1.0 (mesmo porque um carro com motor inferior a isso, nem
pode ser considerado um carro!), qual a soluo eminente ? Varrer todos os cdigo que utilizam
essa classe e verificar se existe erro, caso exista, conserta-se! Bom se o tempo de produo
no um diferencial em sua equipe de desenvolvimento, eu outras empresa ou lugares, as
pessoas no querem perder muito tempo, com essa mudanas, pois se a classe for criada da
forma acima, basta alterar o mtodo setMotor, fazer uma condio e consertar somente ali !
Viu como o encapsulamento uma idia interessante !

5.2 - O relacionamento -UM refere-se a herana

Quando se v uma questo que se indage se X -UM Y, isso quer dizer se X uma subclasse,
subtipo, estendeu de Y. Veja o cdigo:

public class Carro {}

public class Mazda extends Carro {}

Se voc se deparar com uma questo, Mazda -UM Carro, pode ter certeza que sim ! Agora do
inverso no ! Carro -UM Mazda !

5.3 - TEM-UM referencia outra classe

Quando se tem uma questo: X TEM-UM Y, quer dizer que X tem uma referencia a Y, atravs
de um atributo, vejamos um exemplo:

1. public class Motor { }
2. public class Pneu { }
3. public class Carro {
4. private Motor motor;
5. private Pneu[] pneu;
6. }
7. public class Mazda extends Carro { }


Asseres corretas:

Carro TEM-UM Motor
Carro TEM-UM Pneu
Mazda -UM Carro

5.4 - Substituio de mtodo (override)

5.4.1 - Substituindo um mtodo:

Substituir um mtodo como o prprio nome j diz, significa cancelar um mtodo de uma
superclasse em uma subclasse dando-o um outro sentido, ou tcnicamente, um outro cdigo -
portando infere-se que eu s posso substituir um mtodo se houver herana caso contrrio no
existe substituio de mtodo, vejamos o cdigo:

1. public class Empregado {
2. public double getSalario() { }
3. }
4.
5. public class Horista extends Empregado {
6. public double getSalario() {
7. // cdigo que retorna salrio em horas
8. }
9. }
10.
11. public class Mensalista extends Empregado {
12. public double getSalario() {
13. // cdigo que retorna salrio mensal
14. }
15. }


Observe que o mtodo getSalario nas subclasses tm comportamento distintos nas subclasses -
isso devido ao fato de ter sido substitudo nas subclasses. Observe ainda que o mtodo nas
subclasses se manteve idntico ao mtodo da superclasse no que se refere a assinatura do
mtodo (lista de argumentos) - se essa assinatura tivesse sido alterada, no seria substituio
(override) e assim sobreposio ou sobrecarga (overload) - muita ateno com isso, mas
estudaremos isso mais a frente.

1. public class Empregado {
2. public double getSalario() { }
3. public double getSalario() { }
4. }


Qualquer tentativa de redefinio de mtodo na mesma classe, voc passar por uma vergonha
incrvel pelo compilador, no tente! O que define um mtodo sua assinatura (lista de
argumento) - portanto mesmo que tente engan-lo como o cdigo a seguir, assuma as
conseqencias:

1. public class Empregado {
2. public double getSalario() { }
3. public float getSalario() { }
4. }


[color=red:3977e586f4]Erro de compilao: getSalary() is already defined in
Empregado[/color:3977e586f4]

Lembre-se sempre: O mtodo para ser substitudo deve ter a mesma assinatura (lista de
argumentos) na subclasse, caso contrrio, no substituio e sim sobreposio.

5.4.2 - Modificando o acesso de um mtodo substitudo

Voc poder alterar a visibilidade de um mtodo substitudo, mas nunca para uma visibilidade
inferior a definida na superclasse, ou seja, se voc tiver um mtodo na superclasse com o
modificador protected voc no poder substitu-lo por um mtodo com modificador private
(mais restrintivo) mas para um mtodo pblico por exemplo, sem nenhum problema.

A ordem :

private
padro
protected
public

Como podem ser substitudos:

private private, padro, protected e public
padro padro, protected e public
protected protected, public
public public

Vejamos o cdigo:

1. abstract class Empregado {
2. protected abstract double getSalario();
3. }
4.
5. abstract class Horista extends Empregado {
6. public abstract double getSalario();
7. }


Veja que a classe Horista tem um mtodo mais abrangente que o mtodo da superclasse.
Recordando ao captulo 2, lembre-se que a primeira subclasse concreta de Horista ou
Empregado dever substituir o mtodo getSalario() !

Uma tentativa de restringir mais o cdigo do mtodo causa erro de compilao, como veremos
o cdigo a seguir:

1. abstract class Empregado {
2. protected abstract double getSalario();
3. }
4.
5. abstract class Horista extends Empregado {
6. private abstract double getSalario();
7. }


[color=red:3977e586f4]Erro de compilao: getSalario() in Horista cannot override getSalario()
in Employee; attempting to assign weaker access privileges; was protected
![/color:3977e586f4]

5.4.3 - No deve lanar excees verificadas novas ou mais abrangentes

5.4.3.1 - Excees mais abrangentes

J discutimos o que so excees no captulo 4, e com certeza no precisaremos relembrar
(torcemos pra isso - pois s foi um captulo atrs). Um exceo mais abrangente uma
exceo que pode capturar mais erros, vejamos o cdigo:

1. abstract class Empregado {
2. abstract public double calcularComissao() throws ClassNotFoundException;
3. }
4.
5. abstract class Horista extends Empregado {
6. abstract public double calcularComissao() throws Exception;
7. }


Na hierarquia de classes de excees, ClassNotFoundException subclasse de Exception, ou
seja, Exception mais abrangente que ClassNotFoundException, portanto qualquer tentativa de
compilar o cdigo acima causar um erro de compilao:
[color=red:3977e586f4]calcularComissao() in Horista cannot override calcularComissao() in
Empregado; overridden method does not throw java.lang.Exception ![/color:3977e586f4]

5.4.3.2 - Excees verificadas novas

1. abstract class Empregado {
2. abstract public double calcularComissao() throws ClassNotFoundException;
3. }
4.
5. abstract class Horista extends Empregado {
6. abstract public double calcularComissao() throws IllegalAccessException
, RuntimeException;
7. }


O cdigo acima no compila pois IllegalAccessException uma exceo verificada e no tinha
sido definida no mtodo da superclasse, enquanto que a exceo RuntimeException no
verificada e no causar nenhum efeito, se tirarmos a declarao IllegalAccessException do
mtodo da subclasse o cdigo acima ser compilado normalmente. Voc precisar saber o que
uma exceo verificada e no verificada, acrescentar exceo verificada em um sub-mtodo
gera um erro de compilao, enquanto que acrescentar uma exceo no verificada no causa
nenhum efeito colateral. Se tiver alguma dvida quanto a exceo, revise o captulo 4.

5.4.4 - Mtodos finais no podem ser substitudos

Revisando o captulo 2, um mtodo final nunca poder ser substitudo, veja o cdigo:

1. class Empregado {
2. private double salario;
3. final public double getSalario() {
4. return this.salario;
5. }
6. }
7.
8. class Horista extends Empregado {
9. public double getSalario() {
10. return -1;
11. }
12. }


[color=red:3977e586f4]Erro de compilao: getSalario() in Horista cannot override getSalario()
in Empregado; overridden method is final[/color:3977e586f4]

5.4.5 - Uma subclasse usar super.MetodoNome para executar o mtodo substitudo
pela subclasse

Isso muito simples, examinando o cdigo a seguir:

1. class Empregado {
2. public double getSalario() {
3. return -1;
4. }
5. }
6.
7. class Horista extends Empregado {
8. public double getSalario() {
9. return -2;
10. }
11. public void calcular() {
12. System.out.println("Salario da superclasse: "+super.getSalario());
13. System.out.println("Salario da subclasse: "+this.getSalario());
14. }
15. public static void main(String[] args) {
16. Horista h = new Horista();
17. h.calcular();
18. }
19. }


O resultado ser:

Salario da superclasse: -1.0
Salario da subclasse: -2.0

5.5 - Sobreposio/Sobrecarga de mtodo (overload)

5.5.1 - Mtodos sobrepostos devem alterar a lista de argumentos

Para sobrepor um mtodo, sua assinatura deve ser diferente, pois a identificao de um
mtodo sua assinatura (lista de argumentos), analogicamente igual ao ser humano. Vejamos
o cdigo:

1. class Empregado {
2. public void calcularSalario() { }
3. public void calcularSalario(int value) { }
4. public void calcularSalario(long value) { }
5. }


Observe que o mtodo calcularSalario foi definido de trs forma, mas no pense assim! Pois
no o mesmo mtodo e sim trs mtodos distintos, com assinaturas diferentes. Isso muito
importante pois imagine que voc queira definir a lgica de negcio dos mtodos somente no
mtodo sem argumentos calcularSalario(), fazendo com que os demais somente o chamem -
com isso voc eliminaria a redundncia de cdigo que muitas vezes nos incomodada.

5.5.2 - Tipos de retornos diferentes desde que a assinatura tambm seja

Nenhum problema voc ter com o cdigo abaixo, visto que as assinaturas so diferentes,
portanto so mtodos sobrepostos.

1. class Empregado {
2. public void calcularSalario() { }
3. public double calcularSalario(int value) {
4. return 2.0;
5. }
6. public double calcularSalario(long value) {
7. return 1.0;
8. }
9. }


No confunda com mtodos substitudos que no podem ter assinaturas diferentes !

5.5.3 - Podem ter modificadores de acesso diferentes

Como so mtodos distintos, cada um pode ter um modificador de acesso.

1. class Empregado {
2. public void calcularSalario() { }
3. protected void calcularSalario(int value) { }
4. private void calcularSalario(long value) { }
5. void calcularSalario(short value) { }
6. }


Observe que os mtodos acima tem quatro modificadores diferentes.

5.5.4 - Podem lanar excees diferentes

Nenhum problema voc ter se lanar excees (verificadas ou no) em mtodos
sobrecarregados, mas repito novamente, no confunda com os mtodos substitudos, pois as
regras so outras.

1. class Empregado {
2. public void calcularSalario() throws CloneNotSupportedException { }
3. protected void calcularSalario(int value) throws IllegalAccessException
{ }
4. private void calcularSalario(long value) throws Exception { }
5. void calcularSalario(short value) { }
6. }


5.6 - Mtodos de uma superclasse podem ser sobreposto em um subclasse

Um mtodo de uma superclasse pode perfeitamente ser sobreposto em um subclasse como
voc pode ver no cdigo a seguir:

1. abstract class Empregado {
2. abstract public void calcularSalario();
3. }
4.
5. abstract class Horista extends Empregado {
6. abstract protected double calcularSalario(int value) throws Exception;
7. }


Observe tambm que fomos alm, ou seja, aplicamos todas as regras de mtodos sobreposto
no mtodo da classe Horista - mudamos seu modificador (protected), mudamos o retorno
(double), acrescentamos uma exceo verificada, isso tudo em funo da alterao da
assinatura (int value). Com isso conclumos que um mtodo sobreposto um outro mtodo,
apesar de ter o mesmo nome, mas analogicamente quantos Joses conhecemos ? O que os
identifica burocraticamente so suas assinaturas !

5.7 - O polimorfismo aplicado substituio e no a sobreposio

Essa afirmao pode parecer um pouco intrigante, mas muito simples. Primeiro, vamos
entender o que polimorfismo. Segundo a maioria das bibliografias, polimorfismo a
capacidade que um mtodo tem de responder de vrias formas (como o prprio sentido
etimolgico da palavra). Bom, como aprendemos (pelo menos o que esperamos), a
sobreposio tem a funo de permitir que voc defina mtodos distintos, ou seja, novos
mtodos, como voc deve ter observado, na definio de polimorfismo acima, a palavra "um"
foi destacada, para enfatizar bem, que o mesmo mtodo, nico - portanto isso s pode ser
aplicado substituio. Vejamos o cdigo abaixo para entender isso na prtica:

1. abstract class Empregado {
2. protected double salario;
3. public abstract double getSalario();
4. }
5.
6. class Horista extends Empregado {
7. public double getSalario() {
8. return this.salario/220;
9. }
10. }
11.
12. class Mensalista extends Empregado {
13. public double getSalario() {
14. return this.salario;
15. }
16. }


Observe que o mtodo getSalario foi substitudo (no sobreposto, a assinatura continuou
idntica), nas subclasses, mas quando voc executar esse cdigo ver que o mtodo getSalario
responder de forma distinta quando chamado o da classe Horista e/ou da classe Mensalista.
Talvez voc possa estar se perguntando, "mas so mtodos redefinidos, dois mtodos distintos"
- at podemos concondar em partes, mas existe uma mgica que voc ver no cdigo abaixo
que encerrar essa questo, vejamos:

1. abstract class Empregado {
2. protected double salario;
3. public abstract double getSalario();
4.
5. public void setSalario(double value) {
6. this.salario = value;
7. }
8. }
9.
10. class Horista extends Empregado {
11. public double getSalario() {
12. return this.salario/220;
13. }
14. }
15.
16. class Mensalista extends Empregado {
17. public double getSalario() {
18. return this.salario;
19. }
20. }
21.
22. public class Polimorfismo {
23. public static void main(String[] args) {
24. Empregado e;
25. Horista h = new Horista();
26. Mensalista m = new Mensalista();
27. h.setSalario( 2240.00 );
28. m.setSalario( 2240.00 );
29. e = h;
30. System.out.println( "Salario em horas: "+e.getSalario() );
31. e = m;
32. System.out.println( "Salario em horas: "+e.getSalario() );
33. }
34. }


Observe que na classe Polimorfismo o mtodo e.getSalario foi chamado duas vezes no entanto
o resultado desse cdigo ser:

Salario em horas: 10.181818181818182
Salario em horas: 2240.0

Existe muita discusso sobre esse assunto, mas no se preocupe, absorva o que achar correto,
tenha opinio!


5.8 - Voc no pode criar um novo objeto sem chamar o seu construtor

Para criar uma nova instncia de uma classe (um objeto) voc dever chamar o seu construtor.
Existe uma particularidade definida por um padro de projeto chamada Singleton que trata isso
um pouco diferente, mas no vamos entrar nesse estudo agora, visto que no um objetivo
para quem est almeijando a certificao. A sintaxe para se criar um objeto :

ClassName x = new ClassName();

Onde,

ClassName - o nome da classe ou tipo
x - ser o nome do objeto

5.9 - Toda superclasse da rvore de herana de um objeto chamar um construtor

Mesmo que voc no defina um construtor padro, o compilador se encarregar de fazer isso
para voc, independente do nvel de herana de sua classe, saiba que esta sempre chama um
construtor de sua superclasse imediata. T, sei, voc est se perguntando, "p, mas e se minha
classe no herdar de ningum ?" Toda classe a exceo da Object herda de alguma classe, se
no herdar de ningum o compilador coloca como superclasse a class java.lang.Object !

5.10 - Toda classe, mesmo as classes abstratas, tem pelo menos um construtor

Mesmo que voc no defina um construtor para a sua classe, o compilador o far, mesmo que
sua classe seja abstrata, entenda porque. Se tivermos a hierarquia de classe a seguir:

1. abstract class Pessoa { }
2.
3. abstract class PessoaFisica extends Pessoa { }
4.
5. abstract class Empregado extends PessoaFisica { }


Nenhum construtor foi definido para essa classes, mas o compilador (como camarada),
modificou suas classes que ficaram assim:

1. abstract class Pessoa {
2. public Pessoa() {
3. super();
4. }
5. }
6.
7. abstract class PessoaFisica extends Pessoa {
8. public PessoaFisica() {
9. super();
10. }
11. }
12.
13. abstract class Empregado extends PessoaFisica {
14. public Empregado() {
15. super();
16. }
17. }


Voc pode achar estranho, criar construtores para classes abstratas, visto que, nunca sero
instanciadas, mas isso feito para respeitar a hierarquia da pilha de construtores.

5.11 - Construtores devem ter o mesmo nome da classe

Qualquer tentativa de definir um construtor com um nome diferente do nome da classe, gerar
erro de compilao !

1. class Emp {
2. protected double salario;
3.
4. public emp() { // nota 1
5. super();
6. }
7.
8. public double getSalario() {
9. return this.salario;
10. }
11.
12. public void setSalario(double value) {
13. this.salario = value;
14. }
15. }


[color=red:3977e586f4]Erro de compilao: "invalid method declaration; return type
required"[/color:3977e586f4]

O erro se deu porque houve uma tentativa de definio do construtor como um nome diferente
do nome da classe, o compilador subentendeu que isso seria a definio de um mtodo, como
no foi especificado nenhum retorno (mesmo que fosse void) gerou um erro de compilao.

5.12 - Construtores no podem ter tipo retornos

Qualquer tentativa de especificar um tipo de retorno a um construtor, automaticamente ser
considerado um mtodo com o mesmo nome da classe.

1. class Emp {
2. protected double salario;
3.
4. public void Emp() {
5. }
6.
7. public double getSalario() {
8. return this.salario;
9. }
10.
11. public void setSalario(double value) {
12. this.salario = value;
13. }
14. }


Nesse caso Emp() no um construtor e sim um mtodo com o nome idntico ao nome da
classe.

5.13 - Construtores podem ter qualquer modificador de acesso

Um construtor poder ser definido com qualquer modificador de acesso, inclusive private !

1. class Emp {
2. protected double salario;
3.
4. private Emp() {
5. }
6.
7. public double getSalario() {
8. return this.salario;
9. }
10.
11. public void setSalario(double value) {
12. this.salario = value;
13. }
14. }


5.14 - Se nenhum construtor for criado o compilador criar um padro

Se definirmos uma classe da seguinte forma:

1. class Emp {
2. protected double salario;
3.
4. public double getSalario() {
5. return this.salario;
6. }
7.
8. public void setSalario(double value) {
9. this.salario = value;
10. }
11. }


Onde est seu construtor ? No foi especificado pelo programador, porm o compilador o
criar, deixando a classe compilada da seguinte forma:

1. class Emp {
2. protected double salario;
3.
4. private Emp() {
5. super();
6. }
7.
8. public double getSalario() {
9. return this.salario;
10. }
11.
12. public void setSalario(double value) {
13. this.salario = value;
14. }
15. }


No pense que ele ir alterar o seu arquivo .java, ele s faz isso quando ger o .class pois se
voc tiver um construtor padro, o compilador no se entromete e no gera nenhum
construtor.

5.15 - A primeira chamada de um construtor

Como boa prtica de programao, um construtor deve primeiramente chamar um construtor
sobrepostos com a palavra this() ou um construtor da superclasse imediata com a palavra
chave super(), se no for definida explicitamente no construtor, o compilador ter o capricho de
faz-lo:

1. class Emp {
2. protected double salario;
3.
4. Emp(double value) {
5. super();
6. setSalario( value );
7. }
8.
9. Emp() {
10. this(0);
11. }
12.
13. public double getSalario() {
14. return this.salario;
15. }
16.
17. public void setSalario(double value) {
18. this.salario = value;
19. }
20. }


Muito interessante o que acontece nesse cdigo, veja que existem dois modificadores, um que
recebe um argumento (double value) e outro que no recebe nenhum argumento, ou seja, o
programador que deseja utilizar essa classe pode instanciar essa classe de duas formas, esse
exemplo mostra bem um bom caso de utilizao para a sobreposio de mtodos (mesmo que
sejam construtores). Observe que o cdigo de definio inicial do salrio est sendo feito
somente no construtor parametrizado pois quando o usurio chama um construtor sem
argumento, esse chama o construtor sobreposto passando o valor 0 usando a palavra this. Com
isso, podemos concluir que de qualquer forma que essa classe for instanciada, o construtor
parametrizado ser executado e consequentemente uma chamada a super construtor da
superclasse tambm o ser.

5.16 - O compilador adicionar uma chamada super

Se voc definir um construtor em sua classe, o compilador no se afoitar e adicionar para
voc, mas como j foi falado varias vezes, um construtor dever chamar sempre o construtor
da sua superclasse (a exceo de uma chamada a um construtor sobreposto), isso porque o
construtor da classe Object sempre dever ser executado - provavelmente ele faz coisas
maravilhosas que ainda no conhecemos, mas sempre, sempre mesmo, esse dever ser
executado, por isso vejamos o cdigo a seguir:

1. class Emp {
2. protected double salario;
3.
4. Emp(double value) {
5. setSalario( value );
6. }
7.
8. Emp() {
9. this(0);
10. }
11.
12. public double getSalario() {
13. return this.salario;
14. }
15.
16. public void setSalario(double value) {
17. this.salario = value;
18. }
19. }


O cdigo de Object ser executa nesse caso ? Claro que no ! Voc no escreveu nenhuma
chama super em nenhum construtor. Mas vamos nos atentar aos detalhes. Sabemos que essa
classe composta por dois construtores, se o usurio instancia da seguinte forma: Emp e =
new Emp(240); - o objeto seria criado, setado o salrio e no passaria pelo construtor sem
parmetros, pois foi chamado diretamente o construtor parametrizado, agora vejamos um outro
caso, se a instanciao ocorresse da seguinte forma: Emp e = new Emp(); - nenhum parmetro
foi passado, portanto o construtor que ser executado ser obviamente o construtor sem
parametros que chama o construtor parametrizado atravs da palavrinha this, que seta o valor
da varivel salario. Seguindo o fluxo, podemos observar que sempre o construtor parametrizado
ser executado, independente das formas como fora instanciado a classe, portanto a insero
da chamada ao construtor superior imediato dever ser nesse caso no construtor parametrizado
como mostra o cdigo abaixo, mesmo porque qualquer tentativa de inserir uma chamada a
super no construtor sem parametro ocasionaria um erro de compilao.

1. class Emp {
2. protected double salario;
3.
4. Emp(double value) {
5. super();
6. setSalario( value );
7. }
8.
9. Emp() {
10. this(0);
11. }
12.
13. public double getSalario() {
14. return this.salario;
15. }
16.
17. public void setSalario(double value) {
18. this.salario = value;
19. }
20. }


Assim geraria um erro de compilao:

1. class Emp {
2. protected double salario;
3.
4. Emp(double value) {
5. super();
6. setSalario( value );
7. }
8.
9. Emp() {
10. super();
11. this(0); // Erro
12. }
13.
14. public double getSalario() {
15. return this.salario;
16. }
17.
18. public void setSalario(double value) {
19. this.salario = value;
20. }
21. }


[color=red:3977e586f4]Erro de compilao: call to this must be first statement in
constructor[/color:3977e586f4]

5.17 - As variveis de instncias s podem ser acessados aps o construtor ser
encerrados

Nenhuma referncia a variaveis de instncia (do objeto) pode ser feita antes do construtor ser
chamado, como mostra o cdigo abaixo:

1. public class Teste {
2.
3. public static void main(String args[]) {
4. Emp e;
5. e.setSalario( 240 ); // Erro 1
6. }
7. }


[color=red:3977e586f4]Erro de compilao 1: variable e might not have been
initialized[/color:3977e586f4]

1. class Emp {
2. protected double salario;
3.
4. Emp(double value) {
5. super();
6. setSalario( value );
7. }
8.
9. Emp() {
10. this(0);
11. }
12.
13. public double getSalario() {
14. return this.salario;
15. }
16.
17. public void setSalario(double value) {
18. this.salario = value;
19. }
20. }


Se voc lembra bem do captulo 2 deve constestar isso, devido ao fato de existirem as variveis
estticas ! Claro que no, as variveis estticas no so variveis de instncia (de objeto) e sim
da classe !

5.18 - As classe abstratas tem construtores que so chamados quando as classe
concretas so instanciadas

Mesmo que no as classes abstratas nunca sero instanciadas, seus construtores so
executadas na pilha de execuo pelas suas subclasses concretas, por isso que o compilador
acrescenta caso voc no os tenha acrescentado.

5.19 - Interfaces no tem construtores

Como as interfaces tem outro papel na orientao a objetos, elas no possuem construtores.

5.20 - Construtores nunca so herdados

Isso nos leva a concluir que nunca podero ser substitudos.

5.21 - Um construtor no pode ser chamado por um mtodo da classe

Os construtores nunca podero ser chamados de mtodos de uma classe, como mostra o
cdigo abaixo:

1. class Emp {
2. private double salario;
3. public void calcular() {
4. super(0); // Erro
5. }
6. }


[color=red:3977e586f4]Erro de compilao: call to super must be first statement in constructor
![/color:3977e586f4]

Somente atravs de um outro construtor:

1. class Emp {
2. private double salario;
3. Emp(double value) {
4. super();
5. setSalario( value );
6. }
7. Emp() {
8. this(0); // ok - um construtor pode chamar outro
9. }
10. public double getSalario() {
11. return this.salario;
12. }
13. public void setSalario(double value) {
14. this.salario = value;
15. }
16. }


5.22 - Regras para chamadas a construtores:

5.22.1 - Deve ser a primeira instruo de um construtor

1. class Emp {
2. private double salario;
3. Emp(double value) {
4. setSalario( value );
5. super(); // Erro
6. }
7. Emp() {
8. this(0);
9. }
10. public double getSalario() {
11. return this.salario;
12. }
13. public void setSalario(double value) {
14. this.salario = value;
15. }
16. }


[color=red:3977e586f4]Erro de compilao: call to super must be first statement in
constructor[/color:3977e586f4]

5.22.2 - A assinatura determina qual construtor ser chamado

Como permitido a sobreposio de construtores, a assinatura que vai determinar qual o
construtor ser chamado.

5.22.3 - Um construtor pode chamar outro

Para evitar redundncia de cdigo, voc pode criar vrios construtores com assinaturas
diferentes mas definir somente um para iniciar seu objeto realmente, onde os demais
construtores somente o chamem, como mostra o cdigo a seguir:

1. class Emp {
2. private double salario;
3. Emp(double value) {
4. super();
5. setSalario( value );
6. }
7. Emp() {
8. this(0);
9. }
10. public void setSalario(double value) {
11. this.salario = value;
12. }
13. }


No exemplo acima, o construtor sem parmetro est chamando o construtor na prpria classe
(atravs da palavra this) que est chamando o construtor de sua superclasse (nesse caso
Object) e depois setando o valor de varivel de instncia salario. Note que a atribuio
varivel salario poderia ser feita diretamente no cdigo do construtor Emp(), mas se
resolvssemos adicionar algum cdigo nos construtores dessa classe, o deveramos fazer em
dois ou mais lugares, o que causaria uma certa redundncia de cdigo, no caso acima no, o
cdigo que precisa se alterado somente do construtor Emp(double value), pois os demais
(nesse caso um) o chamam.

5.22.4 - this e super no podem no mesmo construtor

Voc nunca poder ter em um nico construtor duas chamadas uma a this() e outra a super().
Ou voc tem um ou outro, qualquer cdigo escrito de forma que discorde dessa linha de
pensamento considerado errado, e o compilador no permitir tal faanha.

5.23 - Tipos de retorno

5.23.1 - Mtodos sobrepostos podem alterar seu retorno.

Observe que no cdigo abaixo houve uma sobrecarga de mtodo, por isso o retorno pode ser
alterado sem nenhum problema.

1. abstract class Empregado {
2. abstract public int calcularReajuste(int value);
3.
4. abstract public double calcularReajusta(double value);
5. }


No tente fazer isso com substituio de mtodos como mostra o cdigo a seguir:

1. abstract class Empregado {
2. public abstract double getSalario();
3. }
4.
5. class Horista extends Empregado {
6. public float getSalario() { // Erro
7. return 240f;
8. }
9. }


[color=red:3977e586f4]Erro de compilao: getSalario() in Horista cannot override getSalario()
in Empregado; attempting to use incompatible return type[/color:3977e586f4]

5.23.2 - null um valor aceitvel para mtodos que retornem objetos

1. abstract class Empregado {
2. public abstract String getNome();
3. }
4.
5. class Horista extends Empregado {
6. public String getNome() {
7. return null;
8. }
9. }


Nenhum problema no cdigo acima.

5.23.3 - Retorno de tipos primitivos

Quando um mtodo retornar um tipo primitivo, qualquer valor que poder implicitamente
convertido para o tipo do retorno, poder ser retornado sem nenhum problema.

1. abstract class Empregado {
2. public abstract double getSalario();
3. }
4.
5. class Horista extends Empregado {
6. public double getSalario() {
7. float rc = 240.0f;
8. return rc;
9. }
10. }


Veja que no cdigo acima, o retorno do mtodo um tipo double, no entando o que est sendo
retornado um float, como essa converso implcita, esse cdigo compilado e executado
sem nenhum problema.

Agora, vamos observar o seguinte cdigo:

1. abstract class Empregado {
2. public abstract float getSalario();
3. }
4.
5. class Horista extends Empregado {
6. public float getSalario() {
7. double rc = 240.0;
8. return rc; // Erro
9. }
10. }


[color=red:3977e586f4]Erro de compilao: possible loss of precision[/color:3977e586f4]


5.23.4 - Tipo de retorno void

Um mtodo pode no retornar nada (void), voc poder perfeitamente criar um mtodo que
no tenha nenhum retorno, basta colocar a palavra void no seu retorno, como veremos no
cdigo abaixo:

1. public class Empregado {
2. public void calcularSalario() { }
3. }


O mtodo acima no retorna nenhum valor, apesar de processar algum cdigo, voc ainda
poder inserir um return (sem nenhum valor) no corpo do mtodo se quiser encerrar a sua
execuo antes do fluxo normal, como o cdigo abaixo:

1. public class Empregado {
2. public void calcularSalario() {
3. if ( this.count <= 0 ) return;
4. // faz os clulos
5. }
6. }


O cdigo acima, testa se a variavel count menor ou igual a 0, se for encerra o mtodo ! fora
de nosso foco questionar se isso um cdigo bem feito ou no, claro que no faramos algo
assim, mais a questo a utilizao da palavra return no meio do corpo de um mtodo e que
no retorna nada (void).

Observe o cdigo abaixo:

1. public class Empregado {
2. public void calcularSalario() {
3. if (count <= 0) return -1; // Erro
4. // faz os clulos
5. }
6. }


[color=red:3977e586f4]Erro de compilao: cannot return a value from method whose result
type is void[/color:3977e586f4]

Qualquer tentativa de retornar um valor em um mtodo com o tipo de retorno void, causar um
erro de compilao.

5.23.5 - Retornando classes

Se um mtodo retorna uma classe X e Y uma subclasse de X, Y pode ser retornado sem
maiores problemas nesse mtodo.

Vejamos:

1. abstract class Empregado {
2. }
3.
4. class Horista extends Empregado {
5. public Empregado getObject() {
6. return this;
7. }
8. }


Observe que o retorno de getObject() uma classe Empregado e o que est sendo
retornado no mtodos this que refere-se a um objeto da classe Horista, e o cdigo
acima no seria nenhum problema para o grande compilador !

Mais uma etapa concluda !!! :o :o :o

Cap. 6 - java.lang e Wrappers
Captulo 6 - java.lang - a classe Math, Strings e Wrappers

6.1 - String

Objetos String so inalterveis, porm as variveis de referncias no.

Essa afirmao pode ser contenciosa mais no . Quando um objeto String criado na
memria, ele no poder ser alterado, vejamos o cdigo:

1. String s1= "abc";
2. String s2 = s1;
3. s1 = "abcd";


Observe que ambas as variaveis de referncias apontam (ops! isso no C, referenciam) para
o mesmo objeto na memria, se listssemos o valor das variveis s1 e s2 obteramos os
resultados:

s1 -> "abcd"
s2 -> "abc"

Note que a string "abc" no foi alterada, pois s1 esta agora referenciando um outro objeto
"abcd" ! Enquanto que s2 continua referenciando "abc".

Verbalmente esse cdigo diz o seguinte: "JVM, por favor, crie uma string no pool de strings
(depois detalharemos sobre isso) com o valor "abc" obrigado.". Agora, s2 guarda o endereo
fsico da mesma string "abc" (nenhum string foi criada no pool), na terceira linha, soar uma
voz: "Crie uma string "abcd" (veja que no foi alterada a primeira string) onde s1 a
referenciar, obrigado.". Com isso podemos concluir que s2 continua referenciando a string
"abc", mas que a referencia s1 foi alterada e a string "abc" no.

Se um nova String for criada e no for atribuida a nenhuma varivel de referncia,
ela ficar perdida.

O consumo de memria um dos pontos crticos para que um programa seja bem sucedido, o
uso incorreto da "escassa memria" (a no ser que seu programa v rodar em um equipamento
com 32 gb e memria) pode gerar falhas irreparveis em um programa, com essa preocupao
a Sun (criadora da especificao Java se voc no sabe), criou um pool de String que armazena
todas as strings coincidentes em um programa Java, ou seja, se voc tiver duas variveis que
referenciam uma string "kuesley legal" saiba que voc s ter uma string no pool, porm
duas referncias e, por esta razo que as strings so inalterveis. Mas se voc criar um string
e no especificar nenhuma varivel de referncia ela ficar perdida - o que os criadores da
linguagens no gostaro nem um pouquinho se olharem para o seu cdigo, pois voc estaria
desprezando todo o esforo deles em otimizar o uso da memria. Vejamos um exemplo prtico
disso:

1. String s1 = "abc";
2. String s2 = "abcd" + "e";


Saiba que o cdigo acima criar no pool 4 strings, sendo que duas ficaram perdidas
("abcd","e"), pois somente as string "abc" e "abcde" esto sendo referenciadas.

Se voc redirecionar a referencia de uma String para outra String, o objeto String
anterior poder ser perdido.

1. String s1 = "abcd";
2. s1 = "xuxu";


O que o cdigo acaba de fazer criar uma string no pool "abcd" e referenci-lo por s1, depois
criar um nova string "xuxu" e referenci-lo pela mesma varivel s1, portanto, a string "abcd"
ficar perdida no pool.

O mtodo substring

O mtodo que errneamente foi definido com substring - pois deveria ser subString, recebe
dois argumentos do tipo inteiro, onde define a posio inicial da string (comeando do 0) e
onde deve terminar a string (comeando de 1), isso quer dizer que:

1. "abcdefghijlmnop".substring(0,3); // resulta em: abc


Pois o primeiro argumento considerado o incio em 0 e o segundo o incio considerado em
1, lembre-se disso.

1. String s = "kuesley e legal";
2. System.out.println(s.substring(8,15));


Resultado: "e legal"

A classe String final

Nenhum mtodo da classe String pode ser substitudo, visto que a classe final.

Mtodos da String

concat- Adiciona umab string a outra, porm no altera a string em que o mtodo est sendo
executado:

1. String s = "teste";
2. s.concat("nao mudou");
3. System.out.println(s); // Resultado "teste"


Note que nenhuma alterao foi efetuada na string s. Se desejssemos alterar s, o cdigo
deveria ser da seguinte forma:

1. String s = "teste";
2. s = s.concat("nao mudou");
3. System.out.println(s); // Resultado "teste nao mudou"


equalsIgnoreCase- testa se uma string igual a outra ignorando a diferena entre letras
maisculas e minsculas:

1. String sl = "teste";
2. String su = "TESTE";
3. System.out.println(sl.equals(su)); // resultado: false
4. System.out.println(sl.equalsIgnoreCase(su)); // resultado: true


length- Obtm o tamanho da string.

1. String nome = "angeline jolie";
2. System.out.println(nome.length() ); // resultado: 14


replace- Substitui os caracteres de uma string.

1. String texto = "Est4mos 4qui p4r4 test4r";
2. texto = texto.replace('4','a');
3. System.out.println(texto); // resultado: Estamos aqui para testar


substring- Extrai uma string de outra.

1. String texto = "0123456789";
2. System.out.println(texto.substring(0,3)); // resultado: 012


J falamos anteriormente, mas queremos ser chatos mesmo, o primeiro argumento considerada
a string iniciando na posio 0, enquando que o segundo em 1 - por isso que o resultado
anterior "012".
Se for especificado um valor invlido para qualquer um dos dois argumento, uma exceo ser
lanada.

1. String texto = "0123456789";
2. System.out.println(texto.substring(0,11)); // exceo


Uma exceo ser lanada: java.lang.StringIndexOutOfBoundsException: String index out of
range: 11

toLowerCase- Muda todas as letras que estiverem maiscula para letra minscula.

1) Qual o resultado do trecho de cdigo acima ?

1. String s = "AKJDJE";
2. s.toLowerCase();
3. System.out.println(s);


a) Erro de compilao
b) Exceo
c) AKJDJE
d) Akjdje
e) akjdje

[color=green:430f7a8ef7]Resposta no final do captulo !!![/color:430f7a8ef7]

Errou ??? No esquea que a string so inalterveis. Portando s no est sendo reatribuido.

toUpperCase- Processo inverso do toLowerCase, ou seja, transforma em maiscula todas as
letras que estiverem minscula.

1. String s = "teste de caixa alta";
2. s = s.toUpperCase();
3. System.out.println(s); // resutlado: TESTE DE CAIXA ALTA


trim- Retira espaos das extremidades de uma string.

1. String s = " tem um ";
2. s = s.trim()
3. System.out.println("*"+s.trim()+"*"); // resultado: *tem um*


toString- retorna o valor da string. (mtodo intil : ) )

Como a classe String derivada de Object esse mtodo substitudo na classe String
retornando o valor da String propriamente dita.

1. String s = "mesma coisa";
2. System.out.print(s.toString()); // resultado: mesma coisa


equals- compara o valor de uma string com outra informada em argumento.

1. String s1 = "texto";
2. String s2 = "texto";
3. System.out.println(s1 == s2); // resultado 1: true
4. System.out.println(s1.equals(s2)); // resultado 2: true
5. s1 = new String("texto");
6. s2 = new String("texto");
7. System.out.println(s1 == s2); // resultado 3: false
8. System.out.println(s1.equals(s2)); // resultado 4: true


O resultado 1 true em funo da string "texto" ser criada uma nica vez e ser referenciado
pelos objetos s1 e s2. O resultado 2 verdadeiro pois o mtodo equals est comparando os
valores. J o resultado 3 falso, pois como os objetos foram criados usando a palavra chave
new voc ter dois objetos na memria apesar de terem os mesmos valores, j o resultado 4
true pois o mtodo equals sempre ir comparar os valores, como ambos os objetos tem os
mesmos valores o resultado true. Com isso podemos concluir que, o operador == compara se
os variveis de referncia esto referenciando o mesmo objeto, se for o caso retorna true caso
contrrio retorna falso, enquanto que o mtodo equals da classe String sempre ir comparar os
valores (no pense que esse mtodo funciona da mesma forma para a classe StringBuffer, isso
o oitavo pecado capital).

6.2 StringBuffer

Diferente da classe String, a classe StringBuffer pode sofrer alterao.

1. StringBuffer sb = new StringBuffer("testando");
2. sb.append(" se mudou");
3. System.out.println(sb);


Resultado: testando se mudou

Observe que o valor de sb foi alterado mesmo que no tenha sido atribudo sb, ou seja, o
mtodo append atuou sobre sb.

StringBuffer - mtodos importantes

append- esse mtodo adiciona uma string ao StringBuffer

1. StringBuffer sb = new StringBuffer("abc");
2. sb.append("def");
3. System.out.println(sb); // Resultado: abcdef


insert- insere uma string em um StringBuffer, comeando em 0 (zero)

1. StringBuffer sb = new StringBuffer("abc");
2. sb.insert(1,"x");
3. System.out.println(sb); // Resultado: axbc


Se um valor invlido for inserido no primeiro argumento, uma exceo ser lanada.

Como voc pode conferir no exemplo abaixo:

1. StringBuffer sb = StringBuffer sb = new StringBuffer("abc");
2. sb.insert(4,"x");
3. System.out.println(sb);


Um exceo ser lanada: StringIndexOutOfBoundsException, no esquea que a posio tem
incio em 0 (zero).

Uma observao vale ser ressaltada, visto que voc poder se deparar com uma questo como:

1. StringBuffer sb = StringBuffer sb = new StringBuffer("abc");
2. sb.insert(3,"x");
3. System.out.println(sb);


Voc pode pensar, "bom se posio inicia em 0 (zero), ento o limite para o primeiro
argumento 2, pois o ndice maior dessa string, mas o mtodo deve possibilitar uma insero
aps a letra "c" ento qual seria o ndice ??? 3 - exatamente. Nenhum problema ocorrer no
cdigo acima, e o resultado seria: "abcx"

reverse- inverte todos os caracteres da StringBuffer.

1. StringBuffer sb = new StringBuffer("kuesley");
2. sb.reverse();
3. System.out.println(sb); // resultado: yelseuk


toString- retorna o valor do objeto StringBuffer, esse mtodo herdado de Object.

1. StringBuffer sb = new StringBuffer("kuesley");
2. sb.reverse();
3. System.out.println(sb); // resultado: yelseuk
4. System.out.println(sb.toString()); // resultado: yelseuk


Exatamente o mesmo resultado do prprio objeto.

equals

O mtodo equals da classe StringBuffer no substitudo, isso significa que ele no compara
valores, portanto uma questo com essa considerao pode confundir, vejamos:

1. StringBuffer sb1 = new StringBuffer("kuesley");
2. StringBuffer sb2 = new StringBuffer("kuesley");
3. System.out.println( sb1.equals(sb2) ); // resultado: false


Apesar de conterem o mesmo valor, o resultado ser false pois comparado se as variveis,
referenciam o mesmo objeto na memria, e como existem 2 objetos distintos na memria, o
resultado false.

Encadeamento de mtodos

Voc poder se deparar tambm com questo que encadenham mtodos como:

2) Dado o codigo abaixo, qual ser o resultado ?

1. StringBuffer sb = new StringBuffer("kuesley");
2. System.out.println(sb.insert(sb.length()," legal").reverse().toString());


a) Uma exceo ser lanada
b) Erro de compilao
c) KUESLEY LEGAL
d) kuesley legal
e) lagel yelseuk

[color=green:430f7a8ef7]Resposta no final do captulo !!![/color:430f7a8ef7]

Observe que os mtodos foram executados da ESQUERDA para a DIREITA exatamente como se
l, ou seja, o primeiro mtodo que foi executado foi o insert alterando o objeto sb, mudando a
StringBuffer para "kuesley legal", depois foi invertido a string "odnil yelseuk" depois o
mtodo toString que, aqui pra ns, no faz nada !!!

6.3 Usando a classe Java.lang.Math

abs

Retorna o valor absoluto de um argumento, veja suas assinaturas:

public static int abs( int value )
public static long abs( long value )
public static float abs(float value )
public static double abs(double value )

Observe que ele sobreposto para aceitar qualquer tipo primitivo a exceo de double e float.
O resultado sempre ser um nmero positivo a exceo de dois casos, mas como ainda no sei,
no colocarei aqui, mas tem !

Agora j t sabendo, Hhehehe

Se o valor informado for menor que Interger.MIN_VALUE ou Long.MIN_VALUE veja o exemplo
a seguir:

System.out.println("Valor absoluto para "+Math.abs(-2147483648));
// Resultado: -2147483648

System.out.println("Valor absoluto para "+Math.abs(-9223372036854775808L));
// Resultado: -9223372036854775808L

System.out.println("Valor absoluto para "+Math.abs(-2147483647);
// Resultado: 2147483647

System.out.println("Valor absoluto para "+Math.abs(-9223372036854775807L));
// Resultado: 9223372036854775807

Onde:

Integer.MIN_VALUE -> -2147483648
Long.MIN_VALUE -> -9223372036854775808

Note que quando o valor informado for igual ao valor de Integer.MIN_VALUE e
Long.MIN_VALUE a funo no retorna o valor absoluto, isso s para complicar nossa vida.

ceil

Retorna o nmero "ponto flutuante inteiro" superior mais prximo.

1. public static float ceil(float value)
2. public static double ceil(double value)
3. System.out.println(Math.ceil(3.8)); // Resultado: 4.0
4. System.out.println(Math.ceil(-3.3)); // Resultado: -3.0


floor

Retorna o nmero ponto flutuante inteiro inferior mais prximo.

1. public static float floor(float value)
2. public static double floor(double value)
3.
4. System.out.println(Math.floor(-10.9)); // Resultado: -11.0
5. System.out.println(Math.floor(12.2)); // Resultado: 12.0


max

Esse mtodo retorna o maior nmero entre dois informados, sua assinatura de mtodos :

1. public static int max(int a, int b )
2. public static long max(long a, long b )
3. public static float max(float a, float b )
4. public static double max(double a, double b )


Observe que no existe assinatura para os tipos byte, short porque esse podem implicitamente
ser convertidos para int.

1. System.out.println("O maior entre -8 e -9 : "+Math.max(-8,-
9)); // Resultado: -8
2. System.out.println("O maior entre -8 e 9 : "+Math.max(-
8.0,9)); // Resultado: 9.0


Por mais que no exista um mtodo com as assinaturas (double, int) seguindo as regras de
valores literais da Java, o valor 9 convertido implicitamente para double por isso o resultado
: 9.0 um tipo double.


min

Esse mtodo retorna o menor nmero entre dois informados, suas assinaturas so:

public static int min(int a, int b )
public static long min(long a, long b )
public static float min(float a, float b )
public static double min(double a, double b )

Observe que no existe assinatura para os tipos byte, short porque esse podem implicitamente
ser convertidos para int.

1. System.out.println("O menor entre -8 e -9 : "+Math.max(-8,-
9)); // Resultado: -9
2. System.out.println("O menor entre 8 e -9 : "+Math.max(8,-
9.0)); // Resultado: 8.0


Por mais que no exista um mtodo com as assinaturas (int, double) seguindo as regras de
valores literais da Java, o valor 8 convertido implicitamente para double por isso o resultado
: 8.0 um tipo double.


round

Arredonda um numero ponto flutuante recebido como argumento, veja suas assinaturas:

public static int round(float a)
public static long round(double a)

Note que como sua funo arredondar, deve retornar um tipo inteiro, porm como o
argumento pode ser um float (32 bits) ou um double (64 bits) o retorno deve suportar essa
quantidade de bits por isso o tipo de retorno muda conforme o argumento de entrada.

1. class Teste {
2. public static void main(String args[]) {
3. System.out.println(Math.round(9.4)); // Resultado: 9
4. System.out.println(Math.round(9.5)); // Resultado: 10
5. System.out.println(Math.round(9.9)); // Resultado: 10
6. System.out.println(Math.round(-9.9)); // Resultado: -10
7. }
8. }


Para entender, vamos dividir em duas regras:

1) Nmero positivo:

Arredondando um nmero positivo: o algoritmo soma ao nmero informado 0.5 e trunca o
nmero, como podemos ver a seguir:

|3.9| + 0.5 = 4.4 // Resultado: 4
|3.5| + 0.5 = 4.0 // Resutlado: 4
|3.4| + 0.5 = 3.9 // Resultado: 3

Funciona exatamento como os mtodos Math.ceil (se o nmero decimal for maior ou igual a
0.5) e Math.floor (se o nmero decimal for menor que 0.5) !

2) Nmero negativo:

|-3.9| + 0.5 = -4.4 // Resultado: -4
|-3.4| + 0.5 = -3.9 // Resultado: -3
|-3.5| + 0.5 = -4.0 (deveria), mas o resultado : -3

Pode parecer estranho o fato de que no primeiro caso o resultado foi -4 onde o esperado fosse
-3, porm nesse caso o round ignora o sinal, ou seja, trabalha com nmeros absolutos - porm
como os criados da linguagem java gostam de complicar, existe um exceo no caso de nmero
negativo quando o valor decimal do nmero for 0.5 o nmero ser arredondado para cima.

Vejamos exemplos:

Math.round(-3.5) // Resultado: -3
Math.round(3.5) // Resultado: 4

Math.round(-3.4) // Resultado: -3
Math.round(-3.6) // Resultado: -4

random

O mtodo Math.random retorna um nmero aleatrio entre 0.0 e menor que 1.0.

public static double random()

System.out.println( Math.random() ); // Resultado: qualquer valor entre 0.0 (inclusive) e menor
que 1.0

sin

Retorna o seno de um ngulo, para o exame voc ter que saber como calcular o sena de
qualquer espcie de ngulo, precisar ser um matemtico e fsico (calma, no desista, s
estava brincando) ! Voc no precisar saber como se calcula nenhum ngulo, basta saber que
recebe um argumento que um valor de um ngulo em radiano.

public static double sin(double a)

cos

Calcula o co-seno de um ngulo.

public static double cos(double a)

tan

Retorna a tangente de um ngulo.

public static double tan(double a)

Lembre-se que esse trs ltimo mtodos recebe um valor de grau em radiano, no tente passar
por exemplo 90" como parmetro que voc poder ser supreendido com um resultado: prdio
no cho !!! (os engenheiros que me perdoe)

sqrt

Retorna a raiz quadrada de um nmero.

public static double sqrt(double a)

System.out.println(Math.sqrt(9)); // Resultado: 3

Como voc um cara esperto, deve estar se perguntando: "E se tentar passar um nmero
negativo para obter a raiz quadrada ? " - aahah, eu sabia que voc questionaria isso. Como
todos sabem, pelo menos uma grande maioria, t bom, algumas pessoas, ou melhor um grupo
bem seleto, ufa!, sabe que no existe raiz quadrada de um nmero negativo, portanto se voc
passar -9 para esse mtodo, voc obter um resultado NaN (Not a Number - ou No um
nmero).

toDegrees

Retorna um valor de um ngulo em graus, para isso voc deve passar um ngulo em radiano.

public static double toDegrees(double a)

Math.toDegrees(Math.PI * 2.0) // Retorna: 360.0

toRadians

Retorna em radiano um ngulo informado em graus.

public static double toRadians(double a)

Exemplo:

Calculando o seno de um ngulo

System.out.println("O seno de 90\" : "+Math.sin(Math.toRadians(90.0))); // Resultado: 1.0

Note que usamos dois mtodos encadeados para que o clculo fosse realizado, visto que o
mtodo sin recebe um valor em radiano e por isso usamos o mtodo toRadians para converter
90.0 (em graus) para radiano.

Algumas observaes sobre a classe Math

double x;

float p_i = Float.POSITIVE_INFINITY;

double n_i = Double.NEGATIVE_INFINITY;

double n_a_n = Double.NaN;

if ( n_a_n != n_a_n) System.out.println("NaN diferente de NaN");
// Ser ecoada, pois NaN no igual a nada inclusive a NaN

if (Double.isNaN(n_a_n)) System.out.println(" um NaN");
// resultado: um NaN

x = Math.sqrt(n_i);
// Alerta geral ! ser atribudo NaN para x

if (Double.isNaN(x)) System.out.println( "x um NaN");
// Resultado: x um NaN

System.out.println( 32 / 0 );
// Resultado: java.lang.ArithmeticException

System.out.println( 32.0 / 0.0 );
// Resultado: Infinity

System.out.println( -32.0 / 0.0 );
// Resultado: -Infinity

System.out.println( 32.0 / -0.0 );
// Resultado: -Infinity

System.out.println( -32.0 / -0 );
// Resultado: -Infinity

System.out.println( 32.0 / -0 );
// Resultado: Infinity

System.out.println( -32.0 / -0.0 );
// Resultado: Infinity (ops! jogo de sinal, vamos entender isso mais abaixo)

bom ressaltar uma regra ou melhor exceo quando envolvemos nmeros ponto-flutuante em
Java.

3) Dado o cdigo, o que acontecer ?

1. 1. public class Test {
2. 2. public static void main(String[] args) {
3. 3. System.out.println( " -32.0 / -0.0 -> " + -32.0 / -0.0 );
4. 4. System.out.println( " -32.0 / 0.0 -> " + -32.0 / 0.0 );
5. 5. System.out.println( " 32.0 / 0.0 -> " + 32.0 / 0.0 );
6. 6. System.out.println( " 32.0 / -0.0 -> " + 32.0 / -0.0 );
7. 7. System.out.println( " -32 / -0.0 -> " + -32 / -0.0 );
8. 8. System.out.println( " 32 / -0.0 -> " + 32 / -0.0 );
9. 9. System.out.println( " -32 / 0.0 -> " + -32 / 0.0 );
10. 10. System.out.println( " 32 / 0.0 -> " + 32 / 0.0 );
11. 11. System.out.println( " -32.0 / 0 -> " + -32.0 / 0 );
12. 12. System.out.println( " -32.0 / -0 -> " + -32.0 / -0 );
13. 13. System.out.println( " 32.0 / 0 -> " + 32.0 / 0 );
14. 14. System.out.println( " 32.0 / -0 -> " + 32.0 / -0 );
15. 15. System.out.println( " -32 / -0 -> " + -32 / -0 );
16. 16. System.out.println( " -32 / 0 -> " + -32 / 0 );
17. 17. System.out.println( " 32 / -0 -> " + 32 / -0 );
18. 18. System.out.println( " 32 / 0 -> " + 32 / 0 );
19. 19. System.out.println( "" );
20. 20. }
21. 21. }


a) Erro de compilao
b) java.lang.ArithmeticException na linha 17
c) Mostrar os valores fazendo jogo de sinal para as divises
d) Erro de compilao na linha 19
e) java.lang.ArithmeticException na linha 15

[color=green:430f7a8ef7]Resposta no final do captulo !!![/color:430f7a8ef7]

Entendendo como Java trata a diviso por 0 (zero)

Para ajudar entender as regras abaixos, voc precisar saber que:

|
86 |__2__
43
0

Onde:

86 o divisor
2 o dividendo
43 o quociente
0 o resto

Peo desculpas aos que j conhecem essa antiga conveno. ": )"
Maiores informaes visite o site:
http://educar.sc.usp.br/matematica/m4p1t6.htm

Continuando...

Quando o divisor e o dividendo forem nmeros inteiros:

Se o divisor for 0, ser lanada uma exceo.

1. System.out.println( 32 / 0 ); // exceo
2. System.out.println( -32 / -0 ); // exceo


Quando a operao envolver pelo menor um nmero ponto flutuante:

Quando o divisor for 0:

NUNCA HAVER A TROCA DE SINAIS, SEMPRE SER MANTIDO O SINAL DO
DIVIDENDO

1. System.out.println( 32.0 / 0 ); // resultado: INFINITY
2. System.out.println( -32.0 / 0 ); // resultado: -INFINITY
3. System.out.println( 32.0 / -0 ); // resultado: INFINITY
4. System.out.println( -32.0 / -0 ); // resultado: -INFINITY


Quando o divisor 0.0 ou maior:

SEMPRE HAVER A TROCA DE SINAIS

1. System.out.println( 32.0 / 0.0 ); // resultado: INFINITY
2. System.out.println( -32.0 / 0.0 ); // resultado: -INFINITY
3. System.out.println( 32.0 / -0.0 ); // resultado: -INFINITY
4. System.out.println( -32.0 / -0.0 ); // resultado: INFINITY
5. System.out.println( 32 / 0.0 ); // resultado: INFINITY
6. System.out.println( -32 / 0.0 ); // resultado: -INFINITY
7. System.out.println( 32 / -0.0 ); // resultado: -INFINITY
8. System.out.println( -32 / -0.0 ); // resultado: INFINITY
9. System.out.println( -32.0 / -1 ); // resultado: 32.0
10. System.out.println( -32.0 / 1 ); // resultado: -32.0
11. System.out.println( 32.0 / -1 ); // resultado: 32.0
12. System.out.println( 32 / -1 ); // resultado: -32
13. System.out.println( -32 / 1 ); // resultado: -32
14. System.out.println( 32 / 1 ); // resultado: 32


Relembrando...

Voc pode ser pego de surpresa durante o exame quando se deparar com questes envolvendo
operaes matemticas e tipos primitivos, porm para vencermos os crpulas do exame, vamos
entender algumas regrinhas:

1) Regra geral: J foi discutido no captulo 3 mas vale a pena relembrar, toda operao
envolvendo numeros inteiro SEMPRE retornar um tipo int.

Vejamos:

1. public class Test {
2. public static void main(String[] args) {
3. byte b = 127; // tamanho 8 bits
4. short s = 127; // tamanho 16 bits
5. short x = s * b; // deveria funcionar, mas d erro de compilao
6. System.out.println(x);
7. }
8. }


Se tentarmos compilar o programa anterior receberamos um insulto por parte do compilador,
pois como j dissemos, todo resultado de uma operao entre tipos inteiros SEMPRE resultar
em int e um tipo short no pode suportar um int sem converso explcita.

1. public class Test {
2. public static void main(String[] args) {
3. byte b = 127; // tamanho 8 bits
4. short s = 127; // tamanho 16 bits
5. short x = (short)s * b; // deveria funcionar, mas tambm d erro de co
mpilao
6. System.out.println(x);
7. }
8. }


Esse cdigo no funcionar, pode confirmar, pois o compilador no consegue saber os valores
das variveis em tempo de compilao e com isso, no pode efetuar a converso explcita !
Vale tambm ressaltar que se a varivel x fosse long, o cdigo seria compilado, pois um tipo int
pode perfeitamente ser atribudos uma varivel do tipo long.

6.4 - Usando as classes Wrappers

As classes wrappers tem o papel de encapsular os tipos primitivos para a possibilidade de
operaes como: converses, mudana de bases decimais, e algumas operao que somente a
objetos permitido, como por exemplo, trabalhar com conjuntos (que ser abordado no
captulo seguinte).

Todo tipo primitivo tem uma classe wrapper correpondente, vejamos:

tipo primitivo classe wrapper

byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean

Note que os nomes das classes wrapper tem o mesmo nome dos tipos primitivos, a exceo de
Integer e Character, e isso no teve nenhuma graa por parte dos desenvolvedores.

Para criar um objeto podemos fazer da seguinte forma:

1. Integer a = new Integer("10");
2. Integer b = new Integer(10);


Note que as classes tem os construtores sobrecarregados, ou seja, aceitam o valor String e o
valor int no caso anterior, vejamos outro exemplo:

1. Float f1 = new Float("14.0f");
2. Float f2 = new Float(14.0f);
3. Boolean b1 = new Boolean("TRUE");
4. Boolean b2 = new Bolean(true)


No caso da classe Boolean, voc poder instanciar um objeto passando uma string TRUE ou
FALSE, independente se estas forem maisculas ou minsculas.

6.4.1 - mtodos importantes

valueOf()
xxxValue()
parseXxx()

Os mtodos acima devem ser compreendidos para o sucesso nas respostas sobre as classes
Wrappers.

6.4.1.1 - o mtodo valueOf()

um mtodo esttico que quase todas classes wrapper tem que retorna o objeto wrapper a
classe relacionada. Esse mtodo tem uma funcionalidade muito interessante, pois pode
converter nmeros em bases diferentes, vejamos:

1. Integer i1 = Integer.valueOf("89");


Retorna um objeto Integer na base decimal.

1. Integer i2 = Integer.valueOf("89",2);


Tentativa de retornar um objeto Integer, porm nesse caso foi especificado a base 2 (binrio)
como "89" nunca foi e nunca ser um nmero binrio, essa linha gerar um exceo
java.lang.NumberFormatException.

No pense em usar:

1. Float.valueOf("89.0",2) ou
2. Double.valueOf("89.0",2)


que voc ter um erro de compilao, pois as classes Float e Double no tem esse mtodo com
essa assinatura.

1. Float f1 = Float.valueOf("10f");
2. Float f2 = Float.valueOf("10.0f");


Porm as linhas acima seriam compiladas sem nenhum problema.

NO ESQUEA: No pense que esse mtodo sobrecarregado como os construtores
permitindo que voc passe o tipo primitivo diretamente:

Float f1 = Float.valueOf(10f);

Isso seria repulsivo ao compilador.


6.4.1.2 - o mtodo xxxValue()

Assinatura do mtodo:

1. public int intValue()
2. public byte byteValue()
3. public short shortValue()
4. public long longValue()
5. public float floatValue()
6. public double doubleValue()


Observe que no so mtodos estticos.

Esse mtodo tem a funo de realizar converses dentro das classes wrapper, pois como
dissemos uma caracterstica dessas classes:

1. public class TestWrappers {
2. public static void main(String[] args) {
3. Float w = Float.valueOf("89f");
4. int i = w.intValue();
5. System.out.println(w.toString());
6. System.out.println(i);
7. }
8. }


O programa acima est fazendo uma converso do valor que o objeto w est armazenando e
convertendo para o tipo primitivo int. Poderamos converter para qualquer outro, vejamos:

1. byte b = w.byteValue();
2. short s = w.shortValue();


6.4.1.3 - o mtodo esttico parseXxx()

Outra forma de se converter usando os mtodos parses, vejamos um exemplo bem simples
para entender como isso funciona:

Imaginemos que voc no precise criar um objeto wrapper necessariamente para realizar uma
converso, voc pode usar o mtodo parseXxx para realizar tal tarefa:

int i = Integer.parseInt("10");

A string passada como parmetro deve corresponder a um tipo primitivo int, seno uma
exceo ser lanada como podemos observar no exemplo a seguir:

int i = Integer.parseInt("10f");

Nesse caso uma exceo ser lanada: java.lang.NumberFormatException


6.4.1.4 - o mtodo toString()

O mtodo toString() tem uma funcionalidade semelhante as vistas at aqui. E alem do mais as
classes Wrapper tem um mtodo esttico toString() sobrecarregado, ou seja, se voc precisar
transformar uma varivel int em String, voc pode usar:

int i = 10;

1. Opo 1:
2. String s = ""+ i;
3.
4. Opo 2:
5. String s = new Integer(i).toString();
6.
7. Opo 3:
8. String s = Integer.toString(i);


Voc concordar comigo que a opo 3 a mais elegante, visto que no cria nenhum objeto na
memrio, e a opo 1 no vou nem me estressar em definir aquilo. (mas acreditem eu j usei!)

Voc tambm poder chamar o mtodo toString do objeto:

1. Float f = Float.valueOf("10.0");
2. System.out.println(f.toString());


6.4.1.5 - convertendo bases com toString()

As classes Integer e Long tem dois mtodos estticos que podem ser usados para realizar
converso de bases decimais, vejamos:

Classe Integer:
public static String toString(int i, int radix)

Classe Long:
public static String toString(long i, int radix)

Voc poder realizar converses entre bases da seguinte forma:

1. String s1 = Integer.toString(256,16);
2. String s2 = Integer.toString(256,2);


O cdigo acima retorna para a variveis s1 e s2, o valores correspondentes a 256 em
Hexa (base 16) e em Binrio (Base 2).

Para encerrarmos esse estudo, ainda temos os mtodos estticos nomeados:

Classe Integer:
public static String toHexString(int i)
public static String toBinaryString(int i)
public static String toOctalString(int i)

Classe Long:
public static String toHexString(long i)
public static String toBinaryString(long i)
public static String toOctalString(long i)

Exemplo de uso:

String s1 = Integer.toHexString(123);

O cdigo acima transforma o inteiro 123 em Hexadecimal.

Mtodos que lanam a exceo NumberFormatException

- Todos os contrutores das classes wrapper numricas
- os mtodos estticos valueOf
- os mtodos estticos toString de Integer e Long
- os mtodos parseXxx

Bom chegamos ao final de mais um captulo !!


Respostas dos exerccios propostos:

1) c

2) e

3) e

Cap. 7 - Objetos e conjuntos
Captulo 7 - Objetos e conjuntos

7.1 - o mtodo equals

Esse mtodo definido na classe Object, portanto toda classe o ter por herana. Sua
assinatura :

public boolean equals(Object o)

Qualquer tentativa de substituio desse mtodo escrita de forma diferente, no ser
evidentemente uma substituio e sim uma sobrecarga de mtodo. Voc deve prestar bastante
ateno nesses conceitos que agora sero explicados, pois so fundamentais para absoro e
compreenso desse captulo. Voc j deve saber que o mtodo equals pode funcionar de forma
diferente em cada classe, e isso vai depender de como ele foi definido, por exemplo, nas
classes Wrappers, possvel saber se um valor 5 inteiro que est armazenado em um objeto x
igual a um objeto y que tambm armazena o valor 5 (desde que sejam da mesma classe
como Integer), isso devido ao fato de que o mtodo equals foi substitudo nas classes
Wrappers, fazendo com que retorne true quando o valor armazenado pelas classes Wrappers
forem idnticos, a exceo claro, se o tipo for diferente. Vejamos:

1. Integer i = new Integer("5");
2. Long l = new Long("5");
3. if ( i.equals(l)) System.out.println("igual");
4. else System.out.println("diferente");


// Resultado: diferente

Agora quando comparamos instncias distintos de duas classes iguais:

1. Integer i = new Integer("5");
2. Integer j = new Integer("5");
3. if ( i.equals(l)) System.out.println("igual");
4. else System.out.println("diferente");


// Resultado: igual

Apesar de serem objetos distintos, tem o mesmo valor.

Se usarmos o operador ==

1. Integer i = new Integer("5");
2. Integer j = new Integer("5");
3. if (i == j) System.out.println("igual");
4. else System.out.println("diferente");


// Resultado: diferente

Apesar dos valores serem identicos, o resultado do teste (==) falso, pois esse testa se os
objetos apontam para o mesmo objeto na memria.

Quando substituir o mtodo equals ?

Para iniciarmos essa discusso, precisamos saber que o mtodo equals na classe Object
funciona da mesma forma como o operador ==, portanto quando no substitumos o mtodo
equals em uma classe o retorno s ser true quando ambos objetos apontarem para o mesmo
objeto na memria, vejamos:

1. class Flamengo {
2. public static void main(String[] args) {
3. Flamengo penta = new Flamengo();
4. Flamengo melhor = new Flamengo();
5. Flamengo temp = penta;
6. int i = 0;
7. if (penta.equals(melhor)) ++i;
8. if (melhor.equals(penta)) ++i;
9. if (temp.equals(penta)) ++i;
10. if (temp.equals(melhor)) ++i;
11. System.out.print(i);
12. }
13. }


// Resultado: 1

Note que somente uma vez a condio satisfeita, no caso em que temp == penta !

Como a Java lhe d os poderes do mundo, voc pode alterar esse comportamento. Como ?
Mudando a JVM ? No ! s substituir o mtodo equals na classe (tira o calado para falar esse
nome) Flamengo, mas para isso preciso saber quando e porque mudar o mtodo equals !
Essa uma deciso que deve ser tomada medindo todas as consequncias. Voc deve primeiro
responder uma pergunta bsica para saber se precisar ou no mudar o mtodo equals.
Pergunte se preciso em alguma situao identificar dois objetos distintos como iguais. Ficou
confuso, calma, calma ! Voce tem dois objetos A e B, e adiciona os mesmos em um conjunto
(estudaremos conjuntos mas afrente) agora voc precisa realizar uma pesquisa afim de saber
se o objeto C est no conjunto - pressuponha que os atributos de C e B so semelhantes, se o
mtodos equals da classe dos objetos citados no for modificado, voc nunca obter true na
condio B.equals(C), mesmo sendo classes iguais por sua semntica.
Ento a deciso de mudar o mtodo equals de uma classe est intimamente relacionada com a
necessidade de em uma pesquisa se saber se um objeto est na lista pesquisa ou no.


Entendendo o uso de hashCode

Outro conceito que precisamos entender agora , onde a utilizao do cdigo hash influncia no
uso de conjuntos ? No se preocupe, apesar de parecer estranho um conceito fcil de se
entender.
Vamos imaginar uma sala com inmeras caixas postais, o PAULO tem uma caixa com nmero
385, a ANA tem uma com o nmero 208, PEDRO usa a de nmero 378 e assim por diante.
Toda vez que chega uma correpondncia (do PAULO por exemplo), sabe-se qual o nmero da
caixa postal atravz de um clculo em funo do seu nome, por exemplo, a soma dos cdigos
ASCII como podemos observar a seguir:

P -> 80
A -> 65
U -> 85
L -> 76
O -> 79

HASH -> 385

No tire sarro desse clculo, esse exemplo de cdigo hash apropriado porm ineficiente (a
quem diga absurdo) e isso veremos mais tarde. Com esse clculo foi possvel obter o nmero
da caixa postal do PAULO. Agora vamos analisar como ficaria a pesquisa, ou seja, quando o
PAULO chegar na empresa de correspondncia e quiser saber se existe alguma correspondncia
para ele, o atendente perguntaria seu nome e faria o mesmo clculo para descobrir qual o
nmero da caixa postal, obtendo o nmero 297, assim o atendente se reportaria cx no. 297 e
recuperaria todas as suas correspondncias. Esse processo muito indicado quando se deseja
extrema velocidade no processo de pesquisa. Se voc um cara esperto j deve ter notado um
"erro" em nosso algoritmo de clculo do cdigo hash, pois seguindo esse clculo qual seria o
nmero da caixa postal para a IVONE. aha com certeza o PAULO pegaria as correspondncias
da IVONE e vice-versa ! NO ! No pense assim, o processo de pesquisa usando cdigo hash
um processo em duas fases, a primeira saber em qual depsito se encontra as informaes,
ou seja, em qual caixa postal est as correspondncias, a segunda verificar cada item da
caixa postal comparando para saber se um item da pessoa desejada. O que no pode
acontecer criar um algoritmo que coloque todas as correspondncias em um ou dois
depsitos (caixa postal) assim o seu processo de pesquisa ficaria ineficiente, ruim, ridculo,
absurdo! Mas correto ! MAS LENTO !
Talvez o exemplo de correpondncia no foi muito convincente, visto que uma caixa postal
um depsito de correpondncias de uma nica pessoa, mas como a empresa de correpondcia
nossa, e os clientes no tem chave, convencionamos dessa forma - s quem pega as
correpondncias um funcionrio da empresa.
Imagine que nosso algoritmo fosse contar as letras do nome para saber o nmero da caixa
postal, a seguinte lista mostraria a baguna que ficaria:

NOME DEPOSITO (CP)

JOAO 4
ANA 3
PEDRO 5
AMY 3
MARIA 5
JOSE 4
ENIO 4
JOAQUIM 7
CAIO 4

Note que cada nome com 4 (quatro) dgitos o nmero da caixa postal ser o mesmo, ficaria
uma baguna, o processo de busca seria muito lento, portanto, quando for criar um algoritmo
de clculo para cdigo hash (espalhamento), faa-o de forma inteligente, usando nmeros
complexos, matrizes, limites, derivadas e funes !!! S para termos uma idia, clulos de hash
do assunto para teses de doutorado (isso eh li no livro) !


Mtodo equals versus hashCode

Voc j deve ter notado a relao entre os mtodos equals e hashCode, pois em uma pesquisa,
voc precisar verificar na segunda fase se um objeto X igual a um item do conjunto - que
nada mais que um objeto Y. Se voc no substituir o mtodos equals voc no ter essa
possibilidade, visto que o mtodo equals da classe Object retorna true se ambos os objetos
apontarem (ops! isso no C) referenciarem o mesmo objeto na memria. Memorize isso: para
se utilizar uma classe em um conjunto, ela deve ter o mtodo equals substitudo.

Contratos do mtodo equals

1) Reflexivo - Para qualquer valor, x.equals() sempre ser true;

2) Simtrico - Para qualquer valor de x e y, x.equals(y) true, se e somente se y.equals(x)
tambem for.

3) Transitivo - Para qualquer valor de x, y e z, se x.equals(y) for verdadeiro e y.equals(z)
tambem for, ento x.equals(z) tambem ser verdadeiro.

4) Consistente - Todas as chamadas para x.equals(y) retornar consistentemente true ou false,
at que haja uma mudana em algum dos objetos, caso contrrio o resultado ser sempre o
mesmo.

5) Se x referenciar algum objeto, ento x.equals(null) dever retornar falso. Obviamente que
uma tentativa de chamar um mtodo equals para um objeto null, lancar um exceo.


Contrato do mtodo hashCode

1) Sempre que um mtodo hashCode for chamado, ele dever resultar no mesmo cdigo hash
consistentemente (caso nenhum valor usado nas comparaes for alterado).

2) Se dois objetos forem iguais, considerados pela chamada ao mtodos equals, portanto o
cdigo hash dever ser o mesmo para ambos os objetos.

3) No obrigado que dado dois objetos distintos, tenham cdigos hash distintos.

4) No aconselhvel usar atributos transients no clculo do cdigo hash, visto que aps o
processo de deserializao, o mtodo equals poder produzir um resultado diferente de quando
o objeto foi serializado, portanto uma situao perigosa.

Esse contratos devem ser respeitados pois voc poder alterar (substituir) o mtodo equals,
portanto siga sempre essas leis.

Substituindo os mtodos equals e hashCode

1. public class Pessoa {
2.
3. private String CPF;
4.
5. public int hashCode() {
6. return 5;
7. }
8.
9. public boolean equals(Object o) {
10. if (o instanceof Pessoa) || (o.CPF == this.CPF) return true;
11. else return false;
12. }
13.
14. }


7.2 - Coleo de Dados

O uso de coleo de dados uma necessidade quando precisamos de trabalhar com dados. J
vimos como comparar objetos afim de saber se so equivalentes ou no, agora vamos entender
seus repositrios e como funcionam.
Existem classes e interfaces que precisaremos entender, se listassmos aqui, j ficaria muito
nebuloso, por isso vamos por parte. Podemos dividor os conjuntos em trs categorias:

Listas
Conjuntos
Mapas

Vejamos a hierarquia dessas classes/interfaces:



7.2.1 - Ordem e classificao

Nesse primeiro instante, precisamos entender dois conceitos fundamentais nas colees, que
so: ordem e classificao de conjuntos. Abaixo podemos vislumbrar uma definio completa
desses conceitos:

ordenada - Uma classe ordenada se pode ser iterada pelos seus elementos em uma ordem
especfica, atravs de um ndice ou por exemplo pela ordem de insero.

classificada - Uma classe classificada, quando seus elementos esto classificados por algum
critrio, como por exemplo, em ordem alfabtica, crescente ou cronolgica etc. Toda classe
classificada ordenada, j uma classe ordenada pode no ser classificada.

7.2.2 - List

As classes que implementam a interface List, relevam o ndice, com isso podemos inserir um
item no meio de uma lista. Como voc j deve ter percebido, as classes que implementam a
interface List so ordenadas por meio de um ndice, isso permite o acesso a um elemento que
se encontra no meio da lista, atravs de seu ndice. uma espcie de sequncia para
armazenamento de objetos.

ArrayList- um estrutura de dados que tem com base um array. isso mesmo! Um ArrayList
nada mais que um array que pode ser alterado. Sua estrutura interna (pode conferir)
baseada em um Array com um tamanho inicial e deve ser especificado na criao do objeto - se
nenhum valor for especificado a classe assumir 10 (sei l porqu). Com isso possvel tem
uma ordem em ArrayList, pois o ndice o identifica os elementos. Vejamos suas principais
caractersticas:

- Acesso sequencial / aleatrio extremamente rpido.

- Em funo do ndice o acesso a um elemento no meio da lista uma operao extremamente
rpida, como j sabemos o mesmo que recuperar um item de um vetor.

- Insero tambm extremamente rpida

- Vale uma ressalva nessa situao, visto que uma ArrayList cresce a medida que os itens vo
sendo inseridos:

Exemplo:

1. import java.util.*;
2.
3. public class TestList {
4. public static void main(String[] args) {
5. long inicio, fim;
6. int n = 3000000;
7. inicio = System.currentTimeMillis();
8. ArrayList array = new ArrayList();
9. for (int i = 0; i < n; i++) {
10. array.add(new Integer(i));
11. }
12. fim = System.currentTimeMillis();
13. System.out.println( "Tempo inserir: " + (fim - inicio)/1000.000 );
14. inicio = System.currentTimeMillis();
15. Iterator o = array.iterator();
16. while (o.hasNext()) {
17. Integer x = (Integer)o.next();
18. }
19. fim = System.currentTimeMillis();
20. System.out.println( "Tempo iterar: " + (fim - inicio)/1000.000 );
21. }
22. }


Resultado do programa acima:

Tempo inserir: 2.563
Tempo iterar: 0.172

Note que houve uma demora relativamente maior no processo de insero, porm observe que
foram inseridos trs milhes de objetos que foram inseridos - acredito que o tempo consumido
nos dois processos foi muito bem aproveitado pela classe.
A classe ArrayList tem um construtor sobrecarregado que recebe um argumento onde pode-se
definir a capacidade da estrutura, ou seja, se for especificado 1000, a classe ir reservar 1000
endereos nulos para o preenchimento dos dados, isso evita a realocao constante de seu
array.

Vector- Tem as mesmas caractersticas de ArrayList, porm seus mtodos so sincronizados.
Se aplicarmos o mesmo teste anterior notaremos uma diferena na insero, vejamos:

1. import java.util.*;
2.
3. public class TestVector {
4. public static void main(String[] args) {
5. long inicio, fim;
6. int n = 60000;
7. int j = 0;
8.
9. inicio = System.currentTimeMillis();
10. Vector array = new Vector(0,1);
11. for (int i = 0; i < n; i++) {
12. array.add(new Integer(i));
13. }
14. fim = System.currentTimeMillis();
15. System.out.println( "Tempo inserir: " + (fim - inicio)/1000.000 );
16.
17. inicio = System.currentTimeMillis();
18. Iterator o = array.iterator();
19. while (o.hasNext()) {
20. Integer x = (Integer)o.next();
21. j++;
22. }
23. fim = System.currentTimeMillis();
24. System.out.println( "Tempo iterar: " + (fim - inicio)/1000.000 );
25. }
26. }



Resultado do programa acima:

Tempo inserir: 109.938
Tempo iterar: 0.015

Observe que o tempo de insero foi extremamente superior ao de ArrayList mesmo com uma
quantidade 50 vezes inferior, portanto a insero usando a classe Vector muito lenta, voc
provavelmente nunca precisar us-la, visto que sua nica diferena em relao classe
ArrayList que seus mtodos so sincronizados, e esse recurso voc pode conseguir se utilizar
mtodos estticos da classe java.util.Colletions.
S pra no ficar nenhuma dvida, se o mesmo programa sobre a classe Vector fosse
especificado 3 milhes com em ArrayList, seria necessrio um tempo equivalente a 50 *
109.938 = 5496,9 s o que equivalente a 91,615 minutos.

LinkedList- A diferena entre LinkedList e ArrayList que os elementos de LinkedList so
duplamente encadeados entre si. Isso essencial quando se deseja implementar uma fila ou
pilha. Por causa da duplicidade de encadeamente, possvel por exemplo inserir no final da
lista, no incio sem a necessidade da realocao do array, visto que cada n tem uma referncia
para seu sucessor e seu predecessor, logicamente que isso faz com que o processo de insero
seja um pouco mais lento, pois a cada objeto inserido registrado o "endereo dos vizinhos"
consequentemente uma lista duplamente encadeada bem maior que uma lista simples,
vejamos:

1. import java.util.*;
2.
3. public class TestVector {
4. public static void main(String[] args) {
5. long inicio, fim, j;
6. j = 0;
7. inicio = System.currentTimeMillis();
8. LinkedList array = new LinkedList();
9. for (int i = 0; i < 1500000; i++) {
10. array.add(new Integer(i));
11. }
12. fim = System.currentTimeMillis();
13. System.out.println( "Tempo inserir: " + (fim - inicio)/1000.000 );
14. inicio = System.currentTimeMillis();
15. Iterator o = array.iterator();
16. while (o.hasNext()) {
17. Integer x = (Integer)o.next();
18. j++;
19. }
20. fim = System.currentTimeMillis();
21. System.out.println( "Tempo iterar: " + (fim - inicio)/1000.000 );
22.
23. }
24. }


Resultado:

Tempo inserir: 2.485
Tempo iterar: 0.109

Note que a metade dos itens do primeiro exemplo foi inserido e no entando o tempo gasto foi
praticamente o dobro.

Resumindo as listas- O que precisamos saber que o ndice em uma lista relevante, toda
lista ordenada, ou seja, podemos iterar em uma ordem especifica, seja ela pela ordem de
insero ou pela ordem do ndice. A no se esquea que no existe lista classificada !

7.2.3 - Set

Voltemos a 5a. srie do ensino mdio:

A = { 0, 1, 2 }
B = ( 1, 2, 3 }
A U B = { 0, 1, 2, 3 }

Note que os elementos repetidos {1,2} foram suprimidos de um dos conjuntos para no haver
repetio. Isso voc j deveria saber, pois deve ter estudado no incio do ensino mdio. Bom o
que precisamos saber agora que toda classe que implementa a interface Set: NO ACEITA
DUPLICATAS !!! Esse conceito fundamental para entendermos as classes Sets !

Como tocamos em um assunto essencial, vejamos como a classe funciona:

X -> Testa o mtodo equals
Y -> Pega o cdigo hash

Se X ou Y for falso o objeto inserido.

Vejamos um caso que sempre ser inserido: Se o mtodo equals no for substitudo todos os
elementos sero inseridos, a menos que voc tente inserir o mesmo objeto duas vezes,
vejamos:


1. public class Test {
2. public static void main(String[] args) {
3. HashSet conjunto = new HashSet();
4. A x, y, z;
5. x = new A();
6. y = new A();
7. x.a = 10;
8. y.a = 20;
9. z = x;
10. conjunto.add(x);
11. conjunto.add(y);
12. conjunto.add(z);
13. }
14. }
15.
16. class A {
17. int a = 0;
18. }


A pergunta : Quantos objetos eu tenho nesse conjunto ??? Acertou se voc respondeu dois,
vamos tentar entender: note que s existem dois objetos distintos: x e y o z uma referncia a
x, portanto, quando o mtodo add foi chamado para o caso de z foi calculado o cdigo hash
(digamos que deu 7621), a segunda questo que a classe faz saber se existe algum objeto no
depsito 7621 que seja igual a z, como sabemos (j estudamos isso) que o cdigo hash de dois
objetos igual sempre ser o mesmo, nesse caso x e z, podemos pressupor que o objeto x est
tambm no depsito 7621, consequentemente o mtodo equals deve (pelo menos o que
esperamos) retornar true, portanto o objeto z no ser inserido no conjunto. Talvez voc esteja
rindo desse exemplo, mais vamos complicar um pouco:

1. import java.util.*;
2.
3. public class Teste {
4. public static void main(String[] args) {
5. HashSet conjunto = new HashSet();
6. A x, y, z;
7. x = new A();
8. y = new A();
9. z = new A();
10. x.a = 10;
11. y.a = 20;
12. z.a = 10;
13. conjunto.add(x);
14. conjunto.add(y);
15. conjunto.add(z);
16. }
17. }
18.
19. class A {
20. int a = 0;
21.
22. public int hashCode() {
23. return 10;
24. }
25. }


Note que nesse caso, substitumos o mtodo hashCode, apesar de ser uma substituio ridcula,
ela funciona. Seguindo o mesmo raciocnio do exemplo anterior, quantos elementos foram
inseridos ? Tentamos entender: cada vez que o mtodo add chamado, a classe HashSet
chama o mtodo hashCode para tentar encontrar um objeto equivalente, bom nesse caso, o
hashCode est retornando 10, com isso podemos saber o endereo de um possvel elemento j
inserido, porm o mtodo equals que prevalece nesse caso o da classe Object (que voc deve
lembrar - retorna true se ambas as referncias forem para os mesmos objetos) e o mtodo
equals nesse caso ir retornar false, com isso mesmo que se tenha a inteno de serem
semelhantes os objetos x e z no o so, visto que para isso ser necessrio substituir tambem o
mtodo equals, vejamos no prximo exemplo:

1. import java.util.*;
2.
3. public class Teste {
4. public static void main(String[] args) {
5. HashSet conjunto = new HashSet();
6. A x, y, z;
7. x = new A();
8. y = new A();
9. z = new A();
10. x.a = 10;
11. y.a = 20;
12. z.a = 10;
13. conjunto.add(x);
14. conjunto.add(y);
15. conjunto.add(z);
16. Iterator o = conjunto.iterator();
17. while (o.hasNext()) {
18. A azinho = (A)o.next();
19. System.out.println( azinho.a );
20. }
21.
22. }
23. }
24.
25. class A {
26. int a = 0;
27.
28. public int hashCode() {
29. return 10;
30. }
31.
32. public boolean equals(Object o) {
33. boolean rc = false;
34. if (o == null) {
35. rc = false;
36. }
37. else {
38. if ((o instanceof A) && ((A)o).a == this.a) {
39. rc = true;
40. }
41. }
42. return rc;
43. }
44. }


Resultado:

20
10

Nesse caso, alteramos a classe A e determinar que quando o membro a tiver o mesmo valor
ser considerada igual (semelhantes as classes Wrappers) - por isso que nesse caso foram
inseridos somente dois objetos no conjunto.

Bom agora que acreditamos que ficou claro essa questo da unicidade dos elementos nas
classes Sets, vejamos suas implementaes usadas.

HashSet- um conjunto no-ordenado e no-classificado, utiliza o cdigo hash do elemento
que est sendo inserido para saber em qual depsito deve armazenar, com isso podemos notar
que um clculo de cdigo hash ineficiente a morte para a boa performance durante o
processo de insero/recuperao. Nunca use essa classe quando precisar de uma ordem na
iterao.

LinkedHashSet- um conjunto ordenado e duplamente encadeado, com isso podemos iterar
pelos seus elementos em uma ordem, sempre use essa classe quando precisar de ordem na
iterao, porm saiba que um pouco mais lenta que HashSet na insero visto que leva mais
tempo para registrar os vizinhos (elemento posterior e inferior).

TreeSet- essa uma das duas classes do framework de coleo da api Java que classificada
e ordenada - essa classificao se d pela ordem natural da classe que est sendo inserida (isso
pode ser alterado mas foge do nosso escopo), vejamos algumas classificaes naturais para as
classes mais usadas:

Classe Ordem Natural

Byte signed numerical
Character unsigned numerical
Long signed numerical
Integer signed numerical
Short signed numerical
Double signed numerical
Float signed numerical
BigInteger signed numerical
BigDecimal signed numerical
File system-dependent lexicographic on pathname.
String lexicographic
Date chronological

7.2.4 - Map

As classes que implementam a interface Map tem funcionalidades distintas da aprendida at
aqui, vejamos porqu. Aprendemos que em uma lista o ndice relevante para se pesquisar ou
at mesmo inserir um objeto no meio no fim ou em qualquer posio da lista, j nas classes
Sets, a unicidade a caracterstica fundamental dessas classes sendo necessrio uma correta
relao dos mtodos equals e hashCode para seu funcionamento, j as classes Maps faz uma
mapeamento de chave X valor, ou seja, voc tem um objeto chave para um objeto valor.
Vejamos um exemplo de seu uso:

1. import java.util.*;
2.
3. public class TestMap {
4. public static void main(String[] args) {
5. HashMap map = new HashMap();
6. map.put( "um", new Integer(1) );
7. map.put( "dois", new Integer(2) );
8. map.put( "tres", new Integer(3) );
9. map.put( "quatro", new Integer(4) );
10. }
11. }


Note que um objeto (nesse caso String) mapeado para cada um valor do conjunto, portanto
nas classes Maps a unicidade da chave relevante, se voc tentar inserir um item como
podemos ver abaixo, voc no ter um novo item no conjunto pois a chave idntica, o valor
somente substitudo.

map.put( "dois", new Float(30.0f) );

Podemos concluir que a chave do conjunto Map um Objeto de uma classe Set, ou seja, a
chave deve ser nica, o processo para saber se a chave est no conjunto idntica ao processo
explicado nas classes Sets, com isso, uma boa implementao dos mtodos hashCode e
equals imprescindvel para a boa performance desse conjunto.

Vejamos isso na prtica:

1. import java.util.*;
2.
3. 1. public class TestMap {
4. 2. public static void main(String[] args) {
5. 3. HashMap map = new HashMap();
6. 4. map.put( "um", new Integer(1) );
7. 5. map.put( "dois", new Integer(2) );
8. 6. map.put( "tres", new Integer(3) );
9. 7. System.out.println( "Antes: "+map.size());
10. 8. map.put( "um", new Float(1f) );
11. 9. System.out.println( "Depois: "+map.size());
12. 10. }
13. 11. }


Resultado:

Antes: 3
Depois: 3

Note que mesmo adicionando um objeto diferente na linha 8, o resultado do tamanho do
conjunto no foi alterado. Fica subitamente entendido que se a classe usada na chave (nesse
caso String) no substituir os mtodos equals e hashCode, todo objeto ser adicionado no
conjunto, o que no faz muito sentido, portanto sempre utilize um objeto de uma classe onde
seus mtodos equals e hashCode tenham sido substitudos.

HashMap- um conjunto Map no-ordenado e no classificado. Permite a existncia de chave
e valores nulos. Vejamos um exemplo esdrxulo, porm funcional:

1. import java.util.*;
2.
3. public class TestMap {
4. public static void main(String[] args) {
5. HashMap map = new HashMap();
6. String um, dois;
7. um = null;
8. dois = null;
9. map.put( um, new Integer(1) );
10. map.put( dois, new Integer(2) );
11. System.out.println( "Tamanho: "+map.size());
12. }
13. }


O resultado ser: Tamanho 1

Hashtable- essa classe equivalente HashMap com a diferena que seus mtodos so
sincronizados, e, alm disso, no permite valores/chaves nulos.

1. import java.util.*;
2.
3. public class TestMap {
4. public static void main(String[] args) {
5. Hashtable map = new Hashtable();
6. String um = null;
7. String dois = null;
8. map.put( "um", um );
9. map.put( "dois", dois );
10. System.out.println( "Tamanho: "+map.size());
11. }
12. }


[color=red:7fc9c06e81]Erro: java.lang.NullPointerException at
java.util.Hashtable.put(Hashtable.java:386) at TestMap.main(TestMap.java: 8) Exception in
thread "main"[/color:7fc9c06e81]

S pra relaxar: Note que a nomeclatura de nomes da Java para essa classe foi esquecida, pois
o t em Hashtable deveria ser maisculo.

LinkedHashMap- uma verso ordenada (ordem de insero/acesso) da interface Map,
embora seja um pouco mais lento para insero e remoo, visto que deve sempre registrar
seus sucessor e predecessor, porm a iterao bem rpida, e, isso tudo por ser uma classe
duplamente encadeada.

TreeMap- a outra classe da Framework Collection Java que classificada e
consequentemente ordenada, vejamos uma aplicao dessa classe:

1. import java.util.*;
2. public class TestMap {
3. public static void main(String[] args) {
4. TreeMap map = new TreeMap();
5. long inicio, fim;
6. inicio = System.currentTimeMillis();
7. int n = 500000;
8. for (int i=0; i < n; i++) {
9. map.put( "um"+i, new Integer(i) );
10. }
11. fim = System.currentTimeMillis();
12. System.out.println( "Tempo inserir: " + (fim - inicio)/1000.000 );
13. }
14. }


Resultado: Tempo inserir: 3.937

Porm o resultado estaria em ordem (nesse caso lexicographic) pois se trata de uma classe
String.

Bom isso encerrado o estudo das classes de colees que a Framework Java nos oferece.

7.3 - Coleta de Lixo

A memria sempre foi o "calcanhar de aquiles" para as linguagens de programao. Uma
linguagem de programao se diz tipada, por poder definir tipos de dados, por exemplo, uma
varivel inteira/integer um tipo, cada linguagem de programao tem uma representao
para o tipo inteiro, em pascal um tipo inteiro corresponde a um interval que provavelmente no
equivale o mesmo intervalo em Java, e essas definies so essencialmente para o melhor
aproveitamento da memria, pois com a definio dos tipos podemos (os programas podem)
estimar o uso de memria, saber quanto um programa ou uma rotina vai usar, enfim a
memria um elemento essencial e primordial para o sucesso de qualquer programa, por isso
devemos saber aproveit-la.
O gerenciamento da memria no uma tarefa fcil, saber quando um objeto est pronto para
ser dilacerado (sempre quis usar essa palavra), anular uma referncia, re-referenciar um
objeto, sugerir a execuo do coletor de lixo, todos esses conceitos sero entendidos (pelo
menos o que esperamos) a partir de agora.

Como o coletor de lixo funciona

Voc poder encontrar dezenas de teorias de como o coletor funciona, mas no caia nessa,
pode ser que sim ou que no, ou sei l ! Mas vamos entender uma coisa: um programa Java
roda simultaneamente vrios processos ou vamos chamar segmentos (no gosto muito desse
nome, prefiro chamar thread), e um segmento pode estar ou no ativo, e um objeto est
pronto para ser extirpado quando nenhum segmento no pode alcanar esse objeto, simples
no ?
Voc pode dar uma mo para o coletor de lixo, porm no caia na idia de que pode cham-lo
quando bem entender, voc pode sugerir: hein t na hora da limpeza, mas no garantido que
ele venha. Portanto se voc se deparar com uma questo perguntando qual a maneira mais
precisa de se executar o coletor de lixo ? No hesite em marcar: IMPOSSVEL !!!

Anulando uma referncia:

1. 1. public class Test {
2. 2. public static void main(String[] args) {
3. 3. StringBuffer b = new StringBuffer("hello");
4. 4. System.out.println(b);
5. 5. b = null;
6. 6. } }


A partir da linha 5, o objeto b no referencia mais nada da memria, portanto o coletor pode
muito bem eliminar a String "hello" que dever estar ocupando lugar. Isso muito gentil por
parte dos programadores, anular uma referncia sempre que no venha mais precisar do
objeto.

Vejamos outro exemplo:

1. 1. public class Test {
2. 2. public static void main(String[] args) {
3. 3. StringBuffer sb1 = new StringBuffer("hello");
4. 4. StringBuffer sb2 = new StringBuffer("my friendy");
5. 5. System.out.println( sb1 );
6. 6. sb1 = sb2;
7. 7. }
8. 8. }


Aps a execuo da linha 6, a string "hello" ficar perdida na memria, estando disponvel para
o coletor de lixo executar o seu trabalho.

Objetos dentro de um mtodo

Todos os objetos criados localmente dentro de um mtodo estaro qualificados para a coleta
aps a execuo do mtodo. Vejamos um exemplo:

1. public void show() {
2. String s1 = "s1";
3. String s2 = "s2";
4. System.out.println(s1+s2);
5. }


Aps a execuo do mtodos acima, os dois objetos s1 e s2 estaro qualificados para a coleta,
agora vejamos um outro exemplo:

1. public String show() {
2. String s1 = "s1";
3. System.out.println(s1+s2);
4. return s1;
5. }


Note que o objeto s1 est sendo utilizado no retorno do mtodo, portanto esse objeto no pode
ser coletar, mesmo porque, ele ainda est sendo referenciado.

Isolando uma referncia

Vamos complicar um pouco as referncias para ver o que acontece com os objetos:

1. public class Test {
2. Test t;
3.
4. public static void main(String[] args) {
5. Test t2 = new Test();
6. Test t3 = new Test();
7. Test t4 = new Test();
8.
9. t2.t = t3;
10. t3.t = t4;
11. t4.t = t2;
12.
13. t2 = null;
14. t3 = null;
15. t4 = null;
16. }
17. }


O que achas que acontece nesse caso ?? Calma vamos entender:

Apenas trs objetos foram criados na memria: t2, t3, t4.

Quando os objetos t2, t3 e t4 foram anulados, tornaram-se qualificados para a coleta, mesmo
existindo outras referncias para esses objetos.

Sugerindo a coleta

1. import java.util.Date;
2. public class Memory {
3. public static void main(String[] args) {
4. Runtime rt = Runtime.getRuntime();
5. System.out.println("Memoria total: "+rt.totalMemory());
6. System.out.println("Memoria Antes: "+rt.freeMemory());
7. Date d = null;
8. for (int i=0; i < 5000; i++) {
9. d = new Date();
10. d = null;
11. }
12. System.out.println("Memoria Depois: "+rt.freeMemory());
13. rt.gc();
14. System.out.println("Memoria Final: "+rt.freeMemory());
15. }
16. }



Note que a linha rt.gc() simplesmente sugere, no garante que a coletar
efetivamente seja feita.

Bom depois dessa lixaiada, terminamos mais um captulo !! :!: :!: :!:

Cap. 8 - Classes internas
Captulo 8 - Classes internas

8.1 - Onde deve ser usada e para que serve ?

Antes de qualquer introduo esse assunto, vamos fazer uma explanao sobre as classes
internas, onde e quando devem ser usadas, visto que esse assunto um tanto contundente no
que se refere a reutilizao de cdigo, extensabilidade e escalabilidade de um cdigo sob o
tica da OO.

8.1.1 - Um exemplo oficial

Definir uma classe interna ou aninhada um recurso interessante adicionado na verso 1.1 da
Java, porm deve ser bem cauteloso o seu uso visto que se assim no o for, com certeza
teremos redundncia de cdigo, classes extremamente complicadas de ser entendidas e com
seu uso limitado, portanto saiba decidir seu uso. Vejamos um exemplo usado na prpria
framework de coleo Java, as classes Map herdam de uma superclasse chamada AbstractList,
para seu funcionamento ela usa um objeto de uma classe interna chamado Entry e seu escopo
est limitado classe AbstractList, com um funcionamento totalmente peculiar AbstractList,
no teria muito sentido, criar uma classe externa para Entry, visto que sua utilizao se limita
AbstractList. Definir classes especilialista um conhecimento extremamente necessrio no
tocante orientao a objeto e nesse caso a classe Entry nada mais do que um membro (pois
assim que tambm pode ser chamadas as classes internas) de AbstractList.

8.2 - As classes internas so divididas em:

- Classe esttica aninhada (top-level class)
- Classe interna comum
- Classe interna local de mtodo
- Classe interna annima


8.3 - Classes estticas

Entenderemos agora o que so as classes estticas que tambm podem ser chamadas como
classe de nvel superior ou top-level class, entretanto no fritar dos ovos tudo a mesma coisa.
Uma classe esttica no tem acesso aos membros da instncia da classe encapsulada, somente
os membros estticos, tem a mesma visibilidade de uma classe externa.

Modificadores que podem ser atribudos uma classe interna esttica:

static - obrigatrio claro
protected
public
private
abstract
final

* nunca abstract e final simultneamente claro!

1. public class Ex03 {
2. static int CountStatic = 0;
3. int CountNonStatic = 0;
4.
5. public static class Inner {
6. }
7. }


Voc NUNCA podera referencia o membro CountNonStatic dentro da classe Inner, uma vez que
esse membro no esttico. Isso geraria um erro de compilao como podemos observar a
seguir:

1. public class Ex03 {
2. static int CountStatic = 0;
3. int CountNonStatic = 0;
4.
5. public static class Inner {
6. public void doInner() {
7. System.out.println( CountNonStatic );
8. }
9. }
10. }


O erro acima bsico pra quem j est no captulo 8 desse guia, mas vou mostrar o erro que o
compilador gera:

[color=red:e4cc865dea]Erro de compilao: non-static variable CountNonStatic cannot be
referenced from a static context.[/color:e4cc865dea]

Agora analisaremos o cdigo a seguir:

1. public class Outer {
2. static private int CountStatic = 0;
3. int CountNonStatic = 0;
4.
5. public static class Inner {
6. public void doInner() {
7. System.out.println( CountStatic );
8. }
9. }
10. }


J o cdigo acima compila sem nenhum problema, visto que CountStatic um membro esttico
da classe e pode ser acessado sem que haja uma instncia de Outer.
Voc deve estar se perguntando: "Oxente, mas porqu ento criar uma classe esttica (top-
level class) se ela se comporta da mesma forma que uma classe externa ?" - Essa questo
natural na cabea de qualquer um. A resposta nem sempre, vejamos um explicao lgica para
tal.

O que ns aprendemos no captulo 2 sobre o modificador private ? Que um membro com
modificador private s pode ser acesso de dentro da prpria classe certo ? Mentira era tudo
mentira ! Calma s uma brincadeira. Note que no cdigo anterior o membro CountStatic tem
o modificador private, e mesmo assim est sendo acessado de uma classe que se comporta
como classe externa porm no deixa de ser interna.
O que uma classe de nvel superior tm de diferentes das classes externas no tocante
relacionamento com sua classe encapsulada um acesso direto aos membros independentes
de sua modificador de acesso. A seguir temos um exemplo prtico do us desse tipo de classe:

1. import java.util.*;
2. public class Week {
3. private int weeknr;
4. private int year;
5. public Week(int weeknr, int year) {
6. this.weeknr = weeknr;
7. this.year = year;
8. }
9. public Iterator getDays() {
10. return new DayIterator(this);
11. }
12. public int getWeeknr() {
13. return weeknr;
14. }
15. public int getYear() {
16. return year;
17. }
18. public static class DayIterator implements Iterator {
19. private int index = 0;
20. private Calendar cal = null;
21.
22. DayIterator (Week aWeek) {
23. cal = new GregorianCalendar();
24. cal.clear();
25. cal.set(Calendar.YEAR, aWeek.getYear());
26. cal.set(Calendar.WEEK_OF_YEAR, aWeek.getWeeknr());
27. }
28. public boolean hasNext() {
29. return index < 7;
30. }
31. public Object next() {
32. cal.set(Calendar.DAY_OF_WEEK, index++);
33. return cal.getTime();
34. }
35. public void remove() {
36. // not implemented
37. }
38. }
39.
40. public static void main(String[] args) {
41. // list the days of the week
42. if (args.length < 2) {
43. System.err.println("Usage: java Week <weeknr> year>");
44. System.exit(1);
45. } else {
46. try {
47. int weeknr = Integer.parseInt(args[0]);
48. int year = Integer.parseInt(args[1]);
49. Week wk = new Week(weeknr, year);
50. for (Iterator i=wk.getDays();i.hasNext();) {
51. System.err.println(i.next());
52. }
53. } catch (NumberFormatException x) {
54. System.err.println("Illegal week or year");
55. }
56. }
57. }
58. }


Entender o cdigo acima o far abrir os horizontes para o uso de classes estticas.

8.4 - Classe interna comum

O estudo de classes internas no segue uma orientao explcita da Sun, porm comum se
deparar com questes ao longo do exame, e voc precisar saber algumas regras para no
vacilar (errar mesmo) alguma questo pertinentes esse assunto.
Voc NUNCA poder ter uma instncia de uma classe interna sem que haja uma instncia de
uma classe externa, Vejamos:

1. public class Outer {
2. class Inner {
3. }
4. }


Fixe bem isso: "Qualquer tentativa de instanciao da classe Inner sem que haja um OBJETO
do tipo Outer, no funciona e entenderemos isso no que segue".
Podemos inferir a partir dessa assero que um mtodo esttico de Outer nunca poder
instanciar uma classe Inner, visto que um mtodo esttico pode ser acesso sem um objeto
propriamente dito e isso viola a regra definida anteriormente. Portanto:

1. public class Outer {
2. public static void main(String[] args) {
3. Inner i = new Inner();
4. }
5.
6. class Inner {
7. }
8. }


O cdigo anterior causa erro de compilao, visto que o mtodo main esttico e pode ser
chamado sem que haja uma instncia de Outer, portanto erro: "Uma instncia de Inner s
poder existir a partir sua classe externa" - mudando um pouco o cdigo obteramos um xito
na compilao:

1. public class Outer {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. Inner i = o.new Inner();
5. }
6.
7. class Inner {
8. }
9. }


Compilao executado sem nenhum erro !

8.4.1 - Classes internas e membros externos

Uma classe interna como j foi falado, pode ser chamada de membro de classe da classe
externa, portanto se um membro, ter visibilidade para qualquer membro da classe externa,
isso mesmo, qualquer membro da classe externa pode ser acesso pela classe interna, vejamos:

1. public class Outer {
2. private int x = 0;
3. public static void main(String[] args) {
4. Outer o = new Outer();
5. Inner i = o.new Inner();
6. o.print();
7. }
8. public void print() {
9. System.out.println("x before "+x);
10. Inner i = new Inner();
11. i.print();
12. }
13. class Inner {
14. public void print() {
15. x++;
16. System.out.println("x after: "+x);
17. }
18. }
19. }


Note que o membro x que privado foi acesso por Inner sem nenhum erro. O cdigo acima
resulta em:

x before 0
x after: 1

8.4.2 - Instanciando um objeto interno fora da classe externa

Por mais que isso possa parecer estranho, mas possvel obter uma instncia de uma classe
interna fora de sua classe externa, vejamos o cdigo que segue:

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. Outer.Inner i = o.new Inner();
5. }
6. }
7. class Outer {
8. class Inner { }
9. }


O cdigo acima compila e vlido, pois para se obter uma instncia Inner se informa sua classe
externa - Outer.
Isso muito interessante pode ser usado tambem para deixar o acoplamento de classes em um
nvel baixo - mas tome muito cuidado com isso!

8.4.3 - Referenciando a classe externa de dentro da classe interna

Ter uma referncia da classe externa de dentro da classe interna pode parecer estranho,
porm, s vezes, necessrio. Imaginemos uma situao em que um mtodo da classe interna
precise passar como referncia a classe externa, viu ? Por mais que a classe interna tem acesso
todos os membros da classe externa, pode ser que em um caso atpico, voc precise disso, ou
acha que estamos colocando isso aqui por ser notrio ?

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. Outer.Inner i = o.new Inner();
5. i.see();
6. }
7. }
8. class Outer {
9. private int x = 10;
10. class Inner {
11. public void see() {
12. System.out.println(x);
13. System.out.println(this); // nota 1
14. System.out.println(Outer.this); // nota 2
15. }
16. }
17. }


Nota 1: Observe que a palavra chave this foi usada, nesse caso ele uma referncia ao objeto
de Inner !
Nota 2: Note que this foi usado com o nome da classe externa, portanto, esse o objeto da
classe externa

8.4.4 - Modificadores aplicados as classes internas comuns

Como j foi falado mais tenho certeza que sua displicncia o fez esqueer :) - calma, calma s
um teste de pacincia ! - uma classe interna um membro da classe externa, portando os
modificadores a seguir podem ser aplicados uma classe interna, seguindo as mesmas regras
do captulo 2:

final

abstract

public

private

protected

static - com uma exceo que estudaremos mais adiante.

strictfp


8.5 - Classe interna local de mtodo

At agora vimos como uma classe pode ser criada dentro de outra, com escopo em toda a
classe, pois bem, agora vamos reduzir esse escopo, isso mesmo, definir uma classe com escopo
de mtodo, vejamos:

1. public class Outer {
2. public void see() {
3. class Inner { }
4. }
5. }


Note que a classe Inner foi criada dentro do mtodo see(), apesar de no fazer nada pois
nenhuma instncia foi criada de Inner dentro do mtodo see.

8.5.1 - Modificador padro

Uma classe de mtodo tem o modificador private por padro, visto que no pode ser instancia
de nenhum outro local seno o mtodo que encapsula a classe, vejamos um exemplo de uso:

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. o.see();
5. }
6. }
7. class Outer {
8. private int x = 10;
9. public void see() {
10. System.out.println("before "+x);
11. class Inner {
12. public Inner() {
13. x = 0;
14. }
15. }
16. System.out.println("after "+x);
17. }
18. }


Note que a classe Inner foi criada no meio do mtodo, e isso perfeitamente aceitvel pelo
compilador, s no tente instanci-la antes de criar, pois isso seria um insulto ao compilador. O
cdigo acima resulta em:

before 10
after 10

A varivel x no foi inicializada com 0 pois o construtor de Inner no foi chamado, vejamos o
exemplo a seguir:

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. o.see();
5. }
6. }
7. class Outer {
8. private int x = 10;
9. public void see() {
10. System.out.println("before "+x);
11. class Inner {
12. public Inner() {
13. x = 0;
14. }
15. }
16. Inner i = new Inner();
17. System.out.println("after "+x);
18. }
19. }


Resultado:

before 10
after 0

No existe forma no mundo Java para instanciar uma classe interna de mtodo fora do prprio
mtodo, se conhecerem no esqueam de me avisar. Tentei mostrar um exemplo de
instanciao invlida mas no fui criativo o suficiente, vejamos algo:

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. o.see();
5. }
6. }
7.
8. class Outer {
9. private int x = 10;
10. Inner x; // ERRO A CLASSE INNER NAO FOI DECLARADA
11. public void see() {
12. System.out.println("before "+x);
13. class Inner {
14. public Inner() {
15. x = 0;
16. }
17. }
18. Inner i = new Inner();
19. System.out.println("after "+x);
20. }
21. }


ou

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. System.out.println(o.see().new Inner().s); // SERIA O CMULO
5. }
6. }
7.
8. class Outer {
9. private int x = 10;
10. public void see() {
11. System.out.println("before "+x);
12. class Inner {
13. public String s = "string inner";
14. public Inner() {
15. x = 0;
16. }
17. }
18. Inner i = new Inner();
19. System.out.println("after "+x);
20. }
21. }


8.5.2.1 - Modificadores aplicados classe interna de mtodo

Os nicos modificadores aplicados a essa classe so:

abstract
final

Nunca os dois ao mesmo tempo claro! Pesquisamos muito para saber qual seria o sentido de
criar uma classe de mtodo abstrata. Se algum descobrir esse enigma no esquea de me
avisar...

PODE ESPERAR QUE NA PROVA PODE CAIR ALGO ASSIM, MAS NO VACILEM !!

8.5.2 - Usando as variveis automtica de mtodos

Uma classe interna de mtodo no pode referenciar as variveis locais de mtodo, por incrvel
que parea ! Voc deve estar desgrenhando-se, mas no pode ! E existe uma explicao
plausvel para isso. Imagina que uma classe interna de mtodo chame um mtodo e precise
passar como parmetro a prpria classe, como um mtodo da classe interna pode referenciar
uma varivel automtica aps a execuo do mtodo, uma vez que esse sendo finalizado, suas
variveis so destrudas. Voc pode estar se perguntando: "Oxente, mas como a classe interna
precisar de uma varivel local aps a execuo do mtodo ?" Calma, imagine que o objeto da
classe interna, que est no heap foi passado para um outro mtodo, e esse tem sua execuo
mesmo aps o mtodo ter sido finalizado. Vejamos um exemplo invlido:

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. o.see();
5. }
6. }
7.
8. class Outer {
9. private int x = 10;
10. public void see() {
11. int y = 5;
12. System.out.println("before "+x);
13. class Inner {
14. public String s = "string inner";
15. public Inner() {
16. x = y; // nota 1
17. }
18. }
19. Inner i = new Inner();
20. System.out.println("after "+x);
21. }
22. }


Nota 1: Note que a varivel local y no pode ser referenciada dentro da classe interna de
mtodo, isso causaria um erro de compilao: local variable y is accessed from within inner
class; needs to be declared final

Mas para aumentar a complexidade e o nmero de regras da linguagem Java, existe uma
exceo para esse caso: Se a varivel for final poder ser referenciada (sei que voc j tinha
traduzido a mensagem de erro acima!), vejamos

1. public class TestOuter {
2. public static void main(String[] args) {
3. Outer o = new Outer();
4. o.see();
5. }
6. }
7.
8. class Outer {
9. private int x = 10;
10. public void see() {
11. final int y = 5;
12. System.out.println("before "+x);
13. class Inner {
14. public String s = "string inner";
15. public Inner() {
16. x = y;
17. }
18. }
19. Inner i = new Inner();
20. System.out.println("after "+x);
21. }
22. }


Resultado:

before 10
after 5

8.5.3 - Modificadores de acesso

As mesmas regras de variveis locais se aplicam as classes internas de mtodos. Com isso
podemos lembrar facilmente quais so os nicos modificadores aplicveis s variveis locais ?

a) public, private, protected, padro
b) final, abstract, static
c) static, final, protected
d) abstract, final
e) todos os modificadores

[color=green:e4cc865dea]Resposta no final do captulo !!![/color:e4cc865dea]

8.6 - Classes internas annimas

Preste bastante ateno nesse tpico, pois voc pode se confundir quando se deparar com
questes que envolvem classes annimas. Vejamos sua sintaxe:

1. class Car {
2. public void run() { ... }
3. }
4.
5. class Gol {
6.
7. Car car = new Car() {
8. public void break() { ... }
9. };
10. }


Observe que a classe Car foi criada sem nenhuma anormalidade, porm a classe Vehicle foi
criada com uma instncia de Car, e se voc for uma camarada esperto, notou que no houve
um (;) (ponto-e-vrgula) aps a declarao do membro car, ao contrrio, foi criada uma
instncia de uma classe annima (pois no foi definido um nome - que uma subclasse de Car)
com um novo mtodo chamado break. A priori, pode parecer complicado, mas isso tudo
nadamais do que, uma herana em local exclusivo (ou pra complicar mesmo), ou seja,
somente nesse ponto preciso de redefinir a classe X. Vejamos um outro exemplo para entender
melhor:

1. class Empregado {
2. public void trabalhar() {
3. System.out.println("trabalhar");
4. }
5. }
6.
7. class QuadroFuncionario {
8. Empregado mgr = new Empregado() {
9. public void trabalhar() {
10. System.out.println("mandar");
11. }
12. };
13.
14. Empregado peao = new Empregado() {
15. public void trabalhar() {
16. System.out.println("executar");
17. }
18. };
19. }


Note que estamos realizando uma criao de mtodos polimrficos para os objetos peao e mgr
onde ambos estendem de Empregado.

Voc capaz de descobrir qual o erro da seguinte listagem ?

1. class Empregado {
2. public void trabalhar() {
3. System.out.println("trabalhar");
4. }
5. }
6.
7. class QuadroFuncionario {
8. Empregado mgr = new Empregado() {
9. public void trabalhar() {
10. System.out.println("mandar");
11. }
12.
13. public void demite() {
14. System.out.println("demite");
15. }
16. };
17.
18. public void work() {
19. mgr.trabalhar();
20. mgr.demite();
21. }
22. }


Observe que mgr uma instncia de Empregado, o qual define o mtodos trabalhar, porm h
uma tentativa de execuo do mtodo (que realmente foi definido na classe annima)
mgr.demite(), que o compilador acusa erro de ignorncia, ou seja, o compilador s ir conhecer
os mtodos definidos na classe pai - qualquer tentativa de execuo ou chamada de um
mtodo no existente, causar um erro de compilao: cannot resolve symbol

No podemos esquecer...

1. public class Test {
2. static public void enclosingMethod(final String arg1, int arg2) {
3. final String local = "A local final variable";
4. String nonfinal = "A local non-final variable";
5. Object obj = new Object() {
6. public String toString() {
7. return local + "," + arg1;
8. }
9. };
10.
11. System.out.println(obj.toString());
12. }
13.
14. public static void main(String[] args) {
15. enclosingMethod("fim", 0);
16. }
17. }


Esse cdigo perfeitamente compilado pois a classe annima que est sendo criada dentro do
mtodo enclosingMethod referencia a varivel local que definida como final e arg1 que
tambm um argumento com modificador final. Qualquer tentativa de referencia arg2 ou
nonfinal dentro do mtodo acima, causar erro de compilao, se estiver duvidando por tentar.

Se voc realmente precisar de referenciar uma varivel local dentro de uma classe annima
podemos dar uma dica, provavelmente voc nunca precisar mas, s pra no perder a viagem:
use array. Vejamos um exemplo:

1. public class Ex02 {
2. public static void main(String[] args) {
3. final int[] age = new int[1];
4. System.out.println("Before: "+age[0]);
5. Pessoa p = new Pessoa() {
6. public void getAge() {
7. age[0] = 25;
8. }
9. };
10. p.getAge();
11. System.out.println("After: "+age[0]);
12. }
13. }
14. abstract class Pessoa {
15. abstract void getAge();
16. }


Se voc est lembrado do que estudamos nos captulos iniciais, vai lembrar que o array final
seus elementos no. Portanto o resultado desse cdigo ser:

Before: 0
After: 25


8.6.2 - Implementando uma interface anonimamente

Voc tambm poder se deparar com o cdigo a seguir:

1. public class Ex04 {
2. public static void main(String[] args) {
3. acao( new Evento() {
4. public void clicar() {
5. System.out.println("clicou");
6. }
7. public void arrastar() {
8. System.out.println("arrastou");
9. }
10. });
11. }
12. public static void acao(Evento e) {
13. e.clicar();
14. e.arrastar();
15. }
16. }
17. interface Evento {
18. public abstract void clicar();
19. public abstract void arrastar();
20. }


Voc deve estar se peguntando, como pode passar para um mtodo uma instncia de uma
interface ? Por mais que possa parecer isso, no o que est acontecendo, na verdade
estamos criando uma classe annima que implementa a interface Evento, tanto que a nova
classe teve que implementar todos os mtodos de Eventos (clicar e arrastar), se um desses dois
mtodos no forem implementados na classe annima um erro de compilao seria exibido.
Pode parecer estranho, mas no ! O que criamos aqui foi um implementador de classe como
algumas literaturas assim o definem.

Mesmo que esse assunto de classes annimas possa parecer diferentes as regras de herana,
polimorfismo se aplicam, ou seja, uma tentativa de criar uma classe annima que herda de uma
classe abstrata deve obrigatriamente implementar todos os seus mtodos, isso porque voc
no pode definir uma classe annima abstrata.

1. public class Ex04 {
2. public static void main(String[] args) {
3. acao( new Evento() {
4. public void clicar() {
5. System.out.println("clicou");
6. }
7. public void arrastar() {
8. System.out.println("arrastou");
9. }
10. });
11. }
12. public static void acao(Evento e) {
13. e.clicar();
14. e.arrastar();
15. }
16. }
17. interface Evento {
18. public abstract void clicar();
19. public abstract void arrastar();
20. }


Vamos mudar um pouco o cdigo acima:

1. public class Ex05 {
2. public static void main(String[] args) {
3. acao( new Evento() {
4. public void clicar() {
5. System.out.println("clicou");
6. }
7. });
8. }
9. public static void acao(Evento e) {
10. e.clicar();
11. e.arrastar();
12. }
13. }
14. abstract class Evento {
15. public abstract void clicar();
16. public abstract void arrastar();
17. }


O cdigo acima gerar um erro de compilao, pois o mtodo arrastar no foi implementado na
nova classe (isso seria perfeitamente possvel se a nova classe fosse abstrata) porm como
uma classe concreta deve implement-lo.

8.6.3 - Classes finais no podem ser annimas

O ttulo anterior j falou tudo o que precisava ser falado, mas vamos ser menos suscinto.
Aprendemos algum dia de nossa vida que uma classe marcada com o modificador final nunca
poderia ser estendida, consequentemente nunca poderamos ter uma classe annimas a partir
de uma classe final, pois uma classe annima nada mais do que uma herana de uma outra
classe onde a subclasse no tem nome. Vejamos isso na prtica:

1. public class Ex06 {
2. public static void main(String[] args) {
3. acao( new Boy() {
4. public String get() {
5. System.out.println("boy anonymous");
6. }
7. });
8. }
9. public static void acao(Boy e) {
10. System.out.println(e.get());
11. }
12. }
13. final class Boy {
14. public String get() {
15. return "boy";
16. }
17. }


O cdigo acima gerar o seguinte erro de compilao:

[color=red:e4cc865dea]Erro de compilao: cannot inherit from final Boy[/color:e4cc865dea]

Bom no podemos esquecer das demais regras envolvendo classes e herana, como a
visibilidade para com classes de outros pacotes, enfim, se tiver alguma dvida quanto a isso
volte ao captulo 2.

8.6.4 - Um cdigo real para esse caso...

Vamos ver um uso prtico desse tipo de classe, inclusive vamos utilizar o mesmo exemplo do
incio do captulo quando falvamos de classes estticas, modificaremos um pouco o cdigo
exibido anteriormente:

1. import java.util.*;
2. public class WeekAnonymous {
3. private int weeknr;
4. private int year;
5. public WeekAnonymous(int weeknr, int year) {
6. this.weeknr = weeknr;
7. this.year = year;
8. }
9. public Iterator getDays() {
10. return new Iterator() {
11. private int index = 0;
12. private Calendar cal = null;
13. private Calendar getCalendar () {
14. if (cal == null) {
15. cal = new GregorianCalendar();
16. cal.clear();
17. cal.set(Calendar.YEAR, year);
18. cal.set(Calendar.WEEK_OF_YEAR, weeknr);
19. }
20. return cal;
21. }
22. public boolean hasNext() {
23. return index < 7;
24. }
25. public Object next() {
26. getCalendar().set(Calendar.DAY_OF_WEEK, index++);
27. return getCalendar().getTime();
28. }
29. public void remove() {
30. // not implemented
31. }
32. };
33. }
34. public static void main(String[] args) {
35. // list the days of the week
36. if (args.length < 2) {
37. System.err.println("Usage: java Week <weeknr> year>");
38. System.exit(1);
39. } else {
40. try {
41. int weeknr = Integer.parseInt(args[0]);
42. int year = Integer.parseInt(args[1]);
43. Week wk = new Week(weeknr, year);
44. for (Iterator i=wk.getDays();i.hasNext();) {
45. System.err.println(i.next());
46. }
47. } catch (NumberFormatException x) {
48. System.err.println("Illegal week or year");
49. }
50. }
51. }
52. }


Note que o cdigo acima no criou uma classe esttica como no incio do captulo,
nesse caso foi criada uma classe annima para resolver o mesmo problema, com
isso podemos inferior que a utilizao de classes internas um assuntos
extremamente relativo, podemos ser utilizado de diversas maneiras.

Esses exemplos foram tirados do guia de certificao da Sun !

Para encerrar esse assunto de classes annimas, gostaramos de explanar que o uso
de classes annimas so freqentemente utilizadas em desenvolvimento de
ambientes grficos quando se usa AWT ou Swing principalmente para tratamento de
eventos.

Estamos terminando nosso estudo, s falta mais um captulo........ :!: :!:

Cap. 9 - Threads (Segmentos)
Captulo 9 - Threads

9.1 - Uma viso sobre Threads

Antes de qualquer estudo mais aprofundado sobre threads, gostaramos de deixar bem claro
alguns pontos importantes para o sucesso da absoro do contedo desse captulo.
Com o crescimento do poder de processamento dos computadores modernos, e as inovaes
dos sistemas operacionais para criar um ambiente de trabalho amigvel junto aos seus
usurios, uma srie de inovaes foram acrescidas, e, um recurso que ganhou espao e tem se
mostrato bastante interessante o processamento paralelo, onde um processo pode se dividir
em inmeros processos de dimenses menores para resolver problemas distintos. Calma que
no mgica. O que acontece na verdade o seguinte: em um ambiente monoprocessado, um
processo maior que responsvel pelos subprocessos divide o tempo do processador entre
esses subprocessos, ou seja, comea a executar o subprocesso 01, aps algum tempo (esse
tempo depende da JVM e SO) esse processo fica aguardando sua vez de continuar sendo
executado, a partir da o processador est livre para execuo de um outro processo, at que
novamente o subprocesso 01 volta a ser executado, at que por algum motivo ele termina.
Esse recurso bastante intrigante pois permite-nos resolver problemas que levaramos um
tempo bem superior, uma vez que sem esse poder de escalonar o processador, o processo
comearia e terminaria para assim liberar o processador a iniciar a execuo de um novo
processo.

Em java, temos duas alternativas para implementar o recurso de multi-thread:

a) Estendendo da Classe Thread
b) Implementando a Interface Runnable

Vejamos um exemplo para cada mtodo:

a) Estendendo de java.lang.Thread:

1. public class Execucao {
2. public static void main(String[] args) {
3. Proc p = new Proc();
4. p.start();
5. while (true) {
6. System.out.println("thread main executando");
7. }
8. }
9. }
10.
11. class Proc extends Thread {
12. public void run() {
13. while (true) {
14. System.out.println("thread executando");
15. }
16. }
17. }


b) Implementando a interface Runnable

1. public class Execucao {
2. public static void main(String[] args) {
3. Proc p = new Proc();
4. Thread t = new Thread(p);
5. t.start();
6. while (true) {
7. System.out.println("thread main executando");
8. }
9. }
10. }
11.
12. class Proc implements Runnable {
13. public void run() {
14. while (true) {
15. System.out.println("thread executando");
16. }
17. }
18. }


Por mais que os cdigos acima possam no ter muito sentido, posso-lhe garantir que
funcionam. O mtodo main uma thread e instancia um objeto p que tambm instancia de
uma classe que estende de Thread. O mtodo start() chamado, informa ao escalonador de
thread que coloque na fila de execuo a Thread p, mas no pense que a thread p vai executar
imediatamente quando o mtodo start foi chamado, somente sinaliza o escalonador (ei, eu sou
p e sou thread, me execute assim que puder, obrigado).

9.2 - O que uma thread executa

Voc j deve ter notado que nos exemplos anteriores o cdigo da Thread fica no mtodo run,
porm mostramos duas formas de se executar um thread, ento vamos entender. Quando uma
classe herda de Thread e implementa seu mtodo abstrato run, o cdigo que se encontrar
dentro executado. J quando uma classe implementa Runnable e implementa o mtodo run,
o mtodo que executado o mtodo da classe que implementa a interface Runnable. Voc
nunca poder chamar diretamente o mtodo run de uma classe Thread, pois assim, o
processador no ser dividido entre os diversos processos, voc dever chamar o mtodo start
para que o escalonador saiba da existncia da Thread, e deixe que o mtodo run seja
executado pelo escalonador. Se voc no chamar o mtodo start, sua thread nunca ser
executada.

A assinatura do mtodo run :

1. public void run()


Note que o mtodo no lana nenhuma exceo checada, isso significa que voc no poder
fazer.

9.3 - Mtodos importantes da classe Thread

Os mtodos a seguir precisam ser decorados, lembrados na hora do exame:

run()- o cdigo que a thread executar.

start()- sinaliza JVM que a thread pode ser executada, mas saiba que essa execuo no
garantida quando esse mtodo chamado, e isso pode depender da JVM.

isAlive()- volta true se a thread est sendo executada e ainda no terminou.

sleep()- suspende a execuo da thread por um tempo determinado;

yield()- torna o estado de uma thread executvel para que thread com prioridades
equivalentes possam ser processadas, isso ser estudando mais adiante;

currentThread()- um mtodo esttico da classe Thread que volta qual a thread que est
sendo executada.

getName()- volta o nome da Thread, voc pode especificar o nome de uma Thread com o
mtodo setName() ou na construo da mesma, pois existe os construtores sobrecarregados.

9.4 - Mtodos herdados de java.lang.Object relacionados com Threads

Os mtodos a seguir pertencem classe Object, porm esto relacionados com a programao
Multi-Threading:

1. public final void wait()
2. public final void notify()
3. public final void notifyAll()


Examinaremos os mtodos acima citados, porm antes de qualquer coisa precisamos entender
os estados de uma thread, e isso que vamos entender a partir de agora.

9.5 - Estados dos segmentos

Novo- estado que uma thread fica no momento de sua instanciao, antes da chamada do
mtodo start();

Executvel- estado em que a thread fica disponvel para ser executada e no aguardo do
escalonador de thread, esperando a sua vez de se executar;

Execuo- Momento em que a thread est executando, est operando, trabalhando, pagando
seu salrio e sua execuo continua at que por algum motivo (que veremos brevemente) esse
momento interrompido;

Espera/Bloqueio/Suspenso- esse estado pode ser dar por inmeros motivos, e vamos
tentar esplanar alguns. Uma thread em seu grande momento de glria (sua execuo) pode se
bloquear por que algum recurso ou objeto no est disponvel, por isso seu estado pode ficar
bloqueado, at que esse recurso/objeto esteja disponvel novamente assim seu estado torna-se
executvel, ou ento, uma thread pode ficar suspensa porque o programador definiu um tempo
de espera, assim que esse tempo expirar essa thread volta ao estado executvel para continuar
seus servios;

Inativo- a partir do momento em que o mtodo run() foi concludo, a thread se tornar
inativa, porm ainda existir o objeto na memria, somente no como uma linha de execuo,
e no poder novamente se estartado, ou seja, qualquer tentativa de chamada do mtodo
start() aps a concluso do mtodos run(), uma exceo ser lanada e no duvide;

9.6 - Impedindo uma thread de ser executada

Suspendendo uma thread

Pense em uma situao em que voc tenha 10 Thread rodando simultneamente (sei, eu fui
redundante agora), porm uma delas voc deseja tarefa realizada, ela aguarde 5 minutos para
prosseguir suas tarefas, por mais que isso parea loucura, mas possvel, voc poder usar o
mtodo sleep para tornar uma thread no modo suspenso at que esse tempo expire, vejamos
sua sintaxe:

1. try {
2. sleep(5*60*1000);
3. }
4. catch (InterruptedException ex) {
5. }


O cdigo acima, faz com que a thread espere por 5 minutos at voltar ao estado Executvel,
porm uma alternativa quando se pretende executar as thread de forma mais organizada,
apesar de que lembre-se sempre: VOC NUNCA TER GARANTIAS QUANTO A ORDEM DA
EXECUO DAS THREAD, POIS ISSO VAI DEPENDER DO ESCALONADOR !
Qualquer pergunta com relao tentativa de garantir um ordem, ou sequencia de execuo
das thread, no hesite em marcar a alternativa que diz que no existe garantias para tal tarefa.

No pense que o tempo que for especificado no mtodo sleep ser exatamento o tempo que a
thread ficar sem executar, a nica garantia que teremos que esse ser o tempo mnimo,
porm aps o seu trmino, seu estado passa para Executvel e no Execuo.

Tenha em mente que o mtodo sleep um mtodo esttico, portanto voc no poder chamar
o mtodo sleep de um thread x ou y, somente da thread que estiver em estado de execuo.

Vejamos um exemplo prtico:

1. public class Exec11 {
2. public static void main(String args[]) {
3. Contador c1 = new Contador();
4. c1.setQtde(10);
5. c1.setName("t001");
6. c1.start();
7. Contador c2 = new Contador();
8. c2.setQtde(15);
9. c2.setName("t002");
10. c2.start();
11. }
12. }
13.
14. class Contador extends Thread {
15. private int qtde = 0;
16. public void run() {
17. for (int i=0; i <= 100; i++) {
18. if ((i%qtde) == 0) {
19. System.out.println(Thread.currentThread().
getName()+"> "+i);
20. }
21. try {
22. sleep(500);
23. }
24. catch (InterruptedException ex) {
25. }
26. }
27. }
28.
29. public void setQtde(int value) {
30. this.qtde = value;
31. if (this.qtde == 0) this.qtde = 10;
32. }
33. }


Por mais que tenha se tentado estabelecer uma ordem, se voc executar o cdigo acima ir
perceber que no h garantias de ordem na execuo.


9.7 - Prioridades

A prioridade tambm assunto contundente, pois cada JVM define a sua maneira de escolher a
thread que passar do estado de executvel para execuo. Pois a especificao Java no
define nada a respeito. Por isso no confie em prioridades para garantir uma execuo
sincronizadas de suas threads, use-as para melhorar a eficincia de suas tarefas. Para definir
uma prioridade para uma thread voc usar o mtodo

1. public void setPriority(xxx)


onde xxx - um nmero inteiro compreendido entre 1 e 10
A prioridade padro 5, ou seja, se no for definida nenhuma prioridade, ser assumido o valor
5 para a thread.

Voc poder cair em uma situao em que poder ter vrias thread com a mesma prioridade, e
desejar que thread que estiver executando d lugar para outras serem processadas, e para isso
existe o mtodo yield() que faz justamente isso, torna o estado de execuo da thread atual
para executvel e d o lugar para as demais thread de prioridades semelhantes. No obstante a
isso, no garante que a thread que vai ser executada, no seja a mesma que acabou de sair do
estado de execuo, portanto esse mtodo tambm no garante fazer o que se prope.

9.8 - Hierarquia de Threads

Imagine que voc tenha uma thread Y que s poder ser executada quando a thread X concluir
sua tarefa, voc poder ligar uma thread outra, usando o mtodo join(), vamos entender isso
a partir de agora:

Examinemos o cdigo a seguir:

1. public class Exec12 {
2. public static void main(String args[]) {
3. try {
4. Contador c1 = new Contador();
5. c1.setQtde(10);
6. c1.setName("t001");
7. c1.start();
8. c1.join();
9. for (int i=0; i <= 100; i++) {
10. if ((i%5) == 0) {
11. System.out.println(Thread.currentThread().getName()+"> "+i);
12. }
13. }
14. }
15. catch (InterruptedException e) {
16. }
17. }
18. }
19.
20. class Contador extends Thread {
21. private int qtde = 0;
22. public void run() {
23. for (int i=0; i <= 100; i++) {
24. if ((i%qtde) == 0) {
25. System.out.println(Thread.currentThread().getName()+"> "+i);
26. }
27. try {
28. sleep(500);
29. }
30. catch (InterruptedException ex) {
31. }
32. }
33. }
34.
35. public void setQtde(int value) {
36. this.qtde = value;
37. if (this.qtde == 0) this.qtde = 10;
38. }
39. }


Resultado do cdigo acima:

t001> 0
t001> 10
t001> 20
t001> 30
t001> 40
t001> 50
t001> 60
t001> 70
t001> 80
t001> 90
t001> 100
main> 0
main> 5
main> 10
main> 15
main> 20
main> 25
main> 30
main> 35
main> 40
main> 45
main> 50
main> 55
main> 60
main> 65
main> 70
main> 75
main> 80
main> 85
main> 90
main> 95
main> 100


O exemplo acima garante que a thread main s ser executada quando a Thread t001 estiver
inativa.

Vamos complicar um pouco.... O mtodo join sobrecarregado e pode receber um valor long
que corresponde quantidade millissegundos que a thread main (em nosso caso) anterior
espera at que t001 se concluir, se a mesma no ficar inativa no tempo informado, nada mais
garantido, ou seja, o escalonador poder iniciar a execuo de ambas as threads. Vamos alterar
um pouco o cdigo e observar os resultados:

1. public class Exec13 {
2. public static void main(String args[]) {
3. try {
4. Contador c1 = new Contador();
5. c1.setQtde(10);
6. c1.setName("t001");
7. c1.start();
8. c1.join(5000);
9. for (int i=0; i <= 100; i++) {
10. if ((i%5) == 0) {
11. System.out.println(Thread.currentThread().getName()+"> "+i);
12. }
13. }
14. }
15. catch (InterruptedException e) {
16. }
17. }
18. }
19.
20. class Contador extends Thread {
21. private int qtde = 0;
22. public void run() {
23. for (int i=0; i <= 100; i++) {
24. if ((i%qtde) == 0) {
25. System.out.println(Thread.currentThread().getName()+"> "+i);
26. }
27. try {
28. sleep(250);
29. }
30. catch (InterruptedException ex) {
31. }
32. }
33. }
34.
35. public void setQtde(int value) {
36. this.qtde = value;
37. if (this.qtde == 0) this.qtde = 10;
38. }
39. }


Resultado:

t001> 0
t001> 10
main> 0
main> 5
main> 10
main> 15
main> 20
main> 25
main> 30
main> 35
main> 40
main> 45
main> 50
main> 55
main> 60
main> 65
main> 70
main> 75
main> 80
main> 85
main> 90
main> 95
main> 100
t001> 20
t001> 30
t001> 40
t001> 50
t001> 60
t001> 70
t001> 80
t001> 90
t001> 100

Note que a thread main s esperou pelo tempo de 5000 (5 segundos) a partir dai ela comeou
sua execuo.

9.9 - Sincronizao

O assunto agora um pouco mais complicado do que o estudado at agora, pois trata de como
duas ou mais threads podem compartilhar o mesmo objeto, ou seja, quais so os riscos que
corremos quando dois objetos podem ser vistos simultneamente.

Cenrio:

Imaginemos um processo de compra on-line pela Internet, onde inmeras pessoam podem
consultar os itens disponveis em estoque e realizar seus pedidos. Pois bem, como no
queremos causar situaes indigestas com nossos clientes, precisamos garantir com seus
pedidos sejam faturados corretamente. Bom onde queremos chegar ? Imagine que temos 5
aparelhos celulares S55 SIEMENS em nosso estoque e que foi lanado uma promoo desse
aparelho e 200 pessoas esto dispostas a entrar no tapa por um aparelho, bem temos que
garantir que esse processo seja concretizado sem maiores problema. (tudo isso foi dito para se
esplanar a situao... ) Vejamos como resolver esse problema:

1. public class PedidoCompra {
2. public static void main(String[] args) {
3. Produto p = new Produto(5);
4. Thread[] t = new Thread[15];
5. for (int i=0; i < t.length; i++ ) {
6. t[i] = new Thread(p);
7. t[i].setName("Cliente: "+i);
8. t[i].start();
9. }
10. }
11. }
12.
13. class Produto implements Runnable {
14. private int estoque = 5;
15.
16. public void run() {
17. try {
18. for (int i=0; i<2; i++) {
19. efetuarPedido();
20. }
21. }
22. catch (Exception ex) {
23. }
24. }
25.
26. public void efetuarPedido() {
27. try {
28. if (this.estoque > 0) {
29. System.out.println("Pedido faturado para o cliente "+Thread.curren
tThread().getName());
30. Thread.sleep(250);
31. this.estoque--;
32. } else {
33. System.out.println("No tem estoque para o cliente "+Thread.curren
tThread().getName());
34. }
35. }
36. catch (Exception ex) {
37. }
38. }
39.
40. public Produto(int value) {
41. this.estoque = value;
42. }
43. }


No tenter vender o programa acima para alguma loja que voc ser escurraado!

O cdigo de efetuar pedido, sempre efetuar o pedido tendo ou no estoque, note que na sada
houve 10 cliente que efetuaram seus pedidos com estoque estourado:

Pedido faturado para o cliente Cliente: 0
Pedido faturado para o cliente Cliente: 1
Pedido faturado para o cliente Cliente: 2
Pedido faturado para o cliente Cliente: 3
Pedido faturado para o cliente Cliente: 5
Pedido faturado para o cliente Cliente: 6
Pedido faturado para o cliente Cliente: 8
Pedido faturado para o cliente Cliente: 9
Pedido faturado para o cliente Cliente: 10
Pedido faturado para o cliente Cliente: 11
Pedido faturado para o cliente Cliente: 4
Pedido faturado para o cliente Cliente: 7
Pedido faturado para o cliente Cliente: 12
Pedido faturado para o cliente Cliente: 13
Pedido faturado para o cliente Cliente: 14
Pedido faturado para o cliente Cliente: 0
Pedido faturado para o cliente Cliente: 1
Pedido faturado para o cliente Cliente: 2
Pedido faturado para o cliente Cliente: 3
Nao tem estoque para o cliente Cliente: 5
Nao tem estoque para o cliente Cliente: 6
Nao tem estoque para o cliente Cliente: 8
Nao tem estoque para o cliente Cliente: 9
Nao tem estoque para o cliente Cliente: 11
Nao tem estoque para o cliente Cliente: 10
Nao tem estoque para o cliente Cliente: 4
Nao tem estoque para o cliente Cliente: 12
Nao tem estoque para o cliente Cliente: 7
Nao tem estoque para o cliente Cliente: 13
Nao tem estoque para o cliente Cliente: 14

O que queremos no permitir que haja faturamento caso o estoque esteja negativo.
Pelo resultado no muito difcil deduzir o que aconteceu nesse processamento - embora voc
possa executar e obter outro resultado. Observe que todos os pedidos s foram efetuados
porque h no mtodo efetuarPedido uma suspenso da execuo das thread para sua
concretizao, ou seja, at o momento em que a thread volta aps sua suspenso, o pedido
ainda no foi efetuado, com isso, outros clientes podem efetuar seus pedidos - quando esse
ciclo se repetir para os 5 primeiros clientes, a sim, no ser mais possvel concretizar pedidos,
pois o estoque do item se tornou 0. Porm no foi exatamente isso que aconteceu em nosso
exemplo anterior. E voc capaz de descobrir porque ?

A grande sacada do programa anterior suspender a thread por um tempo para que antes de
concluir sua operao, dando lugar as outras, fazendo com que o estoque fique negativo.

Mas existe uma soluo para que esse "erro" seja revertido, ou seja, no permitir que dois
clientes possam concluir seus pedidos ao mesmo tempo.

Vamos alterar o cdigo anterior, e acrescentar o modificar synchronized que no permite com
que 2 thread executem o mesmo mtodo ao mesmo tempo, ou seja, as demais thread ficam
esperando at que a thread em execuo conclua seu processamento para assim iniciar o seu.

Resultado:
Pedido faturado para o cliente Cliente: 0
Pedido faturado para o cliente Cliente: 1
Pedido faturado para o cliente Cliente: 2
Pedido faturado para o cliente Cliente: 3
Pedido faturado para o cliente Cliente: 4
Nao tem estoque para o cliente Cliente: 5
Nao tem estoque para o cliente Cliente: 6
Nao tem estoque para o cliente Cliente: 7
Nao tem estoque para o cliente Cliente: 8
Nao tem estoque para o cliente Cliente: 10
Nao tem estoque para o cliente Cliente: 11
Nao tem estoque para o cliente Cliente: 12
Nao tem estoque para o cliente Cliente: 13
Nao tem estoque para o cliente Cliente: 14
Nao tem estoque para o cliente Cliente: 9
Nao tem estoque para o cliente Cliente: 0
Nao tem estoque para o cliente Cliente: 1
Nao tem estoque para o cliente Cliente: 2
Nao tem estoque para o cliente Cliente: 3
Nao tem estoque para o cliente Cliente: 4
Nao tem estoque para o cliente Cliente: 5
Nao tem estoque para o cliente Cliente: 6
Nao tem estoque para o cliente Cliente: 7
Nao tem estoque para o cliente Cliente: 8
Nao tem estoque para o cliente Cliente: 10
Nao tem estoque para o cliente Cliente: 11
Nao tem estoque para o cliente Cliente: 12
Nao tem estoque para o cliente Cliente: 13
Nao tem estoque para o cliente Cliente: 14
Nao tem estoque para o cliente Cliente: 9

Note que a sada agora melhorou ! E houve faturamento somente dos 5 itens !

Pensamento Entrpico: Fazer condies e checagens para evitar que o estoque fique negativo !
Lembre-se sempre, voc nunca ter certeza da ordem da execuo das thread, ou seja, uma
thread pode comear (tendo estoque 5) e terminar quando o estoque j acabou, outras threads
foram mais rapidas.....

Outro exemplo:

1. public class Test {
2. public static void main(String[] args) {
3. Crediario c1 = new Crediario();
4. Crediario c2 = new Crediario();
5. Thread t1 = new Thread(c1);
6. t1.setName("t1");
7. Thread t2 = new Thread(c2);
8. t2.setName("t2");
9. t1.start();
10. t2.start();
11. }
12. }
13.
14. class Crediario implements Runnable {
15. public void run() {
16. Cliente c = Cliente.getInstance();
17. System.out.println("Iniciando transacao de crediario... "+Thread.curr
entThread().getName()+" - "+c.toString());
18. c.analisarFicha();
19. }
20. }
21.
22. class Cliente {
23. private static Cliente singleton;
24. public static Cliente getInstance() {
25. if (singleton == null) singleton = new Cliente();
26. return singleton;
27. }
28.
29. synchronized void analisarFicha() {
30. try {
31. Thread.sleep(500);
32. System.out.println("Analisando ficha.... "+Thread.currentThread().get
Name());
33. Thread.sleep(500);
34. liberarFicha();
35. }
36. catch (Exception e) {
37. }
38. }
39.
40. synchronized void liberarFicha() {
41. try {
42. Thread.sleep(500);
43. System.out.println("Liberando ficha.... "+Thread.currentThread().getN
ame());
44. }
45. catch (Exception e) {
46. }
47. }
48. }


Vejamos um exemplo em que dois mtodos so sincronizados e um no, e observe que pelo
resultado nenhum problema h quando se chama um mtodo sem sincroniza mesmo no caso
do objeto estar bloqueado:

1. public class Test {
2. public static void main(String[] args) {
3. Crediario c1 = new Crediario();
4. Crediario c2 = new Crediario();
5. Negativacao n1 = new Negativacao();
6. Thread t1 = new Thread(c1);
7. t1.setName("t1");
8. Thread t2 = new Thread(c2);
9. t2.setName("t2");
10. Thread t3 = new Thread(n1);
11. t3.setName("t3");
12. t1.start();
13. t2.start();
14. t3.start();
15. }
16. }
17.
18. class Crediario implements Runnable {
19. public void run() {
20. Cliente c = Cliente.getInstance();
21. System.out.println("Iniciando transacao de crediario... "+Thread.curr
entThread().getName()+" - "+c.toString());
22. c.analisarFicha();
23. }
24. }
25.
26. class Negativacao implements Runnable {
27. public void run() {
28. Cliente c = Cliente.getInstance();
29. System.out.println("Iniciando transacao de negativacao... "+Thread.cu
rrentThread().getName()+" - "+c.toString());
30. c.negativar();
31. }
32. }
33.
34.
35. class Cliente {
36. private static Cliente singleton;
37. public static Cliente getInstance() {
38. if (singleton == null) singleton = new Cliente();
39. return singleton;
40. }
41.
42. synchronized void analisarFicha() {
43. try {
44. Thread.sleep(500);
45. System.out.println("Analisando ficha.... "+Thread.currentThread().get
Name());
46. Thread.sleep(500);
47. liberarFicha();
48. }
49. catch (Exception e) {
50. }
51. }
52.
53. synchronized void liberarFicha() {
54. try {
55. Thread.sleep(500);
56. System.out.println("Liberando ficha.... "+Thread.currentThread().getN
ame());
57. }
58. catch (Exception e) {
59. }
60. }
61.
62. void negativar() {
63. try {
64. Thread.sleep(500);
65. System.out.println("Negativando ficha.... "+Thread.currentThread().ge
tName());
66. }
67. catch (Exception e) {
68. }
69. }
70. }


Resultado:

Iniciando transacao de crediario... t2 - Cliente@ba34f2
Iniciando transacao de negativacao... t3 - Cliente@ba34f2
Iniciando transacao de crediario... t1 - Cliente@ba34f2
Analisando ficha.... t2
Negativando ficha.... t3
Liberando ficha.... t2
Analisando ficha.... t1
Liberando ficha.... t1

Note que o processo de negativao se processou mesmo no terminando o processo de
credirio.
Agora vamos sincronizar o mtodo sincronizao para ver o que acontece:

Iniciando transacao de crediario... t1 - Cliente@ba34f2
Iniciando transacao de negativacao... t3 - Cliente@ba34f2
Iniciando transacao de crediario... t2 - Cliente@ba34f2
Analisando ficha.... t1
Liberando ficha.... t1
Negativando ficha.... t3
Analisando ficha.... t2
Liberando ficha.... t2

Note que agora o processo de nativao (mtodo negativar) s se procedeu aps o trmino do
processo de liberao. Uso nos leva a pensar em uma situao inesperada: o impasse.....
vejamos no item seguinte:

9.10 - Deadlock (impasse)

Essa uma situao em que duas thread ficam esperando um bloqueio, ou seja, a thread A fica
aguardando o bloqueio que est sob bloqueio da thread B e a thread B est aguardando o
bloqueio que est em possa da thread A, uma situao assim ocasionar em um travamento do
sistema. Embora no seja uma situao comum, quando ocorre o sistema fica paralizado e
alm disso no muito fcil encontrar o problema.

O cdigo a seguir mostra um exemplo bem simples de um deadlock:

1. public class TestDeadLock {
2. public static void main(String[] args) {
3. Crediario c1 = new Crediario();
4. Negativacao n1 = new Negativacao();
5. Thread t1 = new Thread(c1);
6. t1.setName("t1");
7. Thread t2 = new Thread(n1);
8. t2.setName("t2");
9. t1.start();
10. t2.start();
11. }
12. }
13.
14. class Crediario implements Runnable {
15. public void run() {
16. Class1.m1();
17. }
18. }
19.
20. class Negativacao implements Runnable {
21. public void run() {
22. Class2.m1();
23. }
24. }
25.
26. class Class1 {
27. static synchronized void m1() {
28. try {
29. Thread.sleep(500);
30. System.out.println("executando class1 m1");
31. Class2.m2();
32. }
33. catch (Exception e) {
34. }
35. }
36.
37. static synchronized void m2() {
38. try {
39. Thread.sleep(500);
40. System.out.println("executando class1 m2");
41. }
42. catch (Exception e) {
43. }
44. }
45. }
46.
47. class Class2 {
48. static synchronized void m1() {
49. try {
50. Thread.sleep(500);
51. System.out.println("executando class2 m1");
52. Class1.m2();
53. }
54. catch (Exception e) {
55. }
56. }
57.
58. static synchronized void m2() {
59. try {
60. Thread.sleep(500);
61. System.out.println("executando class2 m2");
62. }
63. catch (Exception e) {
64. }
65. }
66. }


9.11 - Interao entre segmentos

Eventualmente voc precisar notificar um segmento que B que o segmento A finalizou sua
tarefa, fazendo com que o segmento B possa entrar em estado de executvel para se
candidatar a executar.

A classe Object define trs mtodos para realizao dessa interao, so eles:


wait()
notify()
notifyAll()

S um lembrete: como esses mtodos so definidos na classe Object, todos os demais objetos
tem esses mtodos, at mesmo a classe Thread, portanto no vacile......

Eles SEMPRE devem ser chamados de um contexto sincronizados.

Um exemplo bem prtico para esse recurso pode ser visto no trecho abaixo, pois uma thread
de leitura aguarda a criao de um arquivo que gerado por outra thread, vejamos o cdigo:

1. import java.io.*;
2.
3. public class InteraThread {
4. public static void main(String[] args) {
5. try {
6. Arquivo arq = new Arquivo(new File("saida.txt"));
7. Thread[] a = new Thread[20];
8. for (int i=0; i < a.length; i++) {
9. a[i] = new Thread(new Leitura(arq));
10. a[i].setName( ""+i);
11. a[i].start();
12. }
13. Thread b = new Thread( new Gravacao(arq) );
14. b.start();
15. b.join();
16. System.out.println("Processo finalizado...");
17. }
18. catch (Exception ex) {}
19. }
20. }
21.
22. class Gravacao implements Runnable {
23. Arquivo arq;
24. public Gravacao(Arquivo value) {
25. arq = value;
26. }
27. public void run() {
28. arq.gravar();
29. }
30. }
31.
32. class Leitura implements Runnable {
33. Arquivo arq;
34. public Leitura(Arquivo value) {
35. arq = value;
36. }
37. public void run() {
38. arq.ler();
39. }
40. }
41.
42. class Arquivo {
43. File file;
44.
45. public Arquivo(File value) {
46. file = value;
47. }
48.
49. synchronized public void ler() {
50. try {
51. if (!file.exists()){
52. wait();
53. }
54. System.out.print( "thread# "+Thread.currentThread().getName() + ">>>
");
55. if (file.exists()){
56. FileInputStream fis = new FileInputStream(file);
57. int in;
58. while ((in=fis.read())!=-1) {
59. System.out.print((char)in);
60. }
61. fis.close();
62. }
63. }
64. catch (Exception e) {
65. e.printStackTrace();
66. }
67. }
68.
69. synchronized public void gravar() {
70. try {
71. if (!file.exists()){
72. FileOutputStream fos = new FileOutputStream(file);
73. for (int i=0; i < 5; i++) {
74. fos.write( ("linha "+i).getBytes() );
75. }
76. fos.write("\n".getBytes());
77. fos.close();
78. System.out.print("Entrou no notify");
79. notify();
80. }
81. }
82. catch (Exception e) {
83. e.printStackTrace();
84. }
85. }
86. }



Como voc pode notar, o cdigo acima dispara 10 thread para leitura de um arquivo que muito
provavelmente nem tenha sido criado, portanto as thread entram no estado wait at que a
thread crie o arquivo liberando para a leitura.


Bom, acho que terminamos o que podemos definir como o PIOR captulo desse guia, portanto
agora revise todos os captulo e BOA SORTE !!!