Java数组小结

来源:互联网 发布:网络课程培训心得 编辑:程序博客网 时间:2024/06/06 09:19

为什么要使用数组

在容器现在很普遍的情况下,我们有多种方法可以持有对象,并且容器使用起来还很方便,那么为什么还要提到数组这个话题?
数组区别于其他容器的特性有三个:高效率,可以精确持有类型信息,可以持有基本类型。数组是Java中用来持有和访问对象最高效的方式,没有之一。数组的存储方式是简单的线性序列,这是导致其能告诉访问的根本原因。大家可能会想ArrayList不是和数组的特性非常相似么,为什么不使用ArrayList来代替Array。况且ArrayList还提供了更多的方法,并且可以动态的更改容器大小以适应元素的增加。那么我只能说,他提供这些额外的功能都有一定的开销的(别的不说,get这种使用Object类型参数的方法,向上转型是不是要开销?)。在我们追求极限效率的情况下,使用数组是一种更好的选择。
数组还优于容器的另外一个优点是:其可以持有一个有具体类型的变量。而像ArrayList这种。不可以。在1.5版本以后,虽然Java中加入了泛型,ArrayList这种容器好像是具有了可以持有具体类型的对象的这样的能力,实际不然,如果我们去看他源代码的话,我们就可以看到,ArrayList内部是一个Object的数组来存放对象,这就免不了存的时候向上转型,取的时候向下转型。当然这都不用你来做,编译器帮你做了。
另外一个特点就是持有基本类型。在Java引入了AutoBoxing这样一种机制以后,容器类好像是也拥有了这样一个功能?但他存放的是基本类型吗?不是!是包装类型。虽然我们取出来的时候还是可以得到基本类型,但是这个转换过程中是带有自动包装机制在其中起作用的。这就难免会让效率变低。综上所述,我们还是有说一下Java数组的必要性的。

Java中的数组是什么

不管是一个什么类型的数组,Java本身是一个创建在堆上的对象的引用(如果是基本类型的话就是类型本身的值,而不是引用)。而创建在堆上的这个对象是一个存有对其他对象引用的对象。他可以显式的使用new关键字来创建,也可以隐式的通过int[] a={1,2};这种隐式的方式来创建。此对象只有一个可以访问的属性就是length。也只有一个可以用来访问其元素的方法,你可以认为是[]中括号。

如何使用

二维数组

煮个栗子

import static java.lang.System.out;class BerylliumSphere{    private static long counter;    private final long id=counter++;    public String toString(){        return "Sphere "+id;    }}public class ArrayOptions {    public static void main(String... args){        BerylliumSphere[] a;        BerylliumSphere[] b=new BerylliumSphere[5];        BerylliumSphere[] c=new BerylliumSphere[4];        for(int i=0;i<c.length;i++){            c[i]=new BerylliumSphere();        }        BerylliumSphere[] d={new BerylliumSphere(),new BerylliumSphere()};        a=new BerylliumSphere[]{new BerylliumSphere(),new BerylliumSphere()};    }}

多维数组

在Java中只要理解好了数组本身也是一个对象的引用就好办。多维数组其本质上就是数组的数组。其用法如下:

public class Test1 {    public static void main(String... args){        int[][]a={{2,2,2},{3,3,3}};    }}

Ragged Array

Java中还支持Ragged array:

public class Test1 {    public static void main(String... args){        int[][]a={{2,2},{3,3,3}};    }}
public class RaggedArray {    public static void main(String... args){        Random random=new Random(47);        int[][][] a=new int[random.nextInt(7)+1][][];        for (int i=0;i<a.length;++i){            a[i]=new int[random.nextInt(7)+1][];            for(int j=0;j<a[i].length;++j){                a[i][j]=new int[random.nextInt(7)+1];            }        }        System.out.println(Arrays.deepToString(a));    }}

其输出如下:
[[[0, 0, 0, 0, 0, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0]], [[0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0]], [[0, 0, 0, 0, 0], [0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0]], [[0, 0, 0]], [[0, 0, 0, 0, 0]], [[0]]]
可以看到,层次不齐。这也就是Ragged的由来。

泛型数组

在泛型内部由于擦除机制的存在,是不能声明泛型类型的数组的。如E[] es=new E[10];这样的是肯定不行的。如果想要这么做可以参考泛型机制总结那里。
泛型数组的用法主要如下:

public class GenericArray {    public static void main(String... args){        //List<BerylliumSphere>[] a=new ArrayList<BerylliumSphere>[10];        List<BerylliumSphere>[] a=new ArrayList[10];        List<String>[] s;        List[] la=new List[10];        s=(List<String>[])la;        s[0]=new ArrayList<String>();        //s[1]=new ArrayList<Integer>();        Object[] objects=s;        objects[1]=new ArrayList<String>();    }}

第一句不行的主要原因是因为类型擦除机制擦去了类型信息,而数组在运行时也要通过类型信息来确保插入元素的安全,因此不让这么声明。