`
benbenming
  • 浏览: 112539 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

关于java数组的深度思考

阅读更多

刚刚在CSDN上看到的文章,觉得说的还不错!所以转下来收藏。

 

刚刚开始接触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类来处理”说起来容易,用起来自然,但是细细想来,还是有很多不简单的地方呀。

分享到:
评论

相关推荐

    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学习总结.docx

    - **多角度思考:** 不同的编程思想可能导致不同的实现方式,了解并分析这些差异有助于提升个人的技术水平。 #### 二、业务逻辑与应用场景 **1. 业务知识的重要性:** - **具体领域:** 每个企业的业务都有其独特...

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

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

    五子棋java全套源代码

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

    用java编写的中国象棋

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

    java编写的拼图游戏

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

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

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

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

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

    java 连连看游戏

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

    五子棋java源代码

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

    java编写的智能五子棋

    3. **算法**:游戏的核心是AI算法,用于模拟电脑的思考过程。对于五子棋,常见的算法有Minimax(最小最大搜索)或Alpha-Beta剪枝,它们是基于深度优先搜索的决策方法,以预测对手的可能走法并评估每一步的优劣。 4....

    java编的五子棋

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

    java版水果蔬菜连连看

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

    WUZIQI.rar_java五子棋论文_wuziqi_五子棋 java_五子棋论文_趣味 java

    在五子棋中,这涉及到链表、数组或矩阵等数据结构来表示棋盘状态,并通过深度优先搜索(DFS)、广度优先搜索(BFS)或者更复杂的算法来检查是否有五子连珠。 3. **人工智能(AI)**:如果游戏包含电脑对手,那么需要...

    Java小游戏-记忆测试

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

    wuziqi.rar_java五子棋_五子棋java

    【标题】"wuziqi.rar_java五子棋_五子棋java" 指的是一款使用Java编程语言实现的五子棋游戏。在IT领域,五子棋游戏的开发通常被视为一个经典的计算机科学项目,它涉及到图形用户界面(GUI)设计、事件处理、算法实现...

Global site tag (gtag.js) - Google Analytics