A menudo he visto mensajes que usan [L
un tipo para denotar una matriz, por ejemplo:
[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
(Lo anterior es un ejemplo arbitrario que acabo de extraer). Sé que esto significa una matriz, pero ¿de dónde proviene la sintaxis? ¿Por qué el principio [
pero no el corchete de cierre? ¿Y por qué la L? ¿Es puramente arbitrario o hay alguna otra razón histórica / técnica detrás de esto?
Respuestas:
[
significa Array,Lsome.type.Here
significa el tipo. Eso es similar a los descriptores de tipo utilizados internamente en el código de bytes que se ve en §4.3 de la Especificación de la máquina virtual de Java , elegido para ser lo más breve posible . La única diferencia es que los descriptores reales utilizan en/
lugar de.
para denotar paquetes.Por ejemplo, para las primitivas el valor es:
[I
para matriz de int, una matriz de dos dimensiones sería el siguiente:[[I
.Dado que las clases pueden tener cualquier nombre, sería más difícil identificar qué clase es, por lo tanto
L
, el nombre de la clase termina con un;
Los descriptores también se utilizan para representar los tipos de campos y métodos.
Por ejemplo:
... corresponde a un método cuyos parámetros son
int
,double
yThread
y el tipo de retorno esObject
editar
También puede ver esto en archivos .class usando el dissambler java
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 }
Y en el archivo de clase sin formato (mire la línea 5):
Referencia: descripción de campo en la especificación de JVM
fuente
[[I
solo significa matriz-de-matriz-de-int.Descriptores de matriz de JVM.
[Z = boolean [B = byte [S = short [I = int [J = long [F = float [D = double [C = char [L = any non-primitives(Object)
Para obtener el tipo de datos principal, necesita:
Devolverá nulo si el "objeto" no es una matriz. para determinar si es una matriz, simplemente llame a:
o
fuente
Esto se usa en la JNI (y la JVM internamente en general) para indicar un tipo. Las primitivas se indican con una sola letra (Z para booleano, I para int, etc.),
[
indica una matriz y L se usa para una clase (terminada por una;
).Vea aquí: Tipos de JNI
EDITAR: Para explicar por qué no hay terminación
]
, este código es para permitir que JNI / JVM identifique rápidamente un método y su firma. Está destinado a ser lo más compacto posible para agilizar el análisis (= la menor cantidad de caracteres posible), por lo que[
se usa para una matriz que es bastante sencilla (¿qué mejor símbolo para usar?).I
porque int es igualmente obvio.fuente
De la especificación de JVM. Esta es la representación de los nombres de tipo que se especifica en el formato classFile y en otros lugares.
[<typename>
donde<typename>
está el nombre del tipo base de la matriz."Ljava.lang.String;"
. ¡¡Tenga en cuenta el ';' !!Y sí, la notación también está documentada en otros lugares.
No hay duda de que se eligió esa representación de nombre de tipo interno porque es:
Pero no está claro por qué decidieron exponer los nombres de tipos internos de los tipos de matriz a través del
Class.getName()
método. Creo que podrían haber asignado los nombres internos a algo más "amigable para los humanos". Mi mejor suposición es que fue solo una de esas cosas que no pudieron arreglar hasta que fue demasiado tarde. (Nadie es perfecto ... ni siquiera el hipotético "diseñador inteligente").fuente
Creo que es porque C fue tomado por char, así que la siguiente letra en clase es L.
fuente
Otra fuente para esto sería la documentación de Class.getName () . Por supuesto, todas estas especificaciones son congruentes, ya que están hechas para encajar entre sí.
fuente