2016-01-03 11 views
5

Der folgende Code kompiliert fein:Compilerfehler Instanz final class

interface Flyer{ } 
class Bat { } 

public class App { 

    public static void main(String[] args) { 
     Bat b = new Bat(); 
     if(b instanceof Flyer) System.out.println("b is a Bird"); 
    } 

} 

Wenn wir die Klasse Batfinal machen, wird der Code nicht kompilieren:

final class Bat { } 

Wenn die letzte Klasse implementiert Flyer es kompiliert in Ordnung:

final class Bat implements Flyer { } 

Beliebig eine Sorge, um die Logik dahinter zu erklären?

Antwort

6

Wenn Sie Klasse Batfinal machen, sagen Sie, dass diese Klasse nicht unterklassifiziert werden kann. Da Bat die Schnittstelle Flyer nicht implementiert, kann der Compiler feststellen, dass b instanceof Flyer niemals true sein kann und einen Fehler auslöst.

Wenn ein Guss (§15.16) des RelationalExpression zum Reference würde als Fehler bei der Kompilierung zurückgewiesen wird, dann der instanceof relationale ebenfalls Ausdruck:

Dies ist in JLS section 15.20.2 angegeben erzeugt einen Kompilierungsfehler. In einer solchen Situation könnte das Ergebnis des Ausdrucks instanceof niemals wahr sein.

Zusätzlich aus section 15.16 über Guss Ausdrücke:

Es ist ein Fehler bei der Kompilierung, wenn der Kompilierung-Typ des Operanden kann nie auf den von dem Cast-Operator angegebenen Typen umgewandelt wird gemäß die Regeln der Casting-Konvertierung (§5.5).

In diesem Fall Bat kann nie zu Flyer gewirkt: sie es nicht implementieren ist und final sorgt dafür, dass es nicht Unterklassen sein kann, die es umsetzen würde.


Wie Sie herausgefunden, sind die Korrekturen:

  • Machen BatFlyer implementieren: in diesem Fall wird der instanceof Operator würde immer true zurück.
  • Entfernen Sie die final Kennung, was bedeutet, dass es Unterklassen von BatFlyer Implementierung geben könnte.
+0

Würde 'null instanceof X' unabhängig vom" type "der Null-Instanz" true "zurückgeben? Allerdings kann ich sehen, dass dies sehr zwielichtig wäre, den Compiler das akzeptieren zu lassen. – Dici

+0

@Dici Eigentlich ist ['null instanceof X' immer' false'] (http://stackoverflow.com/questions/2950319/is-null-) check-needed-vor-Aufruf-instanceof). – Tunaki

+0

Ups ... Entschuldigung, du hast recht, ich benutze das sogar, um alle meine 'equals' Methoden zu schreiben. Ich brauche einen Schlaf: D – Dici

4

Nun, wenn Bat eine letzte Klasse ist und es nicht implementiert Flyer, kann es keine Unterklasse, die Flyer entweder implementieren würde, so kann instanceof nie wahr zurück. In solchen Fällen lässt der Compiler diesen Ausdruck nicht zu (d. H. (x instanceof Y) ist nur zulässig, wenn die Wahrscheinlichkeit besteht, dass x einen Verweis auf eine Instanz enthält, die Y implementiert oder erweitert).

In Ihrem zweiten Schnipsel Bat implementiert bereits Flyer, so würde b instanceof Flyer immer true zurückkehren, und zwar unabhängig davon, ob Bat ist endgültig oder nicht.

+0

Ich finde es seltsam (vielleicht ein schlechtes Design), dass, wenn es immer "falsch" ist, ein Kompilierungsfehler passieren wird, aber wenn es * immer * 'wahr 'ist, dann ist es in Ordnung. – Maroun

+0

Scheint Logik jetzt ... Frühcheck immer eine gute Idee. – Trace

+0

@MarounMaroun Es gibt einige Unstimmigkeiten hier, stimme ich zu. – Eran

Verwandte Themen