No: anim e' un riferimento a un oggetto di tipo Animale, che punta a un oggetto, prima di tipo Cane, poi di tipo Gatto. Ma il suo tipo rimane Animale.
Quello postato da te e' un esempio in cui il polimorfismo non viene sfruttato. Avresti potuto dichiarare una variabile di tipo Cane e una di tipo Gatto.
Scrivendo invece:
si capisce l'utilita' del binding dinamico.codice:Animale[] anim = {new Cane(), new Gatto()}; for (i=0; i<anim.length; ++i) anim[i].emetteVerso();
Se il tuo dubbio era solo sul fatto che il compilatore non ottimizza il codice, ricordati che Java e' un linguaggio orientato al multitasking. Nessuno ti assicura che la sequenza:
non venga interrotta dall'esecuzione di un altro thread che vada a modificare anim.codice:anim=new Cane(); anim.emetteVerso();