`
flash59
  • 浏览: 97701 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java数组的深度思考【转】

阅读更多
刚刚开始接触java数组的人都会听到一句类似的话:java是纯面向对象的语言,他的数组也是一个对象。于是乎,笔者就按照一个对象的方式来使用数组,心安理得。直到我接触到C的数组后,才发现将数组作为一个类来使用在实现上是多么的“不自然”。
首先我们看一下表面现象,数组创建的时候采用的是如下语句:

  MyClass[] arr = new MyClass[9];

  而普通类采用的是如下语句:

  MyClass obj = new MyClass();

  就是说,创建数组的时候不使用小括号传参。使得数组和普通类看起来就有很多不同,因为小括号里的参数是传递给构造方法的,进而让人感觉数组类是没有构造方法的。

  
再往深了想,还有很多让人感觉不自然的东西。可以肯定的是,java确实将数组作为了一个类来处理。还是用上面的例子说明:

  可以通过以下方法得到MyClass[]的Class实例:arr.getClass()或MyClass[].class。这样,我就可以向数组类里面“窥探”了。

  
  Class clazz = MyClass[].class;
  System.out.println(clazz.getConstructors().length);

  
  打印出来的结果是0;证明数组类确实没有构造方法。

  
  如果强行执行clazz.newInstance();就会得到下面的错误。

  java.lang.InstantiationException: [Larraytest.MyClass;

  证明数组类不能够通过普通的反射方式来创建一个实例。

  
  再看看数组类的“庐山真面目”:

  System.out.println(clazz);

  输出是:

  [Larraytest.MyClass

  对Java Class文件结构稍有了结就知道,这个字符串的意思就是一个元素类型为arraytest.MyClass的一维数组。也就是说,数组类型不是和普通类一样,以一个全限定路径名+类名来作为自己的唯一标示的,而是以[+一个或者多个L+数组元素类全限定路径+类来最为唯一标示的。这个()也是数组和普通类的区别。而这个区别似乎在某种程度上说明数组和普通java类在实现上有很大区别。因为java虚拟机(java指令集)在处理数组类和普通类的时候,肯定会做出区分。笔者猜想,可能会有专门的java虚拟机指令来处理数组。

  既然我们可以得到数组的Class类实例,就说明肯定需要调用ClassLoader的 defineClass(不一定非要是loadClass方法)方法,来构造一个Class实例。java虚拟机规范规定,任何一个可以被加载的类,如果其类文件存储在文件系统上,那么一个*.class文件只能存储一个类信息,也就是说,数组类的信息不可能以类文件的形式存储在本地磁盘上(否则任意一个类都要配有255个数组类了.....),既然这样,那就说明java虚拟机肯定内置了一块用来声明数组类的数据(不管是几级数组)。这是符合java虚拟机规范的,规范规定class类数据可以来自任意介质,包括本地磁盘、网络、数据库、内存等等。

  分析到这里,我基本上可以肯定:java对数组对象化的操作的支持是指令级的,也就是说java虚拟机有专门针对数组的指令。数组的Class类实例是java虚拟机动态创建动态加载的,其结构与普通java类的Class实例有一些不同。

  JDK API中有一个java.lang.reflect.Array类,这个类提供了很多方法(绝大多数是native方法,这在另一个方面证明了java对数组的支持是专用指令支持的,否则用本地方法干嘛^_^),用来弥补我们对数组操作的局限性。

  下面这句话用来创建一个一维的、长度为10的、类型为arraytest.MyClass的数组:

  arraytest.MyClass[] arr = (arraytest.MyClass[]) Array.newInstance(arraytest.MyClass, 10);

  下面这句话用来创建一个二维的、3乘5的、类型为arraytest.MyClass的数组:

  int[] arrModel = new int[]{3,5};
Object arrObj = Array.newInstance(Sub.class, arrModel);

  当然你可以用一个数组的引用指向上面的二维数组,这里我们用一个Object的引用指向他。
使用的时候,我们也是可以利用Array类提供的方法来实现:

  System.out.println(Array.getLength(arrObj);//第一维长度为3
  System.out.println(Array.getLength(Array.get(arrObj, 2)));//第二维长度为5,这里如果写3,就会得到你意想之中的java.lang.ArrayIndexOutOfBoundsException

  打印结果是如我们所想的:

  3
  5

  对于数组的Class类实例,还有一些奇怪的现象:

  在运行代码 java.lang.reflect.Field fieldarr = clazz.getField("length");的时候,会抛出异常:java.lang.NoSuchFieldException: length,这似乎在说数组类没有length这个域,而这个域其实是我们用的最多的一个(也就是说这个域是肯定存在的)。笔者认为关于数组的Class类实例、数组的实现等,还有很多“猫腻”在里面。

  顺便说一句,java数组最多只能是255维的。这个让人看到了C的影子,嘿嘿。“Java把数组当作一个java类来处理”说起来容易,用起来自然,但是细细想来,还是有很多不简单的地方。
分享到:
评论
1 楼 南星_JAVA 2009-12-14  
看似很简单,一琢磨深藏奥秘!

相关推荐

    java--数组.txt

    ### Java数组深度解析 在Java编程语言中,数组是一种非常基础且重要的数据结构,它能够存储固定数量的同类型元素。对于初学者来说,经常会听到这样一句话:“Java是一门纯粹的面向对象的语言,其数组也是一种对象。...

    java 编程入门思考

    2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用...

    对Java的思考(Thinking in Java) Java入门 java与C++对比 深入浅出

    《Thinking in Java》是一本深度剖析Java编程语言的著作,旨在帮助读者深入理解Java的核心概念和技术。本书通过对比Java和C++,使读者能够更好地理解Java的独特之处,并为初学者提供了一个逐步学习Java的框架。 第1...

    五子棋 java版 博弈算法

    在Java版的五子棋实现中,首先我们需要创建一个棋盘模型,通常使用二维数组来模拟棋盘,每个元素代表棋盘上的一个位置。数组的值可以表示棋子的颜色(例如,0表示空位,1表示黑棋,2表示白棋)。棋盘大小通常是15x15...

    Java程序设计与数据结构第六章习题答案

    在Java中,数组可以是一维、二维或多维的。学习如何声明、初始化和操作数组是编程的基础,同时也涉及到数组遍历、查找和排序等操作。 2. **链表**:链表是一种动态数据结构,每个元素(节点)包含数据和指向下一个...

    五子棋java全套源代码

    可能使用二维数组或者特定的数据结构(如矩阵、链表)来表示棋盘,并用特定的方式(如位运算)记录棋子位置和棋局状态。 7. **游戏规则的实现**:实现五子棋的规则,包括判断胜负条件(横、竖、斜方向连续五个同色...

    用java编写的中国象棋

    - 棋局评估:可能会使用某种搜索算法(如深度优先搜索、Alpha-Beta剪枝)来评估当前棋局的优劣,辅助AI决策。 5. **多线程**: - 为了实现游戏的并发性,可能使用了Java的线程机制。例如,用户操作和AI思考可以在...

    java编写的拼图游戏

    这款游戏中,玩家可以体验到经典的拼图玩法,通过逻辑思考和空间感知能力将打乱的图像重新组合成完整的图片。以下是对这个项目及其相关知识点的详细说明: 1. **Java编程语言**:Java是一种广泛使用的面向对象的...

    将升序数组转化为平衡二叉搜索树

    - **空间复杂度**:递归栈的最大深度为树的高度,即O(log n),此外还需要存储左右子数组的空间,因此总的空间复杂度为O(n)。 #### 进阶思考 1. **非递归实现**:虽然递归方式简洁明了,但在实际应用中,为了避免...

    java拼图小游戏

    4. **数据结构**:为了存储拼图的状态,通常会使用二维数组或链表来表示拼图的每个部分。每个单元格包含图像块的信息,如位置、旋转状态等。 5. **算法**:拼图游戏的核心算法是解决拼图的逻辑。这可能包括: - **...

    基于慕课的高职JAVA程序设计教学实践与思考.pdf

    本文将结合高职教育的特点,探讨在慕课环境下Java程序设计教学的实践与思考。 Java程序设计教学的目标和内容 Java程序设计课程的开设旨在使学生掌握Java语言的基本使用方法,包括语法和特性,同时理解和掌握API的...

    java编的五子棋

    3. **数据结构**:棋盘状态通常用二维数组或自定义棋盘类来存储,每格代表一个棋盘位置,存储着当前棋子的颜色或者为空。 4. **游戏逻辑**:五子棋的核心逻辑包括检查落子合法性、判断胜负条件(横向、纵向、斜向...

    java版水果蔬菜连连看

    这需要用到数据结构如二维数组或链表来存储游戏盘面,以及算法(如深度优先搜索或广度优先搜索)来查找和消除匹配的元素。 3. 事件处理:当玩家点击某个图标时,程序需要捕获并处理这个事件。Java提供了事件监听器...

    java 连连看游戏

    在实现连连看的核心算法——寻找可匹配的图案对时,可以运用深度优先搜索(DFS)或广度优先搜索(BFS)策略,结合二维数组或链表数据结构进行高效操作。 此外,事件驱动编程是Java GUI开发的关键。利用...

    JAVA 考试竞赛题--有一定的难度

    Java竞赛题目通常涵盖了广泛的编程概念和技术,旨在测试参赛者对Java语言的理解深度、编程技巧以及问题解决能力。这类竞赛往往包含设计模式、数据结构、算法、多线程、网络编程、异常处理、集合框架、IO流、反射等...

    java第五版课后答案

    在实际学习过程中,应该结合教材内容,先独立思考,然后对照答案理解思路,尝试自己修改和优化代码,这样可以更好地吸收知识。同时,遇到不理解的部分,可以通过网络资源、论坛讨论或者向教师请教来解决,以达到深度...

    Java小游戏-记忆测试

    综上所述,"Java小游戏-记忆测试"项目涵盖了Java编程语言的多个核心方面,不仅锻炼了开发者的技术能力,也展现了其在软件设计和用户体验方面的思考。通过参与这样的项目,开发者可以提升自己的编程技巧,并对Java ...

    五子棋java源代码

    5. **算法**:AI部分可能使用了搜索算法,如深度优先搜索(DFS)或Minimax算法,配合α-β剪枝来优化搜索效率,使得计算机能够作出合理的决策。 6. **递归**:Minimax算法是基于递归的,它通过模拟所有可能的走法来...

    java版剑指Offer

    6. 面试技巧与问题分析:在每道题目的分析中,都涉及了如何针对该问题展开思考,以及如何向面试官展示自己的解题思路,这对于提升面试表现非常有帮助。 由于内容繁多,以下对部分题目进行知识点的详细说明: - ...

Global site tag (gtag.js) - Google Analytics