Tuesday, February 17, 2009

SCJP - 02 - Casting

Tá... é só colocar um tipo entre parênteses antes da referência e pronto, tá feito o cast. Mas é só isso? Não dá erro? Se dá, quando dá? Se dá, por quê dá?



Ao efetuar um cast, podem ocorrer erros em tempo de compilação e em tempo de execução. Tudo o que o compilador consegue fazer é analisar se o tipo de chegada (a nova referência) e o tipo de partida (aquele que queremos transformar) estão, pelo menos, na mesma árvore de herança.





class Base {}

class Derivada extends Base{}

public class Principal {
public static void main (String[] args) {
Derivada derivada = new Derivada();
Base base = derivada;
}
}


Bem, porque isso funciona? Tá, nós estamos carecas de saber que isso é um upcast. Up o que? Tá viciado em RPG homi? Tá bom, tá bom... Bem devagar.



Downcast: conversão de um tipo genérico para um tipo mais específico.

Upcast: conversão de um tipo mais específico para um tipo genérico.


E aí a gente começa a entender. Upcasting é feito de maneira automática, como a gente já sabe (disso eu tenho certeza). E então, quando ocorre um downcasting?



class Base {}
class Derivada extends Base{
public void teste() {
System.out.println(
"Método da classe Derivada");
}
}

public class Principal {
public static void main(String[] args) {
Base[] arrayBase = {
new Base(),
new Derivada(),
new Base()};

for (Base base : arrayBase) {
if (base instanceof Derivada) {
Derivada derivada = (Derivada) base;
derivada.teste();
}
}
}
}


Consegue entender aquela condicional ali? Bem... é ali que ocorre um downcasting. Até agora, só vimos situações em que as conversões ocorrem perfeitamente bem, sem erros. E quando os erros ocorrem?



Base base = new Base();
Derivada derivada = (Derivada) base;


Bem vindo ao primeiro erro. Veja que a classe Base e a classe Derivada fazem parte da mesma árvore de herança (será que dá pra abstrair o nome das classes?). Então, pelo compilador, passa. Mas quando se executa o trecho de código acima, somos apresentados a uma nova classe: java.lang.ClassCastException. Mas por quê? Ué, a variável de referência base não "aponta" para um objeto do tipo Derivada. Só por isso.



E agora, vamos ao segundo erro.



Base base = new Base();
String string = (String) base;


Nada a ver não é? Esse erro é capturado logo em tempo de compilação, já que o compilador consegue averiguar que Base e String não fazem parte da mesma árvore de herança. Acontece um erro mais ou menos parecido com:



inconvertible types


Para o exame, é necessário saber reconhecer quando é necessário fazer um cast, e que tipos de erro (em tempo de execução e em tempo de compilação) podem ocorrer. Para o dia a dia, é importante fazer um teste do tipo instanceof antes de qualquer downcast.



No comments:

Post a Comment

Regras são chatas, mas...
Todos os comentários são lidos e moderados previamente.
São publicados aqueles que respeitam as regras abaixo:

- Seu comentário precisa ter relação com o assunto do post;
- Em hipótese alguma faça propaganda de outros blogs ou sites;
- Não inclua links desnecessários no conteúdo do seu comentário;
- Se quiser deixar sua URL, comente usando a opção OpenID;
- CAIXA ALTA, miguxês ou erros de ortografia não serão tolerados;
- Ofensas pessoais, ameaças e xingamentos não são permitidos;