Downcasting w Javie

Upcasting jest dozwolony w Javie, jednak downcasting powoduje błąd kompilacji.

Błąd kompilacji może zostać usunięty przez dodanie cast, ale i tak pęknie w czasie wykonywania.

W tym przypadku dlaczego Java zezwala na downcasting, jeśli nie może być uruchomiony w środowisku runtime?
Czy jest jakieś praktyczne zastosowanie tej koncepcji?

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
Author: Pshemo, 2008-12-19

9 answers

Downcasting jest dozwolony, gdy istnieje możliwość, że powiedzie się w czasie wykonywania:

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

W niektórych przypadkach to się nie uda:

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

W innych będzie działać:

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

Gdy Obsada (taka jak ta ostatnia) zawiedzie w czasie wykonywania a ClassCastException zostanie wyrzucony.

Zauważ, że niektóre rzuty będą niedozwolone podczas kompilacji, ponieważ nigdy nie odniosą sukcesu:

Integer i = getSomeInteger();
String s = (String) i; // the compiler will not allow this, since i can never reference a String.
 273
Author: Joachim Sauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 11:17:12

Używając Twojego przykładu, możesz zrobić:

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
Author: Rolf Rander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-19 13:08:04

Wydaje mi się, że dotyczy to wszystkich języków typowanych statycznie:

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

Typecast skutecznie mówi: Załóżmy, że jest to odniesienie do klasy cast i użyj go jako takiego. Załóżmy, że o jest naprawdę liczbą całkowitą, zakładając, że jest to ciąg znaków, nie ma sensu i da nieoczekiwane wyniki, dlatego konieczne jest sprawdzenie środowiska uruchomieniowego i wyjątek, aby powiadomić środowisko uruchomieniowe, że coś jest nie tak.

W praktycznym użyciu można pisać kod pracujący na bardziej ogólnej klasie, ale wrzuć go do podklasy, jeśli wiesz, co to jest podklasa i musisz ją traktować jako taką. Typowym przykładem jest obiekt nadrzędny.equals (). Załóżmy, że mamy klasę Dla Samochodu:

@Override
boolean equals(Object o) {
    if(!(o instanceof Car)) return false;
    Car other = (Car)o;
    // compare this to other and return
}
 14
Author: Rolf Rander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-21 23:19:51

Wszyscy widzimy, że podany kod nie będzie działał w czasie uruchomienia. Wiemy bowiem, że wyrażenie new A() może nigdy nie być obiektem typu B.

Ale kompilator tego nie widzi. Kiedy kompilator sprawdza, czy cast jest dozwolony, widzi to:

variable_of_type_B = (B)expression_of_type_A;

I jak wykazali inni, ten rodzaj obsady jest całkowicie legalny. Wyrażenie po prawej stronie może bardzo dobrze ocenić obiekt typu B. Kompilator widzi, że A i B mają Podtyp relacji, więc w widoku" expression " kodu, Obsada może działać.

Kompilator nie bierze pod uwagę specjalnego przypadku, gdy wie dokładnie jaki typ obiektu expression_of_type_A naprawdę będzie miał. Po prostu widzi Typ statyczny jako A i uważa, że typ dynamiczny może być A lub dowolnym potomkiem A, w tym B.

 5
Author: Rob Kennedy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-19 15:41:19

W tym przypadku dlaczego Java zezwala na downcasting, jeśli nie może być uruchomiony w środowisku runtime?

Wierzę, że jest to spowodowane tym, że kompilator nie ma możliwości, aby wiedzieć podczas kompilacji, czy Obsada się powiedzie, czy nie. Dla Twojego przykładu, łatwo jest zobaczyć, że obsada zawiedzie, ale są inne czasy, w których nie jest to tak jasne.

Na przykład, wyobraź sobie, że typy B, C I d rozszerzają Typ A, a następnie metoda public A getSomeA() zwraca instancję B, C lub D w zależności od a losowo wygenerowany numer. Kompilator nie może wiedzieć, który dokładnie typ run-time zostanie zwrócony przez tę metodę, więc jeśli później oddasz wyniki do B, nie ma sposobu, aby dowiedzieć się, czy rzut się powiedzie (lub nie). W związku z tym kompilator musi zakładać, że rzuty odniosą sukces.

 2
Author: matt b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-19 14:17:45

@ Original Poster-Zobacz komentarze inline.

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
Author: Alok Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-27 15:11:01

Downcast działa w przypadku, gdy mamy do czynienia z upcasted obiektu. Upcasting:

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

Więc teraz Ta objValue zmienna może być zawsze zmniejszona do int ponieważ obiekt, który został rzucony jest Integer,

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

Ale ponieważ objValue jest obiektem, nie można go oddać do String, ponieważ int nie można oddać do String.

 1
Author: Uday Reddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-24 12:05:45

Downcasting jest bardzo przydatny w poniższym fragmencie kodu używam go cały czas. W ten sposób udowadniając, że downcasting jest przydatny.

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

Przechowuję ciąg znaków na liście linkowanych. Gdy pobieram elementy listy Linked, zwracane są obiekty. Aby uzyskać dostęp do elementów jako ciągów znaków(lub innych obiektów klasy), downcasting pomaga mi.

Java pozwala nam skompilować kod downcast, ufając nam, że robimy złą rzecz. Jednak jeśli ludzie popełnią błąd, zostaje złapany na runtime.

 0
Author: Drishti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-13 04:57:29

Rozważ poniższy przykład

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

Tutaj tworzymy obiekt subclass Bone i przypisujemy go do super class Aone reference i teraz superclass reference nie wie o metodzie method2 w podklasie czyli kości w czasie kompilacji.dlatego musimy obniżyć to odniesienie klasy nadklasy do podklasy odniesienia, tak jak wynikowe odniesienie może wiedzieć o obecności metod w podklasie TJ Kości

 0
Author: ZohebSiddiqui,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-08 04:59:04