[L
예를 들어 배열을 나타내는 데 유형을 사용하는 메시지를 자주 보았습니다 .
[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
(위는 내가 방금 뽑은 임의의 예입니다.) 이것이 배열을 의미한다는 것을 알고 있지만 구문은 어디에서 왔습니까? 왜 시작 [
이지만 닫는 대괄호는 없습니까? 그리고 왜 L? 순전히 임의적입니까 아니면 그 뒤에 다른 역사적 / 기술적 이유가 있습니까?
답변
[
Lsome.type.Here
유형을 의미하는 배열을 의미합니다. 즉 사용되는 타입 설명 비슷 바이트 코드의 내부 에서 볼 Java 가상 머신 사양의 §4.3 -로 포착 가능한 간단한으로 . 유일한 차이점은 실제 설명자가 패키지를 표시 하는 /
것이 아니라 사용 한다는 것 .
입니다.
예를 들어 프리미티브의 경우 값은 다음과 같습니다. [I
int 배열의 경우 2 차원 배열은 다음과 같습니다 [[I
..
클래스는 어떤 이름을 가질 수 있으므로 어떤 클래스인지 식별하기가 더 어렵습니다. 따라서 L
클래스 이름은;
설명자는 필드 및 메서드 유형을 나타내는데도 사용됩니다.
예를 들면 :
(IDLjava/lang/Thread;)Ljava/lang/Object;
… 매개 변수가 int
, double
이고 Thread
반환 유형이 다음과 같은 메서드에 해당합니다.Object
편집하다
java dissambler를 사용하여 .class 파일에서도 이것을 볼 수 있습니다.
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
}
그리고 원시 클래스 파일 (5 행 참조) :
참조 : JVM 사양에 대한 필드 설명
답변
JVM 배열 설명자.
[Z = boolean
[B = byte
[S = short
[I = int
[J = long
[F = float
[D = double
[C = char
[L = any non-primitives(Object)
기본 데이터 유형을 얻으려면 다음이 필요합니다.
[Object].getClass().getComponentType();
“객체”가 배열이 아닌 경우 null을 반환합니다. 배열인지 확인하려면 다음을 호출하십시오.
[Any Object].getClass().isArray()
또는
Class.class.isArray();
답변
이것은 유형을 표시하기 위해 JNI (및 일반적으로 JVM 내부적으로)에서 사용됩니다. 프리미티브는 단일 문자 (부울의 경우 Z, 정수의 경우 I 등)로 [
표시되고 배열을 나타내며 L은 클래스 (a로 끝남 ;
)에 사용됩니다.
여기 참조 : JNI 유형
편집 : 종료가없는 이유를 자세히 설명하기 ]
위해이 코드는 JNI / JVM이 메서드와 서명을 빠르게 식별 할 수 있도록하는 것입니다. 파싱을 빠르게 (= 가능한 한 적은 문자)하기 위해 가능한 한 간결하게 만들어 졌으므로 [
매우 간단한 배열에 사용됩니다 (사용하기에 더 나은 기호?). I
int도 똑같이 분명합니다.
답변
[L 배열 표기법-어디에서 왔습니까?
JVM 사양에서. 이것은 classFile 형식 및 기타 위치에 지정된 유형 이름의 표현입니다.
- ‘[‘는 배열을 나타냅니다. 실제로 배열 유형 이름은
[<typename>
여기서<typename>
배열의 기본 유형의 이름이다. - ‘L’은 실제로 기본 유형 이름의 일부입니다. 예 : 문자열은
"Ljava.lang.String;"
. 후행 ‘;’에 유의하십시오 !!
그리고 예, 표기법은 다른 곳에서도 문서화됩니다.
왜?
다음과 같은 이유로 내부 유형 이름 표현이 선택되었다는 것은 의심의 여지가 없습니다.
- 콤팩트,
- 자체 구분 (메서드 시그니처의 표현에 중요하며 ‘L’과 후행 ‘;’이있는 이유)
- 인쇄 가능한 문자를 사용합니다 (가독성을 위해 … 가독성이 아닌 경우).
그러나 그들이 메소드 를 통해 배열 유형의 내부 유형 이름을 노출하기로 결정한 이유 는 명확하지 않습니다Class.getName()
. 나는 그들이 내부 이름을보다 “인간 친화적”으로 매핑 했을 수 있다고 생각 합니다. 내 추측으로는 너무 늦을 때까지 고치지 못한 것 중 하나 일 뿐이라는 것입니다. (아무도 완벽하지 않습니다 … 가상의 “지능적인 디자이너”조차도 아닙니다.)
답변
나는 C가 char에 의해 취해 졌기 때문에 클래스의 다음 문자는 L입니다.