Qual è la differenza tra up-casting e down-casting rispetto alla variabile di class

Qual è la differenza tra up-casting e down-casting rispetto alla variabile di class?

Ad esempio, nella seguente class di programma Animal contiene solo un metodo, ma la class Dog contiene due metodi, quindi come lanciamo la variabile Dog alla variabile Animal.

Se il cast è fatto, come possiamo chiamare il metodo del Cane con la variabile di 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(); } } 

    Upcasting è un casting per un supertipo, mentre downcasting è un casting per un sottotipo. L’upcasting è sempre consentito, ma il downcasting prevede un controllo del tipo e può lanciare un ClassCastException .

    Nel tuo caso, un cast da Dog to an Animal è un upcast, perché un Dog è un Animal . In generale, è ansible eseguire l’upcast ogni volta che esiste una relazione tra due classi.

    Downcasting sarebbe qualcosa del genere:

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

    Fondamentalmente quello che stai facendo è dire al compilatore che sai qual è il tipo di runtime dell’object. Il compilatore consentirà la conversione, ma inserirà comunque un controllo di runtime per assicurarsi che la conversione abbia senso. In questo caso, il cast è ansible perché in runtime l’ animal è in realtà un Dog anche se il tipo di animal statico è Animal .

    Tuttavia, se dovessi fare questo:

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

    ClassCastException un ClassCastException . Il motivo è perché il tipo di runtime di Animal è Animal , quindi quando dici al runtime di eseguire il cast vede che l’ animal non è realmente un Dog e quindi lancia una ClassCastException .

    Per chiamare il metodo di una superclass puoi fare super.method() o eseguendo il upcast.

    Per chiamare il metodo di una sottoclass devi fare un downcast. Come mostrato sopra, normalmente rischi un ClassCastException facendo questo; tuttavia, è ansible utilizzare l’operatore instanceof per verificare il tipo di runtime dell’object prima di eseguire il cast, che consente di evitare i 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; } 

    Down-casting e up-casting erano i seguenti:
    inserisci la descrizione dell'immagine qui

    Upcasting : quando vogliamo lanciare una class Sub in class Super, usiamo Upcasting (o allargamento). Succede automaticamente, non c’è bisogno di fare nulla in modo esplicito.

    Downcasting : quando vogliamo trasmettere una class Super alla class Sub, utilizziamo Downcasting (o restringimento) e Downcasting non è direttamente ansible in Java, in modo esplicito.

     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 

    Upcasting e downcasting sono una parte importante di Java, che ci consente di creare programmi complicati usando una semplice syntax e ci offre grandi vantaggi, come il polimorfismo o il raggruppamento di oggetti diversi. Java consente a un object di un tipo di sottoclass di essere trattato come object di qualsiasi tipo di superclass. Questo è chiamato upcasting. L’upcasting viene eseguito automaticamente, mentre il downcasting deve essere fatto manualmente dal programmatore , e darò il massimo per spiegare perché è così.

    Upcasting e downcasting NON sono come lanciare le primitive dall’uno all’altro, e credo che ciò causi molta confusione, quando il programmatore inizia a imparare a lanciare oggetti.

    Polymorphism: tutti i metodi in java sono virtuali per impostazione predefinita. Ciò significa che qualsiasi metodo può essere sovrascritto quando viene utilizzato nell’ereditarietà, a meno che tale metodo non sia dichiarato definitivo o statico .

    Puoi vedere l’esempio di seguito come getType(); funziona secondo il tipo dell’object (cane, animale domestico, cane poliziotto).

    Supponi di avere tre cani

    1. Cane: questa è la super class.
    2. Pet Dog – Pet Dog extends Dog.
    3. Cane della polizia – Il cane della polizia estende il cane.

       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"; } } 

    Polymorphism: tutti i metodi in java sono virtuali per impostazione predefinita. Ciò significa che qualsiasi metodo può essere sovrascritto quando viene utilizzato nell’ereditarietà, a meno che tale metodo non sia dichiarato definitivo o statico. (Spiegazione Appartiene al concetto di tabelle virtuali)

    Tabella virtuale / Tabella di spedizione: la tabella di invio di un object conterrà gli indirizzi dei metodi associati dynamicmente dell’object. Le chiamate ai metodi vengono eseguite recuperando l’indirizzo del metodo dalla tabella di invio dell’object. La tabella di distribuzione è la stessa per tutti gli oggetti appartenenti alla stessa class ed è quindi generalmente condivisa tra loro.

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

    Stampa Normal Dog

      obj2.getType(); 

    Stampa Pet Dog

      obj3.getType(); 

    Stampa Police Dog

    Downcasting deve essere fatto dal programmatore manualmente

    Quando si tenta di richiamare il secretID(); metodo su obj3 che è PoliceDog object ma con riferimento a Dog che è una super class nella gerarchia genera errore poiché obj3 non ha accesso al metodo secretId() . Per richiamare questo metodo è necessario Downcast che obj3 manualmente a PoliceDog

      ( (PoliceDog)obj3).secretID(); 

    che stampa ID

    In modo simile per richiamare il dogName(); metodo nella class PetDog è necessario downcast obj2 a PetDog poiché obj2 è riferito a Dog e non hanno accesso a dogName(); metodo

      ( (PetDog)obj2).dogName(); 

    Perché è così, che upcasting è automatico, ma downcasting deve essere manuale? Bene, vedi, l’upcasting non può mai fallire. Ma se hai un gruppo di Cani diversi e vuoi ridurli tutti a un loro tipo, allora c’è una possibilità, che alcuni di questi Cani sono in realtà di tipi diversi, cioè PetDog , PoliceDog , e il processo fallisce lanciando ClassCastException .

    Questo è il motivo per cui devi downcastare gli oggetti manualmente se hai fatto riferimento ai tuoi oggetti al tipo di super-class.

    Nota: qui per referenziamento significa che non stai cambiando l’indirizzo di memoria dei tuoi oggetti quando lo decidi, rimane lo stesso, li stai raggruppando in un particolare tipo in questo caso.

    So che questa domanda è stata fatta molto tempo fa ma per i nuovi utenti di questa domanda. Si prega di leggere questo articolo dove contiene la descrizione completa su upcasting, downcasting e uso dell’operatore instanceof

    • Non c’è bisogno di upcast manualmente, succede da solo:

      Mammal m = (Mammal)new Cat(); uguale a Mammal m = new Cat();

    • Ma downcasting deve sempre essere fatto manualmente:

       Cat c1 = new Cat(); Animal a = c1; //automatic upcasting to Animal Cat c2 = (Cat) a; //manual downcasting back to a Cat 

    Perché è così, che upcasting è automatico, ma downcasting deve essere manuale? Bene, vedi, l’upcasting non può mai fallire. Ma se hai un gruppo di Animali diversi e vuoi ridurli tutti a un Gatto, allora c’è una possibilità, che alcuni di questi Animali sono in realtà Cani, e il processo fallisce lanciando ClassCastException. Questo è dove dovrebbe introdurre una funzionalità utile chiamata “instanceof” , che verifica se un object è un’istanza di qualche class.

      Cat c1 = new Cat(); Animal a = c1; //upcasting to Animal if(a instanceof Cat){ // testing if the Animal is a Cat System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure."); Cat c2 = (Cat)a; } 

    Per maggiori informazioni leggi questo articolo

    Meglio provare questo metodo per upcasting, è facile da capire:

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

    Forse questo tavolo aiuta. Chiamare il metodo callme() della class Parent o class Child . Come principio:

    UPCASTING -> Nascondere

    DOWNCASTING -> Rivelazione

    inserisci la descrizione dell'immagine qui

    inserisci la descrizione dell'immagine qui

    inserisci la descrizione dell'immagine qui

    Parent: Car
    Bambino: Figo
    Car c1 = new Figo ();

    =====
    Upcasting: –
    Metodo: L’object c1 farà riferimento a Methods of Class (Figo – Method deve essere sovrascritto) perché la class “Figo” è specificata con “new”.
    Variabile di istanza: l’object c1 farà riferimento alla variabile di istanza della class di dichiarazione (“Car”).

    Quando la class Declaration è genitore e l’object viene creato da child, avviene il casting implicito che è “Upcasting”.

    ======
    Downcasting: –
    Figo f1 = (Figo) c1; //
    Metodo: l’object f1 farà riferimento a Method of Class (figo) come object iniziale c1 creato con la class “Figo”. ma una volta terminata la trasmissione, i metodi che sono presenti solo nella class “Figo” possono anche essere riferiti dalla variabile f1.
    Variabile di istanza: l’object f1 non farà riferimento alla variabile di istanza della class di dichiarazione dell’object c1 (la class di dichiarazione per c1 è CAR) ma con il downstart farà riferimento alle variabili di istanza della class Figo.

    ======
    Usa: Quando l’object è di class figlio e la class di dichiarazione è la class padre e figlio desidera accedere alla variabile istanza della propria class e non della class genitore, quindi può essere eseguita con “Downcasting”.

    upcasting significa lanciare l’object in un supertipo, mentre downcasting significa lanciare un sottotipo.

    In Java, l’upcasting non è necessario perché è fatto automaticamente. E di solito si parla di casting implicito. Puoi specificarlo per renderlo chiaro agli altri.

    Quindi, scrivendo

     Animal a = (Animal)d; 

    o

     Animal a = d; 

    porta esattamente allo stesso punto e in entrambi i casi verrà eseguito il callme() da Dog .

    Downcasting è invece necessario perché hai definito a object di Animal. Al momento sai che è un Dog , ma java non ha garanzie è. In realtà in fase di esecuzione potrebbe essere diverso e java genererà una ClassCastException , se ciò accadesse. Ovviamente non è il caso del tuo esempio esemplare. Se non si esegue il cast in Animal , java non potrebbe nemmeno compilare l’applicazione perché Animal non ha il metodo callme2() .

    Nel tuo esempio non puoi raggiungere il codice di callme() di Animal da UseAnimlas (perché il Dog sovrascrive) a meno che il metodo non sia il seguente:

     class Dog extends Animal { public void callme() { super.callme(); System.out.println("In callme of Dog"); } ... } 

    Possiamo creare oggetti a Downcasting. Anche in questo tipo : chiamare i metodi della class base

     Animal a=new Dog(); a.callme(); ((Dog)a).callme2();