SCJP 6.0 e questão sobre casting

Pessoal o caso é o seguinte, fazendo os exercícios me deparei com esta questão:

public class Redwood extends Tree {
public static void main(String[] args) {
new Redwood().go();
      }
   void go() {
   go2(new Tree(), new Redwood());
   go2((Redwood) new Tree(), new Redwood());
      }
   void go2(Tree t1, Redwood r1) { 
   Redwood r2 = (Redwood)t1; [b]No eclipse o erro ocorreu nessa linha, ao tentar converter t1 para Redwood[/b]
   Tree t2 = (Tree)r1;   
     }
}
 class Tree { }

O livro diz que esta é a resposta: Answer: ® ✓ A is correct, a ClassCastException will be thrown when the code attempts to downcast a
Tree to a Redwood.
Entendi o que aconteceu. O livro cita downcasting quando tentamos converter um tipo geral para um tipo mais específico e fala na necessidade disso ser explícito. No caso de upcasting (tipo específico para tipo geral) o casting pode ser explicíto ou implícito. O problema é que no livro fala do downcasting mas deixa mto vago. Pra ser mais direto ele não fala se downcasting funciona pq ambos os exemplos parece que deram pau. O livro menciona e fala sobre os erros que vem a tempo de execução. Então fiquei na dúvida se o downcasting funciona mesmo ou se o livro só abordou pra exemplificar. Por exemplo no seguinte código

class Animal { }
class Dog extends Animal { }
class DogTest {
public static void main(String [] args) {
Animal animal = new Animal();
Dog d = (Dog) animal; // compiles but fails later
}
}

deu pra entender que o compilador não enxerga o problema pois estão na mesma árvore de herança. Pra poder ocorrer um cast pelo que entendi seria necessário fazer a afirmação dog é uma instância de animal e não animal é uma instância de dog.
No caso do exercicio RedWood(madeira vermelha) é um tipo (instância) de tree(árvore) e não árvore é um tipo de madeira vermelha.
Pela minha conclusão o downcasting então não existe, apenas o upcasting onde é possível atribuir um objeto de uma subclasse num tipo mais genérico, pq ao contrário isso não é possível, e o livro não mencionou explicitamente. Estou certo??

Então… você nunca vai conseguir pegar uma instância mais genérica e transformá-la em uma mais específica. Porém o que o livro deve tratar como downcasting é algo como:

[code]public class Animal {}
class Dog extends Animal{}
class Cat extends Animal{}

public static void main(String[] args) {
Animal[] animals = new Animal[]{new Animal(), new Dog(), new Cat()};
Dog dog = (Dog) animals[1];
}[/code]

você tem uma instância de animal, mas o tipo dela é mais genérico que isso. Você bate no peito e diz: “Compilador, o índice 1 do array de animais tem um cachorro, pode confiar!”. Ele faz e funciona. Agora, não há nenhuma maneira de transformar o índice 0 em uma instância de Dog ou Cat. Porque nem todo Animal é Dog e nem todo Animal é Cat. Mesmo se não existisse Dog, por exemplo, quem garante que amanhã não farão a classe Fish?

Resumindo: Uma instância de subclasse pode ser “tipada” para uma superclasse, mas você só pode “tipar” uma superclasse para uma subclasse se a instância for realmente daquele tipo.

tá…então realmente o downcast so se aplicaria a um exemplo como o definido no livro em que há um vetor com 3 animais em que uma das instâncias é um cachorro ou seja, previamente já sabiamos que se tratava de um cachorro, por isso o downcast ocorre sem problemas? Mas fazer algo como no exemplo dos exercícios é de fato impossível, não existe?

Na linha 07, aquele typecasting satisfaz o parâmetro do método go2() ? Parece que esse é o erro…

Na minha opinião o problema vai se iniciar na linha 6 quando você invoca o método go2 fornecendo um objeto Tree como primeiro argumento, isso o compilador aceita porque é o esperado mas em tempo de execução, já dentro do método go2, você tenta fazer um downcast em um objeto Tree, de Tree para Redwood, isso não é possível, não tem como, a JVM sabe que você tem um Tree naquela referência.
Já no exemplo do Animal, um exemplo de downcast seria possível se você armazenasse um objeto Dog em uma referência Animal, e depois tentasse fazer o downcast para um Dog utilizando tal.
Ex.

Animal a = new Dog();
Dog d = (Dog) a;

Em tempo de execução a JVM sabe que existe um objeto Dog na referência a, por isso o downcast do exemplo acima é possível. Espero ter ajudado =)

ajudaram sim…mto obrigado!