java.lang.ClassException: A kann nicht in B umgewandelt werden

9

Ich habe diesen Code implementiert:

%Vor%

Beide Zeilen kompilieren, wenn sie separat kompiliert werden, aber geben Laufzeitfehler mit java.lang.ClassException: A cannot be cast into B .

Warum kompilieren sie gut, geben aber einen Laufzeitfehler?

    
Ozil 20.06.2013, 15:40
quelle

13 Antworten

5

Sie müssen verstehen, dass unter der Referenz vom Typ A alle Objekte der Klasse A oder die Klasse A , wie in Ihrem Fall B , gespeichert werden können.

Also ist es möglich, dass

%Vor%

Da das Objekt unter a referenz eine Instanz der Klasse B ist, sollte es möglich sein, es irgendwie in einer genaueren Referenz zu speichern, wie B b . Versuchen wir es auf diese Weise:

%Vor%

Dieser Code gibt uns die Kompilierzeit Type mismatch error, um diese Art von Situation zu vermeiden:
Sagen wir, wir haben

  • class B1 extends A und
  • class B2 extends A

und wir haben A a = new B1() erstellt. Wenn nun der Compiler Type mismatch error für B1 b = a nicht ausgibt, sollte auch B2 b = a erlaubt sein, aber unter a gibt es eine Instanz von B1 , was nichts mit B2 zu tun hat.

Um dem Compiler zu sagen, dass wir einen möglichen Typenkonflikt kennen, müssen wir das Casting explizit auf unsere gewünschte Klasse anwenden

%Vor%

Dies ist der Grund, warum der Verweis A auf die Klasse angewendet wird, die in der Kompilierzeit extends A möglich ist.

In Ihrem Code haben Sie

%Vor%

Sie müssen wissen, dass der Operator new die Referenz des gleichen Typs zurückgibt, der das Objekt erstellt hat, so dass new A() die Referenz des Typs A so zurückgibt

%Vor%

ist tatsächlich dasselbe wie

%Vor%

Problem hier ist, dass Sie Objekt einer Klasse in Bezug auf seine abgeleitete Klasse nicht speichern können. Warum? Was ist, wenn diese abgeleitete Klasse neue Methoden hat, die diese Objektklasse nicht wie

hat? %Vor%

und nach

%Vor%

Sie werden versuchen, b.setI(42); aufzurufen? Wird es möglich sein? Nein, weil die Instanz der Klasse A nicht die Methode setI hat und selbst wenn sie die ID hatte, wird das Feld int i in dieser Methode nicht verwendet.

Deshalb wirft (B)new A(); java.lang.ClassCastException .

    
Pshemo 20.06.2013, 16:18
quelle
7

Der Grund dafür, dass es zur Laufzeit nicht funktioniert, ist, dass das Objekt kein B ist. Es ist ein A. Also während einige As kann wie Bs sein, kann Ihrs nicht.

Der Compiler kann einfach nicht alles analysieren, was mit deinem A-Objekt passiert ist. Zum Beispiel.

%Vor%

Der Compiler ist also nicht sicher, ob Ihr A-Objekt tatsächlich in ein B umgewandelt werden kann. Im obigen Fall würde es also denken, dass die letzten zwei Zeilen in Ordnung waren. Aber wenn Sie das Programm tatsächlich ausführen, erkennt es, dass a2 kein B ist, es ist nur ein A.

    
Rachel G. 20.06.2013 15:45
quelle
2
%Vor%

Weil A NICHT B ist.

Die Kompilierzeit funktioniert, weil Sie einen Compiler generieren und explizit garantieren, der zur Laufzeit sicher ist. A wird B sein.

    
kosa 20.06.2013 15:41
quelle
2

Wenn B A erweitert, bedeutet dies, dass alle Methoden und Eigenschaften von A auch in B vorhanden sind.

Du kannst also B nach A werfen,

aber Sie können nicht A nach B werfen.

Sie müssen wirklich darauf achten, dass Sie Ihre Bewerbung einreichen.

    
Martin Strejc 20.06.2013 15:44
quelle
2

Wenn du sagst, dass B A ausdehnt, wird A Vater von B jetzt technisch B hat alle Eigenschaften von A plus eine eigene während A Eigenschaften nur von sich selbst

hat

Wenn Sie A in B umwandeln und B zuweisen, ist das in Ordnung aber wenn Sie A in B sagen und A zuweisen, dann ist das nicht möglich, da A hier keine besonderen Eigenschaften in B kennt.

und diese Dinge passieren zur Laufzeit, so dass Sie einen Laufzeitfehler bekommen.

    
VD' 20.06.2013 15:48
quelle
2

Der Name selbst bedeutet, dass compiler nur den Kompilierungszeittyp von expression untersucht.

Es macht keine Annahmen über den Laufzeittyp von expression .

