クラス変数に関するアップキャストとダウンキャストの違いは何ですか?
たとえば、次のプログラムでは、Animal クラスにはメソッドが 1 つしか含まれませんが、Dog クラスにはメソッドが 2 つ含まれます。Dog 変数を Animal 変数にキャストする方法を説明します。
キャストが行われた場合、Animal の変数を使用して Dog の別のメソッドを呼び出すにはどうすればよいですか。
class Animal
{
public void callme()
{
System.out.println("In callme of Animal");
}
}
class Dog extends Animal
{
public void callme()
{
System.out.println("In callme of Dog");
}
public void callme2()
{
System.out.println("In callme2 of Dog");
}
}
public class UseAnimlas
{
public static void main (String [] args)
{
Dog d = new Dog();
Animal a = (Animal)d;
d.callme();
a.callme();
((Dog) a).callme2();
}
}
ベストアンサー1
アップキャストはスーパータイプへのキャストであり、ダウンキャストはサブタイプへのキャストです。アップキャストは常に許可されますが、ダウンキャストには型チェックが含まれ、エラーがスローされる可能性がありますClassCastException
。
Dog
あなたの場合、 a からan へのキャストAnimal
はアップキャストです。なぜなら、 a はDog
is-aだからAnimal
です。一般に、 2 つのクラス間に is-a 関係がある場合はいつでもアップキャストできます。
ダウンキャストは次のようになります。
Animal animal = new Dog();
Dog castedDog = (Dog) animal;
基本的にあなたがやっていることは、オブジェクトの実行時型が何であるかをコンパイラに伝えることです本当にです。コンパイラは変換を許可しますが、変換が意味をなすかどうかを確認するために実行時の妥当性チェックを挿入します。この場合、 の静的型が であるにもかかわらず、実行時には が実際には であるため、キャストが可能animal
です。Dog
animal
Animal
ただし、次のようにすると:
Animal animal = new Animal();
Dog notADog = (Dog) animal;
が返されますClassCastException
。その理由は、animal
のランタイム型が であるためですAnimal
。そのため、ランタイムにキャストを実行するように指示すると、 はanimal
実際には ではないと判断され、Dog
がスローされますClassCastException
。
スーパークラスのメソッドを呼び出すには、super.method()
アップキャストを実行するか、 を実行します。
サブクラスのメソッドを呼び出すには、ダウンキャストを行う必要があります。上記のように、ClassCastException
これを行うと通常は のリスクが発生します。ただし、instanceof
演算子を使用して、キャストを実行する前にオブジェクトの実行時型をチェックすることで、ClassCastException
を防ぐことができます。
Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
// Guaranteed to succeed, barring classloader shenanigans
Dog castedDog = (Dog) animal;
}
Java 16では、ダウンキャストをより簡潔に表現できるようになりました。パターンマッチングinstanceof
:
Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog castedDog) {
// now castedDog is available here as in the example above
}