Upcasting jest dozwolony w Javie, jednak downcasting powoduje błąd kompilacji.
Błąd kompilacji można usunąć, dodając rzutowanie, ale i tak zepsuje się w czasie wykonywania.
W takim przypadku, dlaczego Java pozwala na downcasting, jeśli nie można go wykonać w czasie wykonywania?
Czy istnieje praktyczne zastosowanie tej koncepcji?
public class demo {
public static void main(String a[]) {
B b = (B) new A(); // compiles with the cast,
// but runtime exception - java.lang.ClassCastException
}
}
class A {
public void draw() {
System.out.println("1");
}
public void draw1() {
System.out.println("2");
}
}
class B extends A {
public void draw() {
System.out.println("3");
}
public void draw2() {
System.out.println("4");
}
}
Odpowiedzi:
Downcasting jest dozwolony, jeśli istnieje możliwość, że się powiedzie w czasie wykonywania:
W niektórych przypadkach to się nie powiedzie:
Gdy rzutowanie (takie jak ten ostatni) zawiedzie w czasie wykonywania,
ClassCastException
zostanie wyrzucony.W innych przypadkach będzie działać:
Pamiętaj, że niektóre rzutowania będą niedozwolone w czasie kompilacji, ponieważ nigdy się nie powiedzie:
źródło
Object o = new Object(); String s = (String) o;
Działa dla mnie dobrze ..: O Jak?Korzystając z Twojego przykładu, możesz:
źródło
Uważam, że dotyczy to wszystkich języków o typie statycznym:
Typecast skutecznie mówi: załóżmy, że jest to odwołanie do klasy obsady i używaj go jako takiego. Załóżmy teraz, że o jest naprawdę liczbą całkowitą, przy założeniu, że jest to ciąg znaków, który nie ma sensu i da nieoczekiwane wyniki, dlatego konieczne jest sprawdzenie środowiska wykonawczego i wyjątek, aby powiadomić środowisko wykonawcze, że coś jest nie tak.
W praktyce możesz napisać kod działający na bardziej ogólnej klasie, ale rzuć go do podklasy, jeśli wiesz, co to jest za podklasę i musisz traktować ją jako taką. Typowym przykładem jest przesłanianie Object.equals (). Załóżmy, że mamy klasę dla samochodów:
źródło
Wszyscy widzimy, że podany kod nie będzie działał w czasie wykonywania. To dlatego, że wiemy, że wyrażenie nigdy nie
new A()
może być obiektem typu .B
Ale nie tak to widzi kompilator. Kiedy kompilator sprawdza, czy rzutowanie jest dozwolone, po prostu widzi to:
I jak wykazali inni, ten rodzaj obsady jest całkowicie legalny. Wyrażenie po prawej stronie może bardzo dobrze ocenić obiekt typu
B
. Kompilator widzi toA
iB
ma relację podtypu, więc w widoku kodu wyrażenia wyrażenie może działać.Kompilator nie bierze pod uwagę szczególnego przypadku, gdy dokładnie wie , jaki typ obiektu
expression_of_type_A
rzeczywiście będzie miał. Po prostu widzi typ statyczny jakoA
i uważa, że typem dynamicznym może byćA
dowolny potomekA
, w tymB
.źródło
Wierzę, że dzieje się tak, ponieważ kompilator nie ma możliwości sprawdzenia w czasie kompilacji, czy rzutowanie się powiedzie, czy nie. Na przykład łatwo zauważyć, że rzutowanie zakończy się niepowodzeniem, ale w innych przypadkach nie jest to tak jasne.
Na przykład wyobraź sobie, że wszystkie typy B, C i D rozszerzają typ A, a następnie metoda
public A getSomeA()
zwraca instancję B, C lub D w zależności od losowo wygenerowanej liczby. Kompilator nie może wiedzieć, który dokładnie typ wykonania zostanie zwrócony tą metodą, więc jeśli później rzutujesz wynikiB
, nie ma sposobu, aby dowiedzieć się, czy rzutowanie zakończy się powodzeniem (czy niepowodzeniem). Dlatego kompilator musi założyć, że rzutowanie się powiedzie.źródło
@ Oryginalny plakat - patrz komentarze w tekście.
źródło
Downcast działa w przypadku, gdy mamy do czynienia z upcastowanym obiektem. Upcasting:
Więc teraz to
objValue
zmienna może być zawsze downcasted sięint
, ponieważ obiekt, który został odlany jestInteger
,ale ponieważ
objValue
jest Przedmiotem, na który nie można go rzucić,String
ponieważint
nie można go rzucićString
.źródło
Downcasting jest bardzo przydatny w poniższym fragmencie kodu, którego używam cały czas. W ten sposób udowodniono, że downcasting jest przydatny.
Przechowuję ciąg na liście połączonej. Kiedy pobieram elementy listy połączonej, obiekty są zwracane. Aby uzyskać dostęp do elementów jako ciągów (lub dowolnych innych obiektów klasy), downcasting pomaga mi.
Java pozwala nam skompilować kod downcast, ufając nam, że robimy coś złego. Jeśli jednak ludzie popełnią błąd, zostanie on złapany w czasie wykonywania.
źródło
void*
wskaźników w C ++. To nie brzmi dla mnie jak dobry pomysł.Rozważ poniższy przykład
tutaj tworzymy obiekt podklasy Bone i przypisujemy go do referencji superklasy AOne, a teraz referencja superklasy nie wie o metodzie method2 w podklasie, tj. Bone w czasie kompilacji. dlatego musimy sprowadzić to odwołanie superklasy do referencji podklasy, tak aby wynikowe odniesienie może wiedzieć o obecności metod w podklasie, tj. kości
źródło
Aby przeprowadzić downcasting w Javie i uniknąć wyjątków w czasie wykonywania, zapoznaj się z następującym kodem:
Tutaj Animal jest klasą nadrzędną, a Dog jest klasą podrzędną.
instanceof jest słowem kluczowym używanym do sprawdzania, czy zmienna referencyjna zawiera dany typ referencji do obiektu, czy nie.
źródło
Transformacja obiektów w dół nie jest możliwa. Tylko
jest możliwe
źródło