Ссылка

Zum wirklichen Problem kommen

Du kannst nicht A nach B umwandeln. kannst B nach A umwandeln. Wenn du eine Mango hast, hast du Obst. Aber wenn du ein Obst hast, dann nicht bedeutet, dass Sie eine Mango haben.

    
quelle
1

Ich bin nicht sicher über den Kompilierungsteil, aber ich kann den Laufzeitfehler erklären.

B erweitert A, was bedeutet, dass jedes Objekt der Klasse B ebenfalls ein Objekt des Typs A ist. Umgekehrt ist das nicht wahr.

Vergleiche A mit "Mammal" und B mit "Cow". Eine Kuh ist immer ein Säugetier, aber nicht jedes Säugetier ist eine Kuh.

    
Johanneke 20.06.2013 15:43
quelle
1

Hat zu tun, wenn das Casting fertig ist. Sie sagen dem Compiler: "Hey, mach dir keine Sorgen, das ist es was ich sage, wenn du ein Problem hast, nimm es zur Laufzeit mit mir auf."

Grundsätzlich lässt dich der Compiler deine Sache machen. Wenn Sie etwas explizit umsetzen, führt der Compiler keine Prüfungen durch. Wenn Sie ausführen und das Programm versucht zu casten, aber fehlschlägt, dann sehen Sie den Fehler.

    
Captain Skyhawk 20.06.2013 15:43
quelle
1

Folgendes ist ein Compiletime Casting -

%Vor%

Solche statischen Castings werden implizit vom Compiler ausgeführt, weil der Compiler sich der Tatsache bewusst ist, dass B ein A ist.

Folgendes wird nicht kompiliert -

%Vor%

Keine Compiletime Casting hier, weil der Compiler weiß, dass A nicht B ist.

Nach Kompilieren -

%Vor%

Es ist ein dynamisches Casting. Mit (B) sagen Sie dem Compiler explizit, dass das Casting zur Laufzeit stattfinden soll. Und Sie erhalten ein CCE zur Laufzeit, wenn die Laufzeit versucht, den Cast durchzuführen, aber herausfindet, dass dies nicht möglich ist und ein CCE ausgelöst wird.

Wenn Sie etwas tun (oder müssen), fällt die Verantwortung auf Sie (nicht den Compiler), um sicherzustellen, dass ein CCE zur Laufzeit nicht auftritt.

    
Bhesh Gurung 20.06.2013 15:53
quelle
0

Es ist einfach. Denken Sie, dass wenn Sie erweitern, müssen Sie is a

verwenden %Vor%

Ein realistischeres Beispiel

%Vor%

Ein Hund IS A Tier ANIMAL IS NOT a HUND notwendig (Beispiel: eine Katze ist kein Hund, und eine Katze ist ein Tier)

Sie bekommen runtime exception cause, in der Laufzeit erkennen, dass dieses Tier kein Hund ist, dies ist downcasting nennen und ist nicht sicher, was Sie versuchen zu tun.

    
nachokk 20.06.2013 15:42
quelle
0

Die Tatsache, dass B extends A bedeutet, dass B ist A , d. h. B ist wie A, fügt aber wahrscheinlich etwas anderes hinzu.

Das Gegenteil ist falsch. A ist nicht B . Daher können Sie A nicht auf B anwenden.

Denken Sie so. A ist Animal . B ist Bee . Ist Bee Tier? Ja, so ist es. Ist irgendein Tier Biene? Nicht es ist nicht. Zum Beispiel ist Hund Tier, aber definitiv keine Biene.

    
AlexR 20.06.2013 15:44
quelle
0

Weil A ein Elternteil von B ist. B erweitert die Funktionalität von A , behält aber die ursprüngliche Funktionalität von A bei. So kann B tatsächlich in A umgewandelt werden, aber nicht umgekehrt.

Was ist, wenn B eine neue Methode hinzugefügt hat, sagen wir newMethodInB() . Wenn Sie versuchen würden, diese Methode über die Variable B in der Instanz A aufzurufen (stellen Sie sich vor, dass die Besetzung funktioniert hat), was würden Sie erwarten? Nun, Sie würden definitiv einen Fehler bekommen, weil diese Methode nicht in A existiert.

    
darijan 20.06.2013 15:48
quelle
0

Weil der Compiler nur sieht, dass ein A in ein B umgewandelt wird. Da einige A tatsächlich B sein können, kann das für die A funktionieren. Indem Sie die explizite Umwandlung schreiben, stellen Sie sicher, dass dieses spezielle A tatsächlich ein gültiges B ist. Dies ist jedoch nicht der Fall.

%Vor%

Das ist der Grund, warum der Compiler den Typ nicht wirklich kennt:

%Vor%     
b.buchhold 20.06.2013 15:50
quelle

Tags und Links