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


Creative Commons License
Esta obra está licenciada sob uma Licença Creative Commons.
Comentários
0 Comentários

0 comments:

Postar um comentário

Regras são chatas, mas...

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