diese Ausgabe über Objektreferenzcasting erklären? [Duplikat]

7
%Vor%

Ich weiß, warum a nicht in B umgewandelt werden kann, weil B nicht von A erbt.
meine Frage ist, warum B b1 = (B)i; erlaubt ist, da B nicht implementiert von I ist?
und warum B b1 = (B)i; diese Zeile wird keine Laufzeitausnahme erzwingen, da i null ist?

    
K.Toress 02.04.2014, 15:10
quelle

6 Antworten

11

Der Compiler weiß nicht alles über Ihre Klassenhierarchie. Soweit es das betrifft, könnte es class B2 extends B implements I geben, in diesem Fall müsste die obige Besetzung funktionieren.

    
Jeffrey 02.04.2014, 15:12
quelle
3

Wenn der Compiler auf B b = (B)a; stößt, weiß er ohne Zweifel, dass a vom Typ A ist und nicht legal in B umgewandelt wird.

Wenn der Compiler jedoch B b1 = (B)i; kompiliert, weiß er nur, dass i ein Objekt ist, das I implementiert - es könnte sein:

%Vor%

und die Umwandlung in B könnte legal sein, sodass sie nicht als Fehler behandelt werden kann.

Dies ist wirklich nur eine Re-Aussage von Jaffreys Antwort mit etwas mehr Erzählung.

    
OldCurmudgeon 02.04.2014 15:31
quelle
3

es ist eine Verengung Referenz Konvertierung .. nach Java-Spezifikation $ 5.1.5 ist erlaubt.

  

Von jedem Schnittstellentyp J zu jeder nicht parametrisierten Klassenart C, die nicht endgültig ist.

Diese Konvertierung zeigt keine Fehler bei der Kompilierung an, wird jedoch zur Laufzeit überprüft. Es würde ein ClassCastException nach $ 5.5.3 werfen wenn die Schnittstelle mit einer richtigen Klasse initialisiert wurde, die nicht mit B. zusammenhängt, aber jetzt nicht wirft, da die Schnittstelle null ist und wir wissen

  

Ein Wert des Nulltyps (der NULL-Verweis ist der einzige derartige Wert) kann einem beliebigen Referenztyp zugewiesen werden, was zu einem NULL-Verweis dieses Typs führt.

NB. .. ich wurde nicht über all die oben genannten Begriffe anerkannt ... Ich fühle nur Interesse zu suchen, nachdem ich die Frage gesehen habe. also korrigiere mich bitte, wenn mein Befund falsch ist oder ich etwas falsch verstanden habe

    
stinepike 02.04.2014 15:30
quelle
2

Überlegen Sie:

%Vor%

Dies zeigt, warum der Cast in der Zeile HERE legal sein muss, da es Szenarien gibt, in denen er erfolgreich sein kann. Java würde den Cast nur dann als Fehler markieren, wenn es absolut keinen möglichen Erfolg gibt.

    
ajb 02.04.2014 15:21
quelle
1

Ich glaube, dass den anderen Antworten ein wichtiges Detail fehlt: Es ist möglich, weil der Compiler einfach nicht in Schnittstellen schaut.

Die Argumente, die dies erklären sollen, wurden als

formuliert
  

könnte class B2 extends B implements I

sein

und

  

Der Compiler weiß hier, dass A und B nicht verwandt sind

Dies ist sehr wahr, aber es erklärt nicht, warum der Compiler weiß, dass diese beiden Klassen nicht verwandt sind und nicht warum er nicht wissen kann, wenn ein Schnittstelle wurde implementiert.

Am Ende sollten diese beiden Situationen ziemlich ähnlich sein: Wenn es zur Kompilierzeit prüfen kann, ob zwei Klassen eine Beziehung haben, dann sollte es in der Lage sein, zur Kompilierzeit zu überprüfen, ob eine Schnittstelle in dieser Klasse implementiert ist Diese Situationen stehen zur Kompilierungszeit zur Verfügung.

Daher stimme ich dem Kommentar von Hot Licks in das Duplikat :

  

Weil. Auch wenn Cat Möbel nicht direkt umsetzen darf, mag irgendeine Oberklasse von Cat. Und der Compiler beschließt, sich nicht in solche hässlichen Details zu vertiefen, da die Regeln für Schnittstellen ziemlich kompliziert sind. (Danke, Sun.) Und es gibt keine allgemeine Regel, die den Compiler auffordert, eine unvermeidliche Laufzeitausnahme zu erkennen (z. B. Division durch Null) - es ist eher ein "Service", den es bereitstellt.

Die Überprüfung der Schnittstelle zur Kompilierzeit sollte möglich sein, sie wird vom Compiler aus Gründen, die wir nur erraten können, nicht gemacht. die in den Kommentaren besprochen werden .

Nach einer ausführlichen (und sehr interessanten) Diskussion in den Kommentaren glaube ich, dass dies geklärt ist.

Es ist einfach und billig zu überprüfen, ob zwei Klassen eine Beziehung haben, Sie schauen sich beide Hierarchien an. Schnittstellen erfordern andererseits Kenntnisse über alle Klassen und Schnittstellen im Projekt (einschließlich externer Ressourcen wie Bibliotheken), um festzustellen, ob eine Beziehung zwischen der Schnittstelle und der Klasse besteht.

Dies führt mich zu der Schlussfolgerung, dass es zwar theoretisch möglich ist, aber nicht machbar ist, weil es zwei Dinge erfordern würde:

  1. Erneute Kompilierung des Quellcodes und aller enthaltenen Bibliotheken.
  2. Sehr teure Prüfungen, die die Hierarchien jeder Klasse durchlaufen müssen.
Jeroen Vannevel 02.04.2014 15:46
quelle
-1

Hier finden Sie einige gute Informationen zu Upcasting und Downcasting. Ссылка

Da jede Klasse von Object erbt, können Sie immer zu einem anderen Objekt (B)(Object)a springen und zu einem anderen Objekt herabstufen. Nicht dass das eine gute Idee ist, aber es ist gültig. Wenn Sie tatsächlich A instanziiert hätten, würden Sie eine Laufzeitausnahme java.lang.ClassCastException erhalten, als wären Sie instanziiert und eine Instanz von I i = new I(){}

%Vor%     
Scott 02.04.2014 15:38
quelle

Tags und Links