java 0l_关于java:[L数组符号-它来自哪里?

我经常看到使用[L然后使用类型表示数组的消息,例如:

[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

(以上是我刚刚拔出的一个任意示例。)我知道这表示一个数组,但是语法从何而来? 为什么以[开头但没有右方括号? 为什么是L? 它纯粹是武断的,还是背后有其他历史/技术原因?

查看此帖子

对于读者来说,确实没有理由在邮件中使用这种格式。

[代表Array,Lsome.type.Here表示类型。这类似于Java虚拟机规范4.3中看到的字节码内部使用的类型描述符-尽可能简短。唯一的区别在于,实际描述符使用/而不是.表示包。

例如,对于基元,值是:对于int数组,其值为[I,而二维数组将为:[[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."":()V

const #2 = class        #13;    //  java/lang/Object

const #3 = class        #14;    //  S

const #4 = Asciz        ;

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;// "":()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."":()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."":()V

7:   areturn

LineNumberTable:

line 3: 0

}

在原始类文件中(请看第5行):

3a09d0c51b8cc4c6181767ca3f6ddce3.png

参考:有关JVM规范的字段描述

Java没有真正的二维数组,但是您可以创建由数组组成的数组。 [[I只是表示整数数组。

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用于类(以;终止)。

参见此处:JNI类型

编辑:详细说明为什么没有终止]-此代码是允许JNI / JVM快速识别方法及其签名。它旨在尽可能紧凑以使解析速度更快(=尽可能少的字符),因此[用于一个非常简单的数组(使用哪种更好的符号?)。对于int的I同样明显。

您在回答另一个问题。实际上,OP明确表示他没有问"这意味着什么"。

@Nikita如果您仔细阅读该文档,则会发现" L"表示"完全合格的类",而" [L"表示非常特定的数组类型(FQC数组),而不仅仅是任何数组。

@Nikita:问题是"它来自哪里"?好吧,它来自JNI。

@EboMike问题是为什么。那是一个非常有趣的问题,我也想知道答案。而"在JVM的哪一章中指定了它的规范"这一问题则没有。

我认为问题是" L"和" Z"以及其他听起来任意的缩写来自何处。

@EboMike是的。那解决了这个问题(部分),所以我删除了downvote。

这些不是JNI特定的,而是JVM内部的表示形式。

@OscarRyz是正确的,这甚至在JNI出现之前就已成为JVM规范的一部分。 JNI正在重用JVM规范中的表示形式,而不是相反。

[L array notation - where does it come from?

来自JVM规范。这是在classFile格式和其他位置中指定的类型名称的表示。

" ["表示数组。实际上,数组类型名称是[,其中是数组基本类型的名称。

" L"实际上是基本类型名称的一部分;例如字符串是"Ljava.lang.String;"。注意尾随的";"!

是的,该符号也记录在其他地方。

Why?

毫无疑问,选择内部类型名称表示是因为它是:

紧凑,

自定界(这对于方法签名的表示很重要,这就是为什么'L'和结尾的';'存在的原因),以及

使用可打印的字符(出于可读性……如果不可读)。

但是尚不清楚他们为什么决定通过Class.getName()方法公开数组类型的内部类型名称。我认为他们可以将内部名称映射为更"人性化"的名称。我最大的猜测是,这只是他们直到太晚才解决的问题之一。 (没有人是完美的,甚至没有所谓的"智能设计师"。)

我认为这是因为C被char占用了,所以上课的下一个字母是L。

好点子。但是,您是否有任何实际参考证明您是正确的?

另一个来源是Class.getName()的文档。当然,所有这些规范都是一致的,因为它们相互适合。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值