`
RednaxelaFX
  • 浏览: 3052448 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

Java的多维数组

阅读更多
继续打捞站内信。

同学F 写道
在java中的数组访问,举个例子,对于数组int[][][] arry = new int[2][3][4],我从字节码上看,虚拟机对某个arry中的某个元素如arry[1][1][3]的访问,似乎是先获取arry[1]的引用,然后再获取arry[1][1]的引用,再获取数据arry[1][1][3],如果这个过程我没有理解错的话,那么虚拟机是不是对这些“中间引用”(arry[1]、arry[1][1]之类的)创建相应的类型,否则单凭这些引用如何进行数组下表的越界校验?


Java和JVM里本来就没有所谓的“矩形数组”的概念,多维数组只有“数组的数组”(array-of-arrays)或者叫jagged array。
与之对比,C#和CLI里就有真正的多维“矩形”数组,也支持“数组的数组”。关于几种不同的语言里多维数组的差异,可以参考以前一帖

也就是说,在Java里
类型 说明
int 这是一个基本类型
int[] 这是以int为元素的数组类型
int[][] 这是以int[]为元素的数组类型
int[][][] 这是以int[][]为元素的数组类型

一个数组类型的“组件类型”(component type)就是该数组类型的维度(dimension)减去1的类型;字面上看也就是少一对[]。

每个维度上都是一个真正的数组对象。每个数组对象都记录着自己的长度(length)。所以对每个数组对象都可以用arraylength指令去查询它们的长度,每个Xaload / Xastore也就可以做相应的边界检查。

int[][][] array = new int[2][3][4];

这只是个简写而已。虽然这个语句的右手边对应与一组JVM字节码指令,
   0:	iconst_2
   1:	iconst_3
   2:	iconst_4
   3:	multianewarray	#2,  3; //class "[[[I"

实际上它的作用大致等同于:
int[][][] a = new int[2][][];
for (int i = 0; i < a.length; i++) {
  a[i] = new int[3][];
  for (int j = 0; j < a[i].length; j++) {
    a[i][j] = new int[4];
  }
}


以32位HotSpot VM的实现为例,上面两个版本的代码创建出来的对象都是这种样子的:



这样就好理解了吧?

可以参考JVM规范去了解multianewarray的语义:
http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc9.html#multianewarray

HotSpot VM的实现里,参考解释器版的实现比较直观,在这里:
interpreterRuntime.cpp: InterpreterRuntime::multianewarray
objArrayKlass.cpp: objArrayKlass::multi_allocate
typeArrayKlass.cpp: typeArrayKlass::multi_allocate

该指令接受两个参数,
第一个是多维数组的类型,这个例子是里[[[I,也就是int[][][];
第二个是多维数组的维度n,这个例子里n=3。
知道了维度之后,JVM执行这条指令时就会从操作数栈顶弹出n个值(必须都是int型),并以这些int为每个维度的length嵌套循环的去创建数组对象出来;这个例子里也就是把前面iconst_2、iconst_3、iconst_4指令压到操作数栈上的常量2、3、4分别弹出来,并且作为数组的各维度的长度去创建实例。

multianewarray与上面写的那种显式用嵌套循环来初始化多维数组的Java代码最大的差异是,multianewarray会检查所有维度上的length是否非负,如果有负数就会抛NegativeArraySizeException;要注意的是无论传入的多维数组是否有维度的长度是0,所有维度都会被检查
而显然,如果显式用嵌套循环来初始化的话,负数长度的问题就有可能“逃过去”。

看例子:
public class Foo {
  public static void main(String[] args) {
    int[][][] array = new int[1][0][-1];
  }
}

这个会抛NegativeArraySizeException异常:
$ java Foo
Exception in thread "main" java.lang.NegativeArraySizeException
        at Foo.main(Foo.java:3)



public class Bar {
  public static void main(String[] args) {
    int[][][] a = new int[1][][];
    for (int i = 0; i < a.length; i++) {
      a[i] = new int[0][];
      for (int j = 0; j < a[i].length; j++) { // a[i].length == 0
        a[i][j] = new int[-1];                // 这个循环体不会被执行,-1的长度就被“跳过去”了
      }
    }
  }
}

这个不会抛异常。
  • 大小: 179.1 KB
分享到:
评论
5 楼 HanyuKing 2019-01-29  
   
4 楼 RednaxelaFX 2011-05-31  
IcyFenix 写道
讨论一下文中一个字面翻译的问题:
RednaxelaFX 写道
一个数组类型的“元素类型”(component type)就是该数组类型的维度(dimension)减去1的类型;字面上看也就是少一对[]。

component type是否翻译成“组件类型”会恰当一些?因为数组里面还有个element type表示“所有[]都去掉”的那个类型,把“元素类型”留给它会不会好一些?
JVMS 3,chapter 2.4  写道
An array type consists of a component type with a single dimension (whose length is not given by the type). The component type of an array type may itself be an array type. If, starting from any array type, one considers its component type, and then (if that is also an array type) the component type of that type, and so on, eventually one must reach a component type that is not an array type; this is called the element type of the array type

嗯…“组件类型”听起来怪怪的,不过就先用它吧 ^^
3 楼 IcyFenix 2011-05-31  
讨论一下文中一个字面翻译的问题:
RednaxelaFX 写道
一个数组类型的“元素类型”(component type)就是该数组类型的维度(dimension)减去1的类型;字面上看也就是少一对[]。

component type是否翻译成“组件类型”会恰当一些?因为数组里面还有个element type表示“所有[]都去掉”的那个类型,把“元素类型”留给它会不会好一些?
JVMS 3,chapter 2.4  写道
An array type consists of a component type with a single dimension (whose length is not given by the type). The component type of an array type may itself be an array type. If, starting from any array type, one considers its component type, and then (if that is also an array type) the component type of that type, and so on, eventually one must reach a component type that is not an array type; this is called the element type of the array type
2 楼 RednaxelaFX 2011-05-19  
IcyFenix 写道
这个例子小小滴补充一下,避免有同学误以为multianewarray指令会抛NegativeArraySizeException,而使用anewarray和newarray组合就不会抛NegativeArraySizeException。

嗯完全正确。多谢补充
1 楼 IcyFenix 2011-05-19  
public class Bar {
  public static void main(String[] args) {
    int[][][] a = new int[1][][];
    for (int i = 0; i < a.length; i++) {
      a[i] = new int[0][];
      for (int j = 0; j < a[i].length; j++) {
        a[i][j] = new int[-1];
      }
    }
  }
}
这个例子小小滴补充一下,避免有同学误以为multianewarray指令会抛NegativeArraySizeException,而使用anewarray和newarray组合就不会抛NegativeArraySizeException。

这2个指令也会抛出NegativeArraySizeException,只不过这个异常并非Linking Exception,换句话说,代码不执行到它就没有问题。

所以请同学们看清楚,撒迦使用的是:
int[][][] array = new int[1][0][-1]; 
而不是
int[][][] array = new int[1][1][-1]; 
或者
int[][][] array = new int[1][-1][-1]; 
后面2条用anewarray和newarray来写也会抛异常。

相关推荐

    java多维数组

    ### Java多维数组详解 #### 一、多维数组的概念与背景 多维数组是指具有两个或更多维度的数组,通常我们所说的多维数组至少包括二维数组和更高维度的数组。在现实生活中,多维数组的应用场景十分广泛,比如学校的...

    java多维数组排序(代码)

    题目: 假定本学期某班上有5门课,该班上有10人 (1) 请输入该班同学的学号,姓名,5门课的成绩至数组A、B中,再按5门课的总分排序,然后列出排序后的序号,学号,姓名,成绩1~5; (2) 求出5门课的平均成绩

    java多维数组.txt

    java多维数组.txt

    实例3 演示一维数组和多维数组的初始化和基本操作

    本实例将深入讲解一维数组和多维数组的初始化与基本操作。数组是内存中的连续区域,通过索引来访问其元素,这对于快速访问和处理大量数据非常有用。 一、一维数组 一维数组可以看作是线性的数据结构,类似于一个...

    Java多维数组和Arrays类方法总结详解

    Java多维数组和Arrays类方法总结详解 Java多维数组是指数组的元素也是数组,例如二维数组、三维数组等。Java中可以声明多维数组的方式有多种,下面我们将详细介绍。 一、数组的三种声明方式 Java中数组的声明方式...

    基于eclipse编写的java多维数组和字符加密代码

    可以用来简单学习的代码,也是自己学习过程中的一个记录

    java二维数组倒置实例

    在Java编程语言中,二维数组是一种特殊的数组结构,它由多个一维数组构成,形如一个矩阵。在处理二维数组时,我们有时需要对其进行特定的操作,例如“倒置”。这里的“倒置”可以理解为对数组的行或列进行翻转。本...

    Java语言编程 多维数组

    Java语言编程 多维数组 Java语言编程中,多维数组是数组的数组,一维数组中的每个成员又是一维数组。二维数组是最常见的多维数组形式。 1. 定义二维数组 定义二维数组的基本格式有两种: 方式一:`dataType [][]...

    Java多维数组原理解析详细视频教程,看完还不懂你来找我,负责包你学会.mp4

    前端HTML5+CSS3+JS+AJAX零基础入门到项目实战视频教程

    赋值定义多维数组.rar

    在Java中,多维数组可以视为对象,可以这样定义: ```java int[][] arr = new int[3][4]; // 定义一个3行4列的二维数组 ``` 赋值同样通过索引进行: ```java arr[0][0] = 1; // 给第一行第一列赋值 ``` 3. ...

    Java中多维数组.pdf

    Java中多维数组.pdf 学习资料 复习资料 教学资源

    多维数组

    3.2 动态多维数组:在动态内存分配的环境中,如Java和C#,可以通过连续分配内存并维护行和列的大小信息来实现多维数组。 3.3 数组的嵌套:在Python等语言中,可以使用嵌套的列表来实现多维数组,如`arr = [[1, 2, 3...

    Java中数组的各种应用

    Java支持多维数组,即数组的数组。例如,创建一个2D数组(矩阵): ```java int[][] matrix = new int[3][4]; ``` 遍历2D数组的方式稍有不同: ```java for (int i = 0; i ; i++) { for (int j = 0; j [i]....

    java一维二维多维数组

    对java中数组的概念、使用、内存的使用情况都有详细说明。包括了一维、二维、多维数组

    JAVA程序设计课件-多维数组.pptx

    在这个课件中,我们聚焦于一个关键概念——多维数组,它是Java编程中处理复杂数据结构的重要工具。 多维数组,顾名思义,就是数组的数组,它允许我们在一个数组中存储其他数组。在实际编程中,最常用的是二维数组,...

    Java中使用数组完成学生成绩统计的多种实现代码清单.pdf

    1. **数组定义与初始化**:Java中的数组可以是多维的,例如`int a[][]`表示一个二维数组,每行和每列的元素都是整数。可以通过`{}`来初始化数组。 2. **遍历数组**:使用嵌套循环遍历二维数组,外层循环遍历行,内...

    Java数组与内存控制

    - Java并没有真正的多维数组,所谓的多维数组实际上是一维数组中的元素也是一个一维数组。例如: ```java int[][] matrix = new int[3][4]; ``` - 这个例子中,`matrix`是一个二维数组,但实际上它是包含三个...

    深入探讨:多维数组反转技术与实现

    多维数组的反转是一个复杂但有趣的问题,涉及到多个维度的遍历和交换。通过按行反转、按列反转和整体反转,我们可以满足不同的应用场景。在实际应用中,我们需要根据具体的需求选择合适的反转策略,并考虑空间和时间...

    Java软件开发实战 Java基础与案例开发详解 4-3 多维数组 共7页.pdf

    ### Java软件开发实战:Java基础与案例开发详解之多维数组 #### 4.3 多维数组 在Java编程中,多维数组是数组的一种高级形式,它允许程序员创建包含多个维度的数据结构。最常见的是二维数组,即数组中的每个元素...

    二维动态数组的实现

    控制台实现显示二维动态数组的图形,变形,编辑,表示。

Global site tag (gtag.js) - Google Analytics