2017-08-04 6 views
3

Beim Aufbohren auf den Operator instanceof auf der Java-Bytecode-Assembly-Anweisungsebene entspricht dies einer Java-Assembly-Anweisung instanceof. Aber ich las die zuWas bedeuten die Regeln für die Java-Assembly-Anweisung instanceof?

verwendeten Regeln

bestimmen, ob ein objectref, die nicht null ist eine Instanz der aufgelösten Art ist:

Die zweite Regel gesagt:

Wenn S eine Schnittstellentyp, dann:

  • Wenn T ein Klassentyp ist, dann muss T Objekt sein.
  • Wenn T ein Interface-Typ ist, muss T die gleiche Schnittstelle wie S oder ein Superschnitt von S.

Das hat mich verwirrt. Ist "S ist ein Schnittstellentyp" bedeutet der Referenztyp von S ein Schnittstellentyp? Wenn dies der Fall ist, kann die erste Regel "Wenn T ein Klassentyp ist, dann muss T ein Objekt haben" nicht gelten. Zum Beispiel

CharSequence charSequence = new StringBuilder("test"); 
System.out.println(charSequence instanceof StringBuilder); 
System.out.println(charSequence instanceof String); 

die zweite Zeile in dem obigen Code würde Druck wahr, während oberhalb die dritte Zeile falsch drucken. Also bezweifle ich, dass mein Verständnis wahrscheinlich falsch ist. Jeder kann helfen, die Bedeutung der obigen Regel zu erklären.

+0

'S ist die Klasse des Objekts, auf das mit * objectref *' verwiesen wird: in diesem Fall 'StringBuilder'. Die dritte Zeile, die 'false' druckt, ist korrekt. – EJP

+0

@EJP Aber denkst du nicht, dass die erste Regel, die ich erwähnt habe, anders ist als die, die aus dem Code gedruckt werden sollte? String ist Objekt, ist es nicht – Rui

Antwort

2

Sie haben das Recht, verwirrt zu sein, da die Art, wie diese Regeln geschrieben wurden, sind verwirrend.

Für ein objectref, ist es unmöglich einen Schnittstellentyp zu haben, da jedes Objekt instanziiert eine tatsächliche, nicht abstrakte Art hat, vielleicht eine Schnittstelle zu implementieren. Dies gilt sogar für die Instanzen, die für Lambda-Ausdrücke generiert wurden, die einen nicht spezifizierten (anonymen) Typ haben, der die funktionale Schnittstelle implementiert.

So scheint es auf den ersten Blick, dass dieser Teil dieser Regeln keinen Sinn macht.Aber betrachten Sie den kompletten Text:

Die folgenden Regeln verwendet werden, um zu bestimmen, ob ein objectref, die nicht null ist eine Instanz der aufgelösten Art: Wenn S ist die Klasse des genannte Objekts durch objectref und T wird die aufgelöste Klasse, ein Array oder Schnittstellentyp, instanceof bestimmt, ob objectref ist eine Instanz T wie folgt:

  • Wenn S eine gewöhnliche (Nonarray) Klasse ist, dann gilt:
    • Wenn T ein Klassentyp ist, dann S muss die gleiche Klasse wie T sein, oder S muss eine Unterklasse von T sein;
    • Wenn T ein Schnittstellentyp ist, muss S die Schnittstelle T implementieren.
  • Wenn S ist ein Interface-Typ, dann:
    • Wenn T ist ein Klasse-Typ, dann T Objekt sein muss.
    • Wenn T ein Schnittstellentyp ist, muss T die gleiche Schnittstelle wie S oder ein Superinterface von S sein.
  • Wenn S ist eine Klasse, die den Array-Typs SC[], das heißt, eine Anordnung von Komponenten des Typs SC, dann gilt:
    • T Wenn ein Klassentyp ist, dann T Objekt sein muss.
    • Wenn T ein Schnittstellentyp ist, muss T eine der von Arrays implementierten Schnittstellen sein (JLS §4.10.3).
    • T Wenn ein Array-Typ TC[], das heißt, eine Anordnung von Komponenten des Typs TC, dann einer der folgenden Schritte müssen wahr sein:
      • TC und SC ist der gleiche Urtyp.
      • TC und SC sind Referenztypen und der Typ SC kann mithilfe dieser Laufzeitregeln in TC umgewandelt werden.

Da es für das eigentliche Objekt durch verwiesen unmöglich ist objectref einen Schnittstellentyp haben, nur die beiden anderen Kugeln gelten; Sein Typ ist entweder eine "normale (Nicht-Array-) Klasse" oder ein Array-Typ. Im letzteren Fall ist der letzte Satz der interessante, da er sich auf die zitierten Regeln als Ganzes bezieht und auf die Komponententypen T und S angewendet wird, wenn beide Arrays eines Referenztyps sind.Und der Komponententyp kann ein Schnittstellentyp sein.

So können Sie diese Regeln testen eine tatsächliche Array-Instanz von einem Schnittstellentyp verwendet wird, die Überprüfung gegen andere Array-Typen:

Object o = new Collection[0]; // SC is Collection 
System.out.println(o instanceof Object[]); // TC is class type Object -> true 
System.out.println(o instanceof String[]); // TC is class type other than Object -> false 
System.out.println(o instanceof Collection[]); // TC == SC -> true 
System.out.println(o instanceof Iterable[]); // TC is super interface of SC -> true 
System.out.println(o instanceof List[]); // TC is not super interface SC -> false 

Es denken, wäre es weniger verwirrend sein, wenn die Schnittstelle Fall innerhalb der beschrieben wurde Array Sonderfall, wo es gelten kann. Auf der anderen Seite folgen diese drei Fälle den allgemeinen formalen Zuordnungsregeln, so dass sie in dieser Form leichter zu erkennen sind.

+0

so würde dies nur funktionieren, weil Arrays kovariant richtig sind? Ich kann mir keinen einzigen Ort vorstellen, an dem ich eine Existenz gegen ein Array gesehen habe, obwohl – Eugene

+0

@Eugene: das ist eine der Regeln, die * Arrays * kovariant machen. – Holger

Verwandte Themen