数组用new关键字创建并且组装,使用整形索引来访问,大小不可变,注意经常出现的数组越界问题。
int [] a = new int[2];
int [] a = new int{1,2,3,4}
数组是一个简单的复合数据类型,一系列有序数据的集合,每个数具有相同的数据类型。也是一个对象,既然数组都是对象,那么数组的类究竟是什么呢?当然不是java.util.Arrays啦!我们以int一维数组为例,看看究竟。
public class Main {
public static void main(String args[]){
int a[] = new int[10];
Class clazz = a.getClass();
System.out.println(clazz.getName());
}
}
在SUN JDK 1.6上运行上述代码,输出为:
[I
看起来数组的类很奇怪,非但不属于任何包,而且名称还不是合法的标识符(identifier)。具体的命名规则[1]可以参见java.lang.Class.getName()的javadoc。简单的说,数组的类名由若干个’[‘和数组元素类型的内部名称组成,’[‘的数目代表了数组的维度。
具有相同类型元素和相同维度的数组,属于同一个类。如果两个数组的元素类型相同,但维度不同,那么它们也属于不同的类。如果两个数组的元素类型和维度均相同,但长度不同,那么它们还是属于同一个类。
数组的类有哪些成员呢?
public class Main {
public static void main(String[] args) {
int a[] = new int[10];
Class clazz = a.getClass();
System.out.println(clazz.getDeclaredFields().length); System.out.println(clazz.getDeclaredMethods().length); System.out.println(clazz.getDeclaredConstructors().length);
System.out.println(clazz.getDeclaredAnnotations().length);
System.out.println(clazz.getDeclaredClasses().length);
System.out.println(clazz.getSuperclass());
}
}
0
0
0
0
0
class java.lang.Object
可见,[I这个类是java.lang.Object的直接子类,自身没有声明任何成员变量、成员方法、构造函数和Annotation,可以说,[I就是个空类。
“为什么获取数组的长度用.length(成员变量的形式),而获取String的长度用.length()(成员方法的形式)?”
想必编译器对Array.length进行了特殊处理.
JVM自己在运行时生成的了。JVM生成类还是一件很容易的事情,甚至无需生成字节码,直接在方法区中创建类型数据,就差不多完工了。
The JavaTM Virtual Machine Specification Second Edition
类加载器先看看数组类是否已经被创建了。如果没有,那就说明需要创建数组类;如果有,那就无需创建了。
如果数组元素是引用类型,那么类加载器首先去加载数组元素的类。
JVM根据元素类型和维度,创建相应的数组类。
JVM创建了[I类。JVM不把数组类放到任何包中,也不给他们起个合法的标识符名称,是为了避免和JDK、第三方及用户自定义的类发生冲突吧。JVM也必须动态生成数组类,因为Java数组类的数量与元素类型、维度(最多255)有关,相当相当多了,是没法预先声明好的.
Array.length这样的语法如何通过编译,如何执行的呢?
JVM没有为数组类生成length这个成员变量.
public class Main {
public static void main(String[] args)
{
int a[] = new int[2];
int i = a.length;
}
}
0 iconst_2 //将int型常量2压入操作数栈
1 newarray 10 (int) //将2弹出操作数栈,作为长度,创建一个元素类型为int, 维度为1的数组,并将数组的引用压入操作数栈
3 astore_1 //将数组的引用从操作数栈中弹出,保存在索引为1的局部变量(即a)中
4 aload_1 //将索引为1的局部变量(即a)压入操作数栈
5 arraylength //从操作数栈弹出数组引用(即a),并获取其长度(JVM负责实现如何获取),并将长度压入操作数栈
6 istore_2 //将数组长度从操作数栈弹出,保存在索引为2的局部变量(即i)中
7 return //main方法返回
字节码中,根本就没有看见length这个成员变量,获取数组长度是由一条特定的指令arraylength实现。编译器对Array.length这样的语法做了特殊处理,直接编译成了arraylength指令。另外,JVM创建数组类,应该就是由newarray这条指令触发的了。