注册本站  论坛  繁體中文

电脑技巧
手机 | MP3 | MP4 | 显卡 | 主板 | 显示器 | 光存储 | 笔记本 | 网络设备 | 移动存储 | 数码相机
键鼠 | CPU | 音箱 | GPS | 电视 | 服务器 | 投影机 | 机箱电源 | 品牌电脑 | 办公打印 |
| 网站首页 | Cisco | Windows | Linux | Java | Dotnet | Oracle | 网页设计 | 平面设计 | 安全 | 软件应用 | 电脑维修 | 办公维修 |
您现在的位置: 电脑技巧 >> Java >> 新手入门 >> 基础入门 >> Java正文

基础入门:关于java数组的深度思考

文章来源:ChinaITLab收集整理 作者:深夜两点 更新时间:2006-9-21 【 】 【加入收藏

    刚刚开始接触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:

  • 下一篇Java:
  • 最 新 热 门
     如何在MyEclipse快速搭建Hibernate应用
     spring aop中单独代理和自动代理的设置
     Nhibernate与代码生成器介绍
     Java多线程同步设计中使用Metux
     讨论5种跟踪Java执行的方法
     在Eclipse中使用SWT进行界面设计
     Spring 结合 Hibernate 配置 C3P0
     开发不再是苦差事 用Eclipse简化开发
     解决运行eclipse内存不足的问题
     利用Ecipse生成Javadoc乱码解决方法
    最 新 推 荐
     基础入门:JAVA初学的一些技巧
     基础入门:关于java数组的深度思考
     当前Java软件开发中几种认识误区
     在Java中动态执行类的静态方法
     在java中对数组a[depth]的理解
     java进阶之字符串替换的思考
     Velocity中的变量问题的解决方法
     如何用javascript在IE 标题栏显示Title
     用javascript响应表单的提交事件
     java入门:怎样取得class文件的路径
    相 关 文 章

    java基础入门之Hibernate 入门
    Spring入门之理解Spring的打包方式
    Spring中IoC的入门实例详解
    用 MyEclipse 开发 Spring 入门操作
    新手入门之Spring BeanDoc使用
    详细的 spring 入门实例讲解运用
    SpringFramework 入门实用攻略
    开源技术基础:TOMCAT的用法
    Tomcat+Mysql入门实例:滚动横幅广告
    初学者入门实践:如何在Tomcat上配置SSL

    | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 网站公告

     

    Copyright 2006-2008 pcjx.com All Rights Reserved
    电脑技巧 版权所有 粤ICP备06059145号 地图
    本网站所有内容未经许可不得转载或做其他使用