154

クラス変数に関するアップキャストとダウンキャストの違いは何ですか?

たとえば、次のプログラム クラスの Animal にはメソッドが 1 つしか含まれていませんが、Dog クラスには 2 つのメソッドが含まれています。次に、Dog 変数を Animal 変数にキャストする方法を示します。

キャストが完了したら、動物の変数を使用して犬の別のメソッドを呼び出すにはどうすればよいでしょうか。

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();
    }
}
4

10 に答える 10

241

アップキャストはスーパータイプへのキャストであり、ダウンキャストはサブタイプへのキャストです。アップキャストは常に許可されますが、ダウンキャストには型チェックが含まれ、ClassCastException.

あなたの場合、 aDogから an へのキャストは、 a is-aAnimalであるため、アップキャストです。一般に、2 つのクラス間に is-a 関係がある場合はいつでもアップキャストできます。DogAnimal

ダウンキャストは次のようになります。

Animal animal = new Dog();
Dog castedDog = (Dog) animal;

基本的にあなたがしていることは、オブジェクトの実行時の型が実際に何であるかを知っていることをコンパイラーに伝えることです。コンパイラは変換を許可しますが、変換が適切であることを確認するために実行時のサニティ チェックを挿入します。この場合、実行時にの静的型がisであってもanimal実際にはであるため、キャストが可能です。DoganimalAnimal

ただし、これを行う場合:

Animal animal = new Animal();
Dog notADog = (Dog) animal;

あなたはClassCastException. その理由は、animalのランタイム タイプがAnimalであるためです。そのため、ランタイムにキャストを実行するように指示すると、animal実際には a ではないことがわかり、 aDogがスローされClassCastExceptionます。

スーパークラスのメソッドを呼び出すには、super.method()またはアップキャストを実行します。

サブクラスのメソッドを呼び出すには、ダウンキャストを行う必要があります。上記のように、通常、ClassCastExceptionこれを行うことでリスクが発生します。ただし、instanceof演​​算子を使用して、キャストを実行する前にオブジェクトの実行時の型を確認できます。これにより、ClassCastExceptionsを防ぐことができます。

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 以降では、ダウンキャストをより簡潔に表現できます。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
}
于 2014-05-01T19:12:42.430 に答える
68

ダウンキャストとアップキャストは次のとおりです。
ここに画像の説明を入力

Upcasting : Sub class を Super class にキャストする場合、Upcasting (または widening) を使用します。これは自動的に行われ、明示的に何もする必要はありません。

ダウンキャスト: スーパー クラスをサブ クラスにキャストする場合は、ダウンキャスト (またはナローイング) を使用します。Java では直接ダウンキャストを行うことはできません。明示的に行う必要があります。

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException

オートボクシング vs キャスティング

于 2016-01-21T07:02:54.523 に答える
34

アップキャストとダウンキャストは Java の重要な部分であり、単純な構文を使用して複雑なプログラムを構築することを可能にし、ポリモーフィズムや異なるオブジェクトのグループ化などの大きな利点をもたらします。Java では、サブクラス タイプのオブジェクトを任意のスーパークラス タイプのオブジェクトとして扱うことができます。これをアップキャストと呼びます。アップキャストは自動的に行われますが、ダウンキャストはプログラマーが手動で行う必要があります。その理由を説明するために最善を尽くします。

アップキャストとダウンキャストは、プリミティブをあるものから別のものにキャストするようなものではありません。プログラマーがオブジェクトのキャストを学び始めると、それが多くの混乱を引き起こすと思います。

ポリモーフィズム: Java のすべてのメソッドは、デフォルトで仮想です。つまり、そのメソッドが final または static として宣言されていない限り、継承で使用される場合、任意のメソッドをオーバーライドできます

以下の例でgetType();は、オブジェクト (犬、ペット、警察犬) の種類に応じてどのように機能するかを確認できます。

あなたが3匹の犬を飼っているとします

  1. 犬 - これはスーパー クラスです。

  2. ペットの犬 - ペットの犬は犬を拡張します。

  3. 警察犬 - 警察犬はペット犬を拡張します。

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }
    

ポリモーフィズム: Java のすべてのメソッドは、デフォルトで仮想です。これは、そのメソッドが final または static として宣言されていない限り、継承で使用されるときに任意のメソッドをオーバーライドできることを意味します。(説明は仮想テーブルの概念に属します)

仮想テーブル / ディスパッチ テーブル : オブジェクトのディスパッチ テーブルには、オブジェクトの動的にバインドされたメソッドのアドレスが含まれます。メソッド呼び出しは、オブジェクトのディスパッチ テーブルからメソッドのアドレスをフェッチすることによって実行されます。ディスパッチ テーブルは、同じクラスに属するすべてのオブジェクトで同じであるため、通常はオブジェクト間で共有されます。

public static void main (String[] args) {
      /**
       * Creating the different objects with super class Reference
       */
     Dog obj1 = new Dog();
`         /**
           *  Object of Pet Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry about it 
           *  
           */
     Dog obj2 = new PetDog();
`         /**
           *  Object of Police Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry       
           *  about it here even though we are extending PoliceDog with PetDog 
           *  since PetDog is extending Dog Java automatically upcast for us 
           */
      Dog obj3 = new PoliceDog();
}



 obj1.getType();

