当前位置: 首页 > 面试题库 >

数组如何在Java的ByteCode中工作

钱志强
2023-03-14
问题内容

如果我使用List,Vector之类的普通类size(),则会得到一个返回所考虑类的长度的函数,但是如果我使用一个类的数组或默认数据类型,则会得到一个公共成员的长度,该长度返回当前类的长度。数组的长度。

int a[] = new int[3];
a.length; // used without ()

Vector<Integer> v = new Vector<Integer>();
v.length(); // used with ()

这是为什么?我的意思是数组不是自己的类,不是吗?因此,如果它不是类,则不能有成员变量。我不知道如何在后台处理(字节码)。我知道在内存中的数组存储有指向数组第一个元素的指针,并且内存指针被移至索引(i)ArrayPointer + i*(size of DataType)

现在您可以说计算机遍历了数组的所有元素并计算了所有元素,但是计算机如何才能知道数组在哪里结束以及下一个数组在哪里开始呢?大小存储在数组中的“成员变量”从何而来?

我的意思是我们经常使用数组,但是我对ByteCode中Java代码背后发生的事情了解得很少。你能告诉我这怎么可能吗?


问题答案:

数组是Java中的对象,但它们并不对应于真实的类。实际上,JVM会在运行中隐式创建数组类,但出于性能原因,它们不是实际的类。

由于它们是对象,因此可以将它们存储在“对象”字段中并像往常一样传递。但是,它们在字节码级别上的处理有所不同。

首先,阵列与所创建的newarrayanewarraymultinewarray为分别单一维度灵长类动物的,单维对象,和多维数组的说明。相反,常规对象是通过new指令创建的。

获取和设置元素是通过*aload*astore指令完成的。

同样,x.length不是一个实数字段 。而是将其编译为arraylength指令。通过编译以下代码可以看到这一点。

public void test(int size){
    int[] x = new int[size];
    String[] y = new String[size];
    System.out.println(x.length);
    System.out.println(y.length);
}

产生以下字节码

.method public test : (I)V
    .limit stack 2
    .limit locals 4
    iload_1
    newarray int
    astore_2
    iload_1
    anewarray java/lang/String
    astore_3
    getstatic java/lang/System out Ljava/io/PrintStream;
    aload_2
    arraylength
    invokevirtual java/io/PrintStream println (I)V
    getstatic java/lang/System out Ljava/io/PrintStream;
    aload_3
    arraylength
    invokevirtual java/io/PrintStream println (I)V
    return
.end method

尝试length通过手动创建字节码来访问该字段将导致异常,因为该字段实际上不存在。

.method static public main : ([Ljava/lang/String;)V
    .limit stack 1
    .limit locals 1
    aload_0
    getfield [Ljava/lang/String; length I
    return
.end method

结果是

Exception in thread "main" java.lang.VerifyError: Expecting reference to class i
n class ArrayTest at constant pool index 30 in method ArrayTest.main([Ljava/lang
/String;)V
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.getMainMethod(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)


 类似资料:
  • 问题内容: 由于数组中的equals函数仅检查实例,因此它不适用于Set。因此,我想知道如何在Java中制作一组数组? 一种可能的方法是将每个数组放在一个对象中,并为该类实现equals函数,但这会降低性能吗? 问题答案: 由于ArrayList类已经包装了一个数组,因此您可以扩展它并覆盖and 方法。这是一个示例: 更新: 您甚至可以重写它以用于一般用途,只需将代码更改为:

  • 本文向大家介绍java反编译工具Bytecode-Viewer分享,包括了java反编译工具Bytecode-Viewer分享的使用技巧和注意事项,需要的朋友参考一下 在java的开发学习中,可能需要想了解class文件对应的代码内容是什么,如果我们使用IDE工具,可以通过IDE工具的各种反编译插件去进行反编译,但是java的IDE工具还是比较笨重的,启动耗时并且占用内存,这时我们就需要一些简单的

  • 问题内容: 数组在Java中被实现为对象,对吗?如果是这样,我可以在哪里查看数组类的源代码。我想知道数组中的length变量是否定义为常量,如果是这样,为什么不是全部使用大写字母LENGTH来使代码更易于理解。 问题答案: 尽管从它们继承java.lang.Object的角度来看,数组是Object,但是这些类是作为语言的特殊功能动态创建的。它们未在源代码中定义。 考虑以下数组: 没有这样的源代码

  • 问题内容: 我知道该怎么做,但是我发誓您可以像[[0] = {0,0,0,0};那样填写;你是怎么做到的?我确实尝试过Google,但没有任何帮助。 问题答案: 您也可以将其作为声明的一部分:

  • 问题内容: 如何过滤Java中的数组? 我有一系列对象,例如汽车: 类: 用: 现在我要过滤汽车阵列,只保留4门或更多: 我应该怎么做? 在使用Vector之前,请执行以下操作: 然后,我将使用Vector的大小创建一个新数组。然后,我将再次遍历向量并填充新数组。我知道这对于简单的事情来说是一个非常大的过程。 我正在使用J2ME。 问题答案: 编辑: 看到ArrayList不在J2ME中,但是基于