Ich habe oft Nachrichten gesehen, die [L
dann einen Typ verwenden, um ein Array zu bezeichnen, zum Beispiel:
[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
(Das obige ist ein willkürliches Beispiel, das ich gerade herausgezogen habe.) Ich weiß, dass dies ein Array bedeutet, aber woher kommt die Syntax? Warum der Anfang, [
aber keine schließende eckige Klammer? Und warum das L? Ist es rein willkürlich oder gibt es einen anderen historischen / technischen Grund dafür?
Antworten:
[
steht für Array,Lsome.type.Here
bedeutet den Typ. Dies ähnelt den Typdeskriptoren, die intern im Bytecode in §4.3 der Java Virtual Machine-Spezifikation verwendet werden - so kurz wie möglich . Der einzige Unterschied besteht darin, dass die realen Deskriptoren/
eher.
Pakete als Bezeichnungen verwenden.Für Grundelemente lautet der Wert beispielsweise:
[I
Für ein Array von int wäre ein zweidimensionales Array :[[I
.Da Klassen einen beliebigen Namen haben können, ist es schwieriger zu identifizieren, um welche Klasse es sich handelt. Daher
L
endet der Klassenname mit einem;
Deskriptoren werden auch verwendet, um die Arten von Feldern und Methoden darzustellen.
Zum Beispiel:
... entspricht ein Verfahren , deren Parameter sind
int
,double
undThread
und der Rücklauftyp istObject
bearbeiten
Sie können dies auch in .class-Dateien sehen, die den Java-Dissambler verwenden
C:>more > S.java class S { Object hello(int i, double d, long j, Thread t ) { return new Object(); } } ^C C:>javac S.java C:>javap -verbose S class S extends java.lang.Object SourceFile: "S.java" minor version: 0 major version: 50 Constant pool: const #1 = Method #2.#12; // java/lang/Object."<init>":()V const #2 = class #13; // java/lang/Object const #3 = class #14; // S const #4 = Asciz <init>; const #5 = Asciz ()V; const #6 = Asciz Code; const #7 = Asciz LineNumberTable; const #8 = Asciz hello; const #9 = Asciz (IDJLjava/lang/Thread;)Ljava/lang/Object;; const #10 = Asciz SourceFile; const #11 = Asciz S.java; const #12 = NameAndType #4:#5;// "<init>":()V const #13 = Asciz java/lang/Object; const #14 = Asciz S; { S(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 java.lang.Object hello(int, double, long, java.lang.Thread); Code: Stack=2, Locals=7, Args_size=5 0: new #2; //class java/lang/Object 3: dup 4: invokespecial #1; //Method java/lang/Object."<init>":()V 7: areturn LineNumberTable: line 3: 0 }
Und in der Rohklassendatei (siehe Zeile 5):
Referenz: Feldbeschreibung in der JVM-Spezifikation
quelle
[[I
bedeutet nur Array-of-Array-of-Int.JVM-Array-Deskriptoren.
[Z = boolean [B = byte [S = short [I = int [J = long [F = float [D = double [C = char [L = any non-primitives(Object)
Um den Hauptdatentyp zu erhalten, benötigen Sie:
Es wird null zurückgegeben, wenn das "Objekt" kein Array ist. Um festzustellen, ob es sich um ein Array handelt, rufen Sie einfach Folgendes auf:
oder
quelle
Dies wird in der JNI (und der JVM intern im Allgemeinen) verwendet, um einen Typ anzugeben. Grundelemente werden mit einem einzelnen Buchstaben bezeichnet (Z für Boolescher Wert, I für Int usw.),
[
geben ein Array an und L wird für eine Klasse verwendet (mit a abgeschlossen;
).Siehe hier: JNI-Typen
BEARBEITEN: Um herauszufinden, warum es keine Beendigung gibt
]
- dieser Code soll es der JNI / JVM ermöglichen, eine Methode und ihre Signatur schnell zu identifizieren. Es soll so kompakt wie möglich sein, um das Parsen schnell zu machen (= so wenig Zeichen wie möglich). Es wird daher[
für ein Array verwendet, das ziemlich einfach ist (welches bessere Symbol ist zu verwenden?).I
für int ist ebenso offensichtlich.quelle
Aus der JVM-Spezifikation. Dies ist die Darstellung von Typnamen, die im classFile-Format und an anderen Stellen angegeben ist.
[<typename>
wo<typename>
der Name des Basistypen des Arrays ist."Ljava.lang.String;"
. Beachten Sie das nachfolgende ';' !!Und ja, die Notation ist auch an anderen Stellen dokumentiert.
Es besteht kein Zweifel, dass diese interne Typnamenrepräsentation ausgewählt wurde, weil es ist:
Es ist jedoch unklar, warum sie beschlossen haben, die internen Typnamen von Array-Typen über die
Class.getName()
Methode verfügbar zu machen. Ich denke , sie könnten die internen Namen zu etwas mehr „human friendly“ zugeordnet haben. Meine beste Vermutung ist, dass es nur eines dieser Dinge war, die sie erst reparieren konnten, als es zu spät war. (Niemand ist perfekt ... nicht einmal der hypothetische "intelligente Designer".)quelle
Ich denke, das liegt daran, dass C von char genommen wurde, also ist der nächste Buchstabe in der Klasse L.
quelle
Eine weitere Quelle hierfür wäre die Dokumentation von Class.getName () . Natürlich sind alle diese Spezifikationen kongruent, da sie aufeinander abgestimmt sind.
quelle