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