Rzutowanie w Javie nie jest magią, to ty mówisz kompilatorowi, że obiekt typu A jest w rzeczywistości bardziej specyficznym typem B, a tym samym uzyskujesz dostęp do wszystkich metod na B, których nie miałbyś w innym przypadku. Podczas rzucania nie wykonujesz żadnej magii ani konwersji, po prostu mówisz kompilatorowi „zaufaj mi, wiem co robię i mogę zagwarantować, że ten obiekt w tej linii jest w rzeczywistości rzutem <Wstaw rzut wpisz tutaj>. ” Na przykład:
Object o = "str";
String str = (String)o;
Powyższe jest w porządku, nie magiczne i wszystko w porządku. Obiekt przechowywany w o jest w rzeczywistości łańcuchem, dzięki czemu możemy bez problemu rzutować na łańcuch.
Może to się nie udać na dwa sposoby. Po pierwsze, jeśli rzucasz między dwoma typami w zupełnie różnych hierarchiach dziedziczenia, kompilator będzie wiedział, że jesteś głupi i cię powstrzyma:
String o = "str";
Integer str = (Integer)o;
Po drugie, jeśli są w tej samej hierarchii, ale nadal są nieprawidłowym rzutowaniem, ClassCastException
zostanie wyrzucony w czasie wykonywania:
Number o = new Integer(5);
Double n = (Double)o;
Zasadniczo oznacza to, że naruszyłeś zaufanie kompilatora. Powiedziałeś mu, że możesz zagwarantować, że obiekt jest określonego typu, a tak nie jest.
Dlaczego potrzebujesz odlewania? Cóż, na początek potrzebujesz go tylko wtedy, gdy przechodzisz od bardziej ogólnego typu do bardziej szczegółowego. Na przykład Integer
dziedziczy z Number
, więc jeśli chcesz zapisać Integer
jako a, Number
to jest w porządku (ponieważ wszystkie liczby całkowite są liczbami) .Jeśli jednak chcesz pójść w drugą stronę, potrzebujesz rzutu - nie wszystkie liczby są liczbami całkowitymi (również As Integer mamy Double
, Float
, Byte
, Long
, itd.), a nawet jeśli jest tylko jedna podklasa w projekcie lub JDK, ktoś może łatwo tworzyć inny i rozprowadzać, że tak nie masz gwarancji, nawet jeśli uważasz, że jest to jedno, oczywistym wyborem !
Jeśli chodzi o użycie do przesyłania, nadal widzisz potrzebę tego w niektórych bibliotekach. Przed Java-5 był używany intensywnie w kolekcjach i różnych innych klasach, ponieważ wszystkie kolekcje pracowały nad dodawaniem obiektów, a następnie rzutowaniem wyniku, który otrzymałeś z kolekcji. Jednak wraz z pojawieniem się generyków wiele użycia do rzutowania zniknęło - zostało zastąpione przez generyczne, które zapewniają znacznie bezpieczniejszą alternatywę, bez potencjału ClassCastExceptions (w rzeczywistości, jeśli używasz generyków w czysty sposób i kompiluje się bez ostrzeżeń, masz gwarancję, że nigdy nie otrzymasz wyjątku ClassCastException.)