关于.length和.length()
曾一度以为是简单的问题,只知道老师说记住就行,但并不知道其中的原理,只知道String底层使用的是char数组,但并不知道String的length()方法的.length从何而来
public int length() {
return value.length;
}
观察一下代码
char a[]={'1','2','3'};
Class class1=a.getClass();
System.out.println(class1.getName());
int b[]=new int[1];
Class class2=b.getClass();
System.out.println(class2.getName());
其结果是:
[C
[I
这是利用反射查看char数组和int数组的类,真是一个奇怪的类名
简单的说,数组的类名由若干个’[‘和数组元素类型的内部名称组成,’['的数目代表了数组的维度。
观察一下代码
int b[]=new int[1];
Class class2=b.getClass();
System.out.println(class2.getName());
System.out.println(class2.getDeclaredFields().length);//所有字段组成的Field数组
System.out.println(class2.getDeclaredMethods().length);//所有方法组成的Method数组
System.out.println(class2.getDeclaredConstructors().length);//所有构造方法组成的Constructor数组
System.out.println(class2.getDeclaredAnnotations().length);//所有注解
System.out.println(class2.getDeclaredClasses().length);
//返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口。
System.out.println(class2.getSuperclass());//返回父类
其结果是:
[I
0
0
0
0
0
class java.lang.Object
由此可见,数组的类的内容为空,且父类是Object
那么数组的类在哪里呢?
答案是在JVM中自动创建,并且类中并没有length成员变量,由代码反编译(字节码文件.class)可以知道
JVM的知识还没有学到,以下内容转载自记忆犹新的博客
public class Main {
public static void main(String[] args) {
int a[] = new int[2];
int i = a.length;
}
}
编译上述代码,并使用jclasslib打开Main.class文件,得到main方法的字节码:
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这条指令触发的了。
小结,.length是由JVM实现的…