版画Normal Dog

  obj2.getType();

版画Pet Dog

 obj3.getType();

版画Police Dog

ダウンキャストは、プログラマーが手動で行う必要があります

階層内のスーパークラスであるが参照されているメソッドを呼び出そうとすると、メソッドにアクセスできないため、エラーがスローsecretID();されます。そのメソッドを呼び出すには、obj3 を手動でダウンキャストする必要があります。obj3PoliceDog objectDogobj3secretId() PoliceDog

  ( (PoliceDog)obj3).secretID();

印刷するID

obj2 が参照され、メソッドにアクセスできないため、ダウンキャストする必要があるクラスでdogName();メソッドを呼び出すのと同様の方法でPetDogobj2PetDogDogdogName();

  ( (PetDog)obj2).dogName();

アップキャストは自動であるのに、ダウンキャストは手動でなければならないのはなぜですか? アップキャストが失敗することはありません。しかし、異なる Dog のグループがあり、それらすべてをそれぞれのタイプにダウンキャストしたい場合、これらの Dog の一部が実際には異なるタイプ、つまり 、PetDogPoliceDogあり、 をスローしてプロセスが失敗する可能性がありますClassCastException

これが、オブジェクトをスーパー クラス タイプに参照している場合に、オブジェクトを手動でダウンキャストする必要がある理由です。

注:ここでの参照とは、オブジェクトをダウンキャストするときにオブジェクトのメモリアドレスを変更していないことを意味します。この場合、オブジェクトを特定のタイプにグループ化するだけです。Dog

于 2015-09-27T22:46:08.803 に答える
6

アップキャストにはこの方法を試してみてください。理解しやすいです。

/* upcasting problem */
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) 
    {
        Animal animal = new Animal ();
        Dog dog = new Dog();
        Animal ref;
        ref = animal;
        ref.callme();
        ref = dog;
        ref.callme();
    }
}
于 2014-09-19T13:40:00.277 に答える
2

親: Car
子: Figo
Car c1 = new Figo();

===== Upcasting
:-
Method: クラス "Figo" が "new" で指定されているため、オブジェクト c1 はクラスのメソッド (Figo - メソッドをオーバーライドする必要があります) を参照します。
インスタンス変数: オブジェクト c1 は宣言クラス ("Car") のインスタンス変数を参照します。

Declaration クラスが親であり、オブジェクトが子から作成されると、「アップキャスト」である暗黙のキャストが発生します。

======
ダウンキャスティング:-
フィーゴ f1 = (フィーゴ) c1; //
メソッド: オブジェクト f1 は、最初のオブジェクト c1 がクラス "Figo" で作成されるため、クラス (figo) のメソッドを参照します。ただし、ダウン キャストが完了すると、クラス "Figo" にのみ存在するメソッドも変数 f1 で参照できます。
インスタンス変数: オブジェクト f1 は、オブジェクト c1 の Declaration クラスのインスタンス変数を参照しません (c1 の宣言クラスは CAR です) が、ダウン キャストでは、クラス Figo のインスタンス変数を参照します。

======
用途: オブジェクトが子クラスで宣言クラスが親で、子クラスが親クラスではなく自身のクラスのインスタンス変数にアクセスしたい場合、「ダウンキャスト」で実行できます。

于 2015-08-07T06:40:46.487 に答える
1

アップキャストはオブジェクトをスーパータイプにキャストすることを意味し、ダウンキャストはサブタイプにキャストすることを意味します。

Java では、自動的に行われるため、アップキャストは必要ありません。そして、それは通常、暗黙的なキャストと呼ばれます。他の人にわかりやすいように指定できます。

したがって、書く

Animal a = (Animal)d;

また

Animal a = d;

はまったく同じポイントにつながり、どちらの場合もcallme()fromが実行されDogます。

aAnimal のオブジェクトとして定義したため、代わりにダウンキャストが必要です。現在、それが であることはわかっていますDogが、Java にはそれが保証されていません。実際には実行時に異なる可能性があり、Java は をスローしClassCastExceptionます。もちろん、あなたの非常にサンプルの例には当てはまりません。にキャストaしないと、メソッドがないAnimalため、Java はアプリケーションをコンパイルすることさえできません。Animalcallme2()

あなたの例では、メソッドが次のようにならない限り、 from のコードに到達できません(上書きするcallme()ためAnimal) UseAnimlas:Dog

class Dog extends Animal 
{ 
    public void callme()
    {
        super.callme();
        System.out.println("In callme of Dog");
    }
    ... 
} 
于 2014-05-01T19:26:20.693 に答える
0

ダウンキャストするオブジェクトを作成できます。こちらのタイプも。: 基本クラス メソッドの呼び出し

Animal a=new Dog();
a.callme();
((Dog)a).callme2();
于 2016-02-22T07:09:43.677 に答える