一般来说,程序会产生新的对象,有的时候只能到执行期,才能具体知道产生了多少对象,为了存放这些对象的存放(或者说是reference的存放),程序员必须提供对象的存放容器。
数组(Array)
数组是java用来存放以及随机访问一连串对象的各种做法中,最有效率的一种。数组是简单的线性序列,其中元素能够被快速访问,不过缺点是:当你产生数组后,你不能改变其size。在java中,数组是一个比较特殊的对象。
public class Main{
public static void main(String[] args) {
int[] a = new int [10];
System.out.println(a.getClass().getSuperclass());
System.out.println(a.getClass().getName());
}
}
————————————————————
class java.lang.Object
[I
可以看出Array是Object的直接子类,但是又与一般的java对象有所不同。可以看出其类名是[I,非常滴奇怪,
下面我们再看
public class Main{
public static void main(String[] args) {
System.out.println("Object[]:" + Object[].class);
System.out.println("Object[][]:" + Object[][].class);
System.out.println("Object:" + Object.class);
}
}
++++++++++++++++++++
Object[]:class [Ljava.lang.Object;
Object[][]:class [[Ljava.lang.Object;
Object:class java.lang.Object
从这个实例中我们可以看出数组类和一般java类是不同的,普通的java类是全限定路径名+名字作为自己的唯一标识,但是数组是以[+L+数组元素类全限定路径+类名来作为自己的唯一标识,多了[和L。
看下面一组代码:
public class Main{
public static void main(String[] args) {
int[] a = new int [10];
System.out.println(a.getClass().getName());
int[][] a1 = new int [10][10];
System.out.println(a1.getClass().getName());
}
}
++++++++++++++++++++++++++
[I
[[I
通过这个例子我们知道,[代表一维,[[代表二维。可以简单滴说数组的类名由若干个[和"I"组成,下面使用反射机制看一下。
public class Main{
public static void main(String[] args) {
int a [] =new int [10];
Class myClass = a.getClass();
System.out.println(myClass.getDeclaredFields().length);
System.out.println(myClass.getDeclaredMethods().length);
System.out.println(myClass.getDeclaredAnnotations().length);
System.out.println(myClass.getDeclaredConstructors().length);
System.out.println(myClass.getDeclaredClasses().length);
System.out.println(myClass.getSuperclass());
}
}
++++++++++++++++
0
0
0
0
0
class java.lang.Object
可见, [I这个直接子类自身没有申明任何成员方法,构造方法,成员变量,注解等。可以说这就是一个空类。但是我们经常使用.lenth来查看数组的长度,那么为为甚没有length这个成员方法呢。先不管这length,先搞清楚[I在哪申明的吧。
首先[I不是一个标识符,那么这个类肯定是在代码中显式地申明了,只能是在JVM自己运行的时候生成的、java虚拟机这本书中写到:
类加载器先看看数组类是否已经创建,如果创建了就无需创建,如果没有就创建一个,
如果数组是引用类型元素的话,那么类加载器首先去加载元素的类
JVM根据元素类型和唯独,创建相应的类,
因此,是JVM动态地生成了[I类,再想想,JAVA数组中的元素类型,数量都是未知的,因此必须是动态生成数组类。
为了研究length是怎么来的,我们看下一段代码。
public class Main{
public static void main(String[] args) {
int a [] =new int [10];
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实现(具体不知道如何实现),另外没JVM创建数组类,应该就是newarray这条指令发出的了。