Atenção - cast não é conversão e não faz milagres

Vou deixar este tópico reservado para tentar tirar da cabeça das pessoas uma noção, que está firmemente arraigada na maior parte dos programadores Java iniciantes, que cast é conversão e que faz milagres.

Cast (para referências) só é uma forma de indicar ao compilador que “sabemos qual é o tipo do objeto cuja referência temos, e então queremos indicar explicitamente o tipo correto, para poder usar uma operação dele”. Ele não faz mais nada - não faz conversão, não chama toString, não faz wrapping/unwrapping, não faz pipoca nem frita pastéis.

É que muitas vezes o compilador deixa até usar o cast (afinal de contas, seu chefe não está lhe pressionando um monte? Se pelo menos puder entregar algo que compile, mesmo que não rode, a pressão pode diminuir um pouco :slight_smile: ) mas ele não consegue lhe dizer que o que você está tentando fazer não vai funcionar.

Compilador não faz milagres (e mesmo Deus não faz milagres a esmo, eu costumo dizer que ele só faz milagres como “prova de conceito”).

A primeira coisa que tenho de dizer é que cast só é conversão em um caso muito específico - quando você quer converter um tipo primitivo (numérico) em outro tipo primitivo numérico. Ou seja, isto realmente faz conversões:

long x = 10;
int y = (int) x;
char z = (char) x; // char é um tipo inteiro de 2 bytes, que vai de 0 até 65535 - ou '\u0000' até '\uFFFF'
double d = (double) x;

A segunda coisa é que vocês que aprenderam C++ (onde cast pode fazer conversões se você criar um operador com o nome de um tipo, ou então se você criar um determinado tipo de construtor) estão confundindo C++ com Java. Na verdade, existem vários tipos de casts em C++:

(T) x
const_cast<T>(x)
dynamic_cast<T>(x)
reinterpret_cast<T>(x)
T (x) 

e cada um deles faz uma coisa um pouco diferente. (Quem aprendeu só um pouquinhozinho de C++ só conhece o primeiro tipo, que é o que existe em C também).

A terceira coisa é que há uma sutileza com o uso de classes Wrappers e autoboxing que já vi ocorrer. Quantas vezes você já tentou fazer isto aqui:

Integer i = 10;
Long x;
x = (Long) i;

e isso não funcionou? (Ou então pior, provocou um “ClassCastException”)?
É que o equivalente usando tipos primitivos não só funciona direitinho, como também evita até o cast (nesse caso) - e isso deve lhe dar um nó na cabeça:

int i = 10;
long x;
x = (long) i;

Pior ainda, você pode ter algo como:

Integer i = 10;
Long x;
x = i + 0;

e esse troço funcionar. Não é estranho?
Bom, a primeira coisa q fazer é resolver o seu problema. Troque o código acima por:

Integer i = 10;
Long x;
x = i.intValue();

O que ocorre é que cast não consegue converter nada para nada, mesmo classes wrappers. Nesse caso, é necessário efetuar o “unwrapping”, passar para o tipo adequado para fazer suas contas, e então efetuar o novo “wrapping”. Na linha 3 do código corrigido, há um unwrapping explícito (intvalue() nesse caso), e então um wrapping implícito (quando você atribuiu um int a uma variável do tipo java.lang.Long).