Zastanawiam się, czy ktoś mógłby mi powiedzieć, jak działa casting? Rozumiem, kiedy powinienem to zrobić, ale tak naprawdę nie wiem, jak to działa. Częściowo rozumiem prymitywne typy danych, ale jeśli chodzi o rzutowanie obiektów, nie rozumiem, jak to działa.
Jak można nagle rzutować obiekt typu Object na, powiedzmy, MyType
(tylko przykład), a następnie pobrać wszystkie metody?
Odpowiedzi:
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; //Compilation fails here
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; //ClassCastException thrown here
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 zNumber
, 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 mamyDouble
,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.)
źródło
Double.valueOf(gpsLastLoc.getLatitude()).getClass().getSimpleName()
. W obu przypadkach nie powinieneś nigdy potrzebować dynamicznego pobierania klasy prymitywu, ponieważ jeśligetLatitude()
zwraca podwójny prymityw, zawsze wiesz, że będzie on promowany doDouble
obiektu.Właściwie casting nie zawsze działa. Jeśli obiekt nie jest
instanceof
klasą, do której go przesyłasz, otrzymaszClassCastException
w czasie wykonywania.źródło
Załóżmy, że chcesz rzutować a
String
na aFile
(tak, to nie ma żadnego sensu), nie możesz rzutować bezpośrednio, ponieważFile
klasa nie jest dzieckiem ani rodzicemString
klasy (i kompilator narzeka).Ale możesz rzucić
String
naObject
, ponieważ aString
jestObject
(Object
jest rodzicem). Następnie możesz rzucić ten obiekt na aFile
, ponieważ File toObject
.Więc wszystkie twoje operacje są „legalne” z punktu widzenia pisania w czasie kompilacji, ale nie oznacza to, że będą działać w czasie wykonywania!
File f = (File)(Object) "Stupid cast";
Kompilator pozwoli na to, nawet jeśli nie ma to sensu, ale ulegnie awarii w czasie wykonywania z następującym wyjątkiem:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.io.File
źródło
Rzutowanie referencji będzie działać tylko wtedy, gdy jest to
instanceof
ten typ. Nie możesz przesyłać losowych odniesień. Musisz też przeczytać więcejCasting Objects
.na przykład
String string = "String"; Object object = string; // Perfectly fine since String is an Object String newString = (String)object; // This only works because the `reference` object is pointing to a valid String object.
źródło
Właściwy sposób jest następujący:
Ta metoda
cast()
jest znacznie bezpieczniejszą alternatywą dla rzutowania w czasie kompilacji.źródło