Downcasting en Java

Upcasting est autorisé en Java, cependant downcasting donne une erreur de compilation.

l'erreur de compilation peut être supprimée en ajoutant un cast, mais se briserait de toute façon à l'exécution.

dans ce cas, pourquoi Java autorise la downcasting si elle ne peut pas être exécutée à l'exécution?

Ce concept a-t-il une utilité pratique?

public class demo {
  public static void main(String a[]) {
      B b = (B) new A(); // compiles with the cast, 
                         // but runtime exception - java.lang.ClassCastException
  }
}

class A {
  public void draw() {
    System.out.println("1");
  }

  public void draw1() {
    System.out.println("2");
  }
}

class B extends A {
  public void draw() {
    System.out.println("3");
  }
  public void draw2() {
    System.out.println("4");
  }
}
159
demandé sur Pshemo 2008-12-19 15:11:44

9 réponses

Passer est autorisé lorsqu'il y a une possibilité qu'il réussit au moment de l'exécution:

Object o = getSomeObject(),
String s = (String) o; // this is allowed because o could reference a String

Dans certains cas, cela ne réussira pas:

Object o = new Object();
String s = (String) o; // this will fail at runtime, because o doesn't reference a String

dans d'autres il fonctionnera:

Object o = "a String";
String s = (String) o; // this will work, since o references a String

Lorsqu'un moulage (comme celui-ci) échoue à l'exécution, un ClassCastException sera lancé.

notez que certaines distributions seront refusées au moment de la compilation, car elles jamais réussir du tout:

Integer i = getSomeInteger();
String s = (String) i; // the compiler will not allow this, since i can never reference a String.
273
répondu Joachim Sauer 2018-09-19 11:17:12

en utilisant votre exemple, vous pouvez faire:

public void doit(A a) {
    if(a instanceof B) {
        // needs to cast to B to access draw2 which isn't present in A
        // note that this is probably not a good OO-design, but that would
        // be out-of-scope for this discussion :)
        ((B)a).draw2();
    }
    a.draw();
}
16
répondu Rolf Rander 2008-12-19 13:08:04

je crois que cela s'applique à tous les langages statiquement typés:

String s = "some string";
Object o = s; // ok
String x = o; // gives compile-time error, o is not neccessarily a string
String x = (String)o; // ok compile-time, but might give a runtime exception if o is not infact a String

le typecast dit effectivement: supposons qu'il s'agisse d'une référence à la classe de fonte et utilisez-la comme telle. Maintenant, disons que o est vraiment un entier, en supposant qu'il s'agisse d'une chaîne de caractères n'a aucun sens et donnera des résultats inattendus, donc il faut qu'il y ait une vérification d'exécution et une exception pour notifier à l'environnement d'exécution que quelque chose ne va pas.

