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