`
TonyLian
  • 浏览: 402090 次
  • 性别: 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类来处理”说起来容易,用起来自然,但是细细想来,还是有很多不简单的地方。

分享到:
评论

相关推荐

    转贴:随心所欲的Web页面打印技术

    【正文】 随心所欲的Web页面打印技术是针对基于B/S架构的应用程序中客户端页面打印问题的一种解决方案。传统的Web页面打印方式,如使用IE的内置打印功能或水晶报表,往往无法满足特定的排版和定位需求。...

    转贴:利用钩子技术控制进程创建.txt

    根据提供的文件信息,可以看出标题与描述均指向了“利用钩子技术控制进程创建”的主题,但实际内容似乎并未直接涉及这一技术细节,而是包含了大量非结构化和个人化的文本信息。因此,下面将基于标题和描述中提及的...

    java面试大全(中软国际的大公司)

    1. **基础概念**:Java的基础知识包括但不限于语法、面向对象编程(OOP)、异常处理、数据类型、类与对象、封装、继承和多态。文档"Java学习过程中应该深入理解的一些重点.doc"可能会涵盖这些内容。 2. **集合框架*...

    java编程事项(转载收集整理版)

    1. **基本语法**:Java是一种静态类型的面向对象编程语言,其语法严谨。学习Java首先要了解变量声明、数据类型(如int、String等)、运算符、控制结构(如if语句、for循环、while循环)以及方法定义。 2. **类与...

    flex和java进行CRUD操作(转贴)

    本篇文章将围绕"Flex与Java进行CRUD操作"这一主题展开,详细介绍如何使用Flex作为前端,通过与Java后端交互来实现创建(Create)、读取(Retrieve)、更新(Update)和删除(Delete)数据的功能。 1. **Flex基础知识** ...

    android和java面试大全集

    史上最全的android和java面试文档集。包括有: java程序员面试宝典.txt Java面试宝典2011版-1C,Java基础部分.doc 三大框架面试题.zip 技术面试题.zip Android笔试题库 C语言终极面试宝典.doc Java笔试题目汇总.pdf ...

    Java SafeEngine API接口说明

    Java SafeEngine API接口说明 Java SafeEngine API接口说明是上海市数字证书认证中心有限公司开发的数字证书系统的接口说明,旨在提供给开发者使用Java语言开发安全的数字证书应用程序。该API接口提供了丰富的功能...

    转贴:四十岁的男人要像孩子一样养.doc

    在当今社会,四十岁的男性被赋予了多重角色:他们在职场上可能是中流砥柱,是家庭的经济支柱,同时也是孩子的父亲和妻子的伴侣。人们常说,四十不惑,但随着社会压力的加大和生活节奏的加快,四十岁的男性在面临生活...

    函数调用,参数堆栈等学习资料收集

    函数调用,参数堆栈等学习资料收集 关于函数调用时堆栈的变化分析(转自Jim's blog) - H_S_的学习总结与心得 - 博客园.mht 函数参数堆栈.txt ...转贴:关于函数调用的深入分析 百度空间_应用平台.mht

    asp.net中的并发控制

    转贴:asp.net中的并发控制 并发控制的类型 通常,管理数据库中的并发有三种常见的方法: 保守式并发控制 开放式并发控制 最后的更新生效

    Axis学习笔记(网页转贴)

    **Axis学习笔记(网页转贴)** Axis是一个开源的Java库,主要用于创建和使用Web服务。它是Apache软件基金会的一部分,广泛应用于开发基于SOAP(简单对象访问协议)的Web服务。本学习笔记将深入探讨Axis在Web服务开发...

    电子政务-导电泡棉转贴装置.zip

    6. **维护与保养**:提供关于导电泡棉及转贴装置的日常维护、清洁、替换等方面的指导,以延长设备使用寿命。 7. **未来趋势**:探讨电子政务领域中导电材料和技术的未来发展,可能涉及新材料的研发、更高效的转贴...

    易语言源码动网转贴.rar

    "动网转贴"这个主题可能指的是在论坛或者社交网络中实现帖子转发或分享的功能。 动网转贴的源码可能涉及到以下几个方面的知识点: 1. **网络通信**:在实现动网转贴功能时,首先需要与服务器进行交互,发送用户的...

    易语言动网转贴.rar

    关于"动网转贴"的具体实现,可能涉及到以下知识点: 1. **网页爬虫技术**:为了从动网论坛抓取帖子,开发者可能使用了HTTP请求和解析HTML的技术,这可能涉及到了易语言的网络模块和字符串处理。 2. **数据解析与处理...

    动网转贴.zip易语言项目例子源码下载

    易语言提供了一系列的字符串函数,可以方便地进行字符串查找、替换、分割等操作,同时也支持数组、列表等数据结构,便于数据的存储和检索。 用户界面设计是直接影响用户体验的关键。易语言提供了一套完整的图形用户...

Global site tag (gtag.js) - Google Analytics