In utilisation pratique, vous pouvez écrire du code travaillant sur une classe plus générale, mais jetez-le dans une sous-classe si vous savez de quelle sous-classe il s'agit et si vous avez besoin de le traiter comme tel. Un exemple typique est primordial d'Objet.égal.)( Supposons que nous ayons une classe pour la voiture:

@Override
boolean equals(Object o) {
    if(!(o instanceof Car)) return false;
    Car other = (Car)o;
    // compare this to other and return
}
14
répondu Rolf Rander 2014-01-21 23:19:51

nous pouvons tous voir que le code que vous avez fourni ne fonctionnera pas à l'exécution. C'est parce que nous savons que l'expression new A() peut jamais être un objet de type B .

mais ce n'est pas comme ça que le compilateur le voit. Au moment où le compilateur vérifie si la distribution est autorisée, il voit juste ceci:

variable_of_type_B = (B)expression_of_type_A;

Et comme d'autres l'ont démontré, ce genre de casting est parfaitement légal. Expression sur la droite, pourrait très bien correspondre à un objet de type B . Le compilateur voit que A et B ont une relation de sous-Type, donc avec la vue "expression" du code, la distribution pourrait fonctionner.

le compilateur ne considère pas le cas spécial quand il sait exactement quel type d'objet expression_of_type_A aura vraiment. Il voit juste le type statique A et considère le type dynamique pourrait être A ou tout descendant de A , y compris B .

5
répondu Rob Kennedy 2008-12-19 15:41:19

dans ce cas, pourquoi Java autorise la downcasting si elle ne peut pas être exécutée à l'exécution?

je crois que c'est parce qu'il n'y a aucun moyen pour le compilateur de savoir au moment de la compilation si la distribution réussira ou non. Pour votre exemple, il est simple de voir que la distribution va échouer, mais il ya d'autres moments où il n'est pas si clair.

par exemple, imaginez que les types B, C, et D Tous étendent le type A, puis une méthode public A getSomeA() renvoie une instance de B, C ou d en fonction d'un nombre généré au hasard. Le compilateur ne peut pas savoir quel type exact run-time sera retourné par cette méthode, donc si vous lancez plus tard les résultats sur B , il n'y a aucun moyen de savoir si la distribution réussira (ou échouera). Par conséquent, le compilateur doit assumer jette réussira.

2
répondu matt b 2008-12-19 14:17:45

@ affiche originale - voir les commentaires en ligne.

public class demo 
{
    public static void main(String a[]) 
    {
        B b = (B) new A(); // compiles with the cast, but runtime exception - java.lang.ClassCastException 
        //- A subclass variable cannot hold a reference to a superclass  variable. so, the above statement will not work.

        //For downcast, what you need is a superclass ref containing a subclass object.
        A superClassRef = new B();//just for the sake of illustration
        B subClassRef = (B)superClassRef; // Valid downcast. 
    }
}

class A 
{
    public void draw() 
    {
        System.out.println("1");
    }

    public void draw1() 
    {
        System.out.println("2");
    }
}

class B extends A 
{
    public void draw() 
    {
        System.out.println("3");
    }

    public void draw2() 
    {
        System.out.println("4");
    }
}
2
répondu Alok Sharma 2012-12-27 15:11:01

Downcast fonctionne dans le cas où nous avons affaire à un objet upcasted. Upcasting:

int intValue = 10;
Object objValue = (Object) intvalue;

donc maintenant cette variable objValue peut toujours être réduite à int parce que l'objet qui a été moulé est un Integer ,

int oldIntValue = (Integer) objValue;
// can be done 

mais parce que objValue est un objet qu'il ne peut pas être moulé à String parce que int ne peut pas être moulé à String .

1
répondu Uday Reddy 2017-02-24 12:05:45

Passer est très utile dans l'extrait de code suivant que j'utilise tout le temps. Prouvant ainsi que de passer est utile.

private static String printAll(LinkedList c)
{
    Object arr[]=c.toArray();
    String list_string="";
    for(int i=0;i<c.size();i++)
    {
        String mn=(String)arr[i];
        list_string+=(mn);
    }
    return list_string;
}

je stocke la chaîne dans la liste liée. Lorsque je récupère les éléments de la liste liée, les objets sont retournés. Pour accéder aux éléments en tant que Chaînes(ou tout autre objet de classe), downcasting m'aide.

Java nous permet de compiler du code downcast en nous faisant confiance que nous faisons la mauvaise chose. Encore si les humains font une erreur, il est pris à la course.

0
répondu Drishti 2013-10-13 04:57:29

considérons l'exemple ci-dessous

public class ClastingDemo {

/**
 * @param args
 */
public static void main(String[] args) {
    AOne obj = new Bone();
    ((Bone) obj).method2();
}
}

class AOne {
public void method1() {
    System.out.println("this is superclass");
}
}


 class Bone extends AOne {

public void method2() {
    System.out.println("this is subclass");
}
}

nous créons ici l'objet de la sous-classe Bone et nous l'assignons à un renvoi de super classe AOne et maintenant le renvoi de superclasse ne sait pas à propos de la méthode method2 dans la sous-classe I. e os pendant la compilation.par conséquent, nous devons réduire ce renvoi de la superclasse au renvoi de la sous-classe afin que le renvoi résultant puisse connaître la présence de méthodes dans la sous-classe I. e os 151920920"

0
répondu ZohebSiddiqui 2014-06-08 04:59:04