JavaRush /Blog Java /Random-PL /Konwersja typów referencyjnych w Javie
Sant9Iga
Poziom 41

Konwersja typów referencyjnych w Javie

Opublikowano w grupie Random-PL
Dzień dobry, człowieku z Javarasha. Zacząłem otrzymywać pytania dotyczące rzutowania typów referencyjnych w Javie. Aby nie powtarzać za każdym razem tego samego, postanowiłem napisać krótki artykuł.

Najpierw przyjrzyjmy się, jaki jest typ castingu.

Rzutowanie typów (konwersja typów) to konwersja wartości zmiennej jednego typu na wartość innego typu. Spójrzmy na przykład, czym jest i z czym jest spożywany. Mamy pewną hierarchię klas ( patrz rysunek 1 ). Tutaj możesz zobaczyć wszystkie klasy w hierarchii, kto dziedziczy kogo i metody każdej klasy. Obrazek 1Występuje rozszerzanie i kurczenie się przywodzenia. Widzimy, że klasa Catjest potomkiem klasy Pet. Petz kolei jest następcą klasy Animal. Kiedy piszemy:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
Jest to obsada rozszerzająca się (lub ukryta). Rozszerzyliśmy linki animalCati animalDog. Odnoszą się do obiektów Cati Dog. Przy takim rzutowaniu nie możemy animalCat/animalDogwywoływać metod poprzez referencje, które znajdują się w Cat/Dog, ale których w nim nie ma Animal. Zawężający się (lub wyraźny) rzut występuje w przeciwnym kierunku:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
Cat cat =(Cat)animalCat;
YorkshireTerrier dog = (YorkshireTerrier) animalDog;
Jasno wskazaliśmy na jaki typ chcemy rzucić ten obiekt. ALE BĄDŹ OSTROŻNY!!! Jeśli zrobisz to w ten sposób:
Animal animalCat = new Cat();
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
kompilator pominie ten kod. Ale RunTimewyrzuci ci:
Exception in thread "main" java.lang.ClassCastException: Animals.Cat cannot be cast to Animals.YorkshireTerrier
RunTimewidzi, że Catistnieją YorkshireTerrierdwie różne klasy. Aby uniknąć wyjątku ClassCastException podczas zawężania konwersji, użyj instanceof.
Animal animalCat = new Cat();
if (animalCat instanceof YorkshireTerrier)
{
    YorkshireTerrier dog = (YorkshireTerrier) animalCat;
}
Jeśli animalCattak YorkshireTerrier, to przypisanie nastąpi, jeśli nie, nic się nie stanie.

Dlaczego jest to konieczne, jeśli tracimy metody i możemy uzyskać takie błędy

Spójrzmy na kod, który wykonałem według schematu na ryc. 1 . KlasaAnimal
public abstract class Animal
{
    String name;
    int age;
    String nameOfClass = getClass().getSimpleName();
    public void eat(){
        System.out.println(nameOfClass + ": Omnomnom");
    }
    public void sleep(){
        System.out.println(nameOfClass + ": Z-z-z-z");
    }
}
Klasa WildAnimal, z której dziedziczyAnimal
public abstract class WildAnimal extends Animal
{
    public void steelChicken()
    {
        System.out.println(nameOfClass+": Muhaha,I stole a chicken!");
    }
}
Klasa Pet, z której dziedziczyAnimal
public abstract class Pet extends Animal
{
    public void peeInTray(){
        System.out.println(nameOfClass + ": Master, I peed");
    }
}
Klasa Fox, z której dziedziczyWildAnimal
public class Fox extends WildAnimal
{
    public void eatColobok(){
        System.out.println(nameOfClass + ": I will eat you, Colobok");
    }
}
Klasa Wolf, z której dziedziczyWildAnimal
public class Wolf extends WildAnimal
{
    public void hawlAtTheMoon(){
        System.out.println(nameOfClass + ": Ouuuuu!!!Ouuuu!!!");
    }
}
Klasa Cat, z której dziedziczyPet
public class Cat extends Pet
{
    public void sleepOnKeyboard(){
        System.out.println(nameOfClass + ": Master, stop working!!I wanna sleep on your keyboard");
    }
}
Klasa YorkshireTerrier, z której dziedziczyPet
public class YorkshireTerrier extends Pet
{
    public void bark(){
        System.out.println(nameOfClass + ": Meow!!! Meow!!!");
    }
}
Wyobraź sobie sytuację. Musimy zebrać wszystkie zwierzęta na jedną listę, nakarmić je, a następnie położyć do łóżka. Łatwo to zrobić, jeśli stworzymy ArrayListzwierzęta ( Animal). A następnie wywołujemy odpowiednie metody dla każdego zwierzęcia:
public class ZOO
{
    public static void main(String[] args)
    {
        List<Animal> allAnimals = new ArrayList<>();
        allAnimals.add(new Cat());
        allAnimals.add(new Wolf());
        allAnimals.add(new Fox());
        allAnimals.add(new YorkshireTerrier());
        for (Animal animal : allAnimals)
        {
            animal.eat();
            animal.sleep();
        }
    }
}
Nie mogę animalwywołać metody bark()lub sleepOnKeyboard(). Ponieważ arkusz allAnimalszawiera kota, wilka, yorika i lisa, ale są one zredukowane do Animal. I mają tylko metody, które są w Animal. To bardzo dobrze, bo gdybyśmy mogli wywołać wszystkie metody, to po co nam wilk, który śpi na klawiaturze, albo yorick, który kradnie kurczaki? Dziękuję za uwagę. Mam nadzieję, że ten artykuł będzie dla Ciebie przydatny. Krytyka i komentarze mile widziane)
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION