Java 基础:数组

一、数组声明:

int[] x;
int x[];

在Java中一般使用前者,机把int[]看做一个类型,C++中只能后者

二、数组初始化:

直接提供值:

int[]   x = {1, 3, 4};
int[][] y = {
                   {1, 2, 3},
                   {4, 5}
            };

各个维度的长度信息直接根据提供的值得出。这种使用大括号包裹的值序列作为数组看待,仅仅在数组初始化时才成立,其他情况均认为语法错误。

赋值初始化:

1.默认数组对象:
int[] x = new int[5];
Integer[] y = new Integer[5];

基本类型数组元素为0/false,引用类型的数组元素初值全为null

2.匿名数组对象
int x[] = new int[] { 1, 2 };

匿名数组可以指定数组内的值,不仅可以用在数组类型变量的初始化(其实就是一个赋值)还可以作为函数参数:

    public static void main(final String[] args) {
        print(new String[] { "first line", "second line" });
    }

    public static void print(final String[] lines) {
        for (String line : lines) {
            System.out.println(line);
        }
    }

匿名数组再指定其内值后不能再指定其维度上的长度,也就是说默认数组对象和匿名数组对象只能二选一。

三、数组类型

数组是协变类型(covariant),参见stackoverflow上的讨论:http://stackoverflow.com/questions/18666710/why-are-arrays-covariant-but-generics-are-invariant

简单来说就是如果Male是Man的子类那么,Male[]也是一个Man[]。由讨论可知早期的Java是没有泛型的,所以类似的任务需要把不同类型一些通用处理函数的形参定为Object[]来处理。

现在依旧可以直接使用如下代码:

        ArrayList x = new ArrayList();
        x.add(new Integer(100));
        System.out.println(x.get(0));

只不过会给出警告:

"ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized" raw type就是Object类型。

当加入类型参数后就不会有警告了,即有了泛型后,可以保证容器在编译阶段的类型安全,但实际上编译后使用的其实还是raw type那份代码,不像C++模板真的会有一份独立的代码生成,这个过程称为类型擦除。

 

如果把数组和泛型结合起来会失败:

        List<String>[] x = new List<String>[] { new ArrayList<String>() };
        List<String>[] y = new List<String>[2];

以上两行均有错误提示不能创建对应的泛型list容器的数组。按照Thinking in Java上的说法是:类型擦除会移除数组的类型信息,而数组必须知道他们所持有的确切类型,以强制保证类型安全。不过我们知道,List<String>是List的子类型(这么说是否合适?),而数组又是协变的,那么可以这么做实现上述操作:

        List<String>[] z = new List[10];
        z[0] = new ArrayList<String>();
        z[0].add("haha");
        System.out.println(z[0].get(0));

只有第一行会出现警告,后面的操作其实都包含了泛型检查(信息来自List<String>数组定义)。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。