JavaRush /Java Blog /Random-JA /Java での参照型の変換
Sant9Iga
レベル 41

Java での参照型の変換

Random-JA グループに公開済み
こんにちは、ジャバラッシュさん。Java での参照型のキャストに関する質問を受けるようになりました。毎回同じことを言わないように、短い記事を書くことにしました。

まず、型キャストとは何かを見てみましょう。

型キャスト (型変換) は、ある型の変数値を別の型の値に変換することです。それが何であるか、そしてそれが何と一緒に食べられるかの例を見てみましょう。いくつかのクラス階層があります (図 1 を参照)。ここでは、階層のすべてのクラス、誰が誰を継承するか、および各クラスのメソッドを確認できます。 写真1拡張する内転と収縮する内転があります。Catこのクラスが class の子孫であることがわかりますPetPetは、クラス の後継者ですAnimal。書くとき:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
これは拡張キャスト(または暗黙的なキャスト) です。リンクanimalCatと を展開しましたanimalDog。これらはオブジェクトCatとを参照しますDog。このようなキャストでは、内にあるが 内にないanimalCat/animalDogリンクを介してメソッドを呼び出すことはできません。 縮小(または明示的) キャストは反対方向に発生します。 Cat/DogAnimal
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();
Cat cat =(Cat)animalCat;
YorkshireTerrier dog = (YorkshireTerrier) animalDog;
このオブジェクトをどの型にキャストするかを明確に示しました。 ただし、気をつけてください!!! 次のようにすると:
Animal animalCat = new Cat();
YorkshireTerrier dog = (YorkshireTerrier) animalCat;
コンパイラはこのコードをスキップします。しかし、RunTimeそれはあなたに投げかけます:
Exception in thread "main" java.lang.ClassCastException: Animals.Cat cannot be cast to Animals.YorkshireTerrier
RunTimeCat2 つの異なるクラスがあることがわかりますYorkshireTerrier。縮小変換中のClassCastExceptionを回避するには、 を使用しますinstanceof
Animal animalCat = new Cat();
if (animalCat instanceof YorkshireTerrier)
{
    YorkshireTerrier dog = (YorkshireTerrier) animalCat;
}
animalCatの場合 はYorkshireTerrier割り当てが行われ、そうでない場合は何も起こりません。

メソッドが失われ、このようなエラーが発生する可能性があるのに、なぜこれが必要なのでしょうか。

図に従って作成したコードを見てみましょう。1 . クラスAnimal
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");
    }
}
WildAnimalから継承する クラスAnimal
public abstract class WildAnimal extends Animal
{
    public void steelChicken()
    {
        System.out.println(nameOfClass+": Muhaha,I stole a chicken!");
    }
}
Petから継承する クラスAnimal
public abstract class Pet extends Animal
{
    public void peeInTray(){
        System.out.println(nameOfClass + ": Master, I peed");
    }
}
Foxから継承する クラスWildAnimal
public class Fox extends WildAnimal
{
    public void eatColobok(){
        System.out.println(nameOfClass + ": I will eat you, Colobok");
    }
}
Wolfから継承する クラスWildAnimal
public class Wolf extends WildAnimal
{
    public void hawlAtTheMoon(){
        System.out.println(nameOfClass + ": Ouuuuu!!!Ouuuu!!!");
    }
}
Catから継承する クラスPet
public class Cat extends Pet
{
    public void sleepOnKeyboard(){
        System.out.println(nameOfClass + ": Master, stop working!!I wanna sleep on your keyboard");
    }
}
YorkshireTerrierから継承する クラスPet
public class YorkshireTerrier extends Pet
{
    public void bark(){
        System.out.println(nameOfClass + ": Meow!!! Meow!!!");
    }
}
状況を想像してみてください。すべての動物を 1 つのリストに集め、餌をあげてから寝かせる必要があります。動物を作成すると、これを簡単に行うことができますArrayList( Animal)。そして、各動物に対応するメソッドを呼び出します。
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();
        }
    }
}
animalメソッドbark()または を呼び出す ことができませんsleepOnKeyboard()。シートallAnimalsには猫、オオカミ、ヨリック、キツネが含まれていますが、それらは に縮小されているためですAnimal。そして、それらは にあるメソッドのみを持っていますAnimal。これは非常に良いことです。すべてのメソッドを呼び出すことができるのであれば、なぜキーボードの上で寝るオオカミやニワトリを盗むヨリックが必要なのでしょうか。ご清聴ありがとうございました。この記事があなたのお役に立てば幸いです。批判やコメントは大歓迎です)
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION