Non può assolutamente essere automatico: una variabile puntatore contiene al suo interno solo un numero, che indica una locazione di memoria. Quella locazione di memoria potrebbe contenere QUALSIASI tipo di informazione (una stringa, un numero, l'intestazione di un oggetto o, addirittura, un'altro puntatore!). Cos'è che dice al compilatore COSA stà puntando la variabile x? Il tipo! Questo succede anche in linguaggi come C/C++: questi linguaggi ti permettono di manipolare direttamente i puntatori e, come tutte le altre variabili, esse possono essere incrementate e decrementate. Cosa vuol dire incrementare (o decrementare) un puntatore? Significa farlo puntare alla locazione di memoria successiva. Qual è la locazione di memoria successiva? Boh: se il puntatore punta ad un valore intero di 2 byte, la locazione successiva è quella posta 2 byte dopo. Se punta ad un float di 4 byte, la locazione successiva si trova 4 byte dopo. Se punta ad un oggetto di 10 byte la locazione successiva è posta 10 byte dopo. Solo il tipo può determinare di quanto effettuare l'incremento (o decremento). E questo vale anche per Java, con l'unica differenza che in Java non si possono manipolare direttamente i puntatori (dal punto di vista del programmatore, ma per il compilatore non c'è differenza).
Quello che ha detto Xadoom è perfettamente giusto. Questa è la potenza dell'ereditarietà nella programmazione Object Oriented ed il compilatore, per poterla realizzare, deve sapere di che tipo sia la variabile che il programmatore ha dichiarato.
Ciao.