Java是一种强类型的语言。既然是对象, 那么就必须属于一个类型,比如根据Person类创建一个对象,这个对象的类型就是Person。那么数组的类型是什么呢?看下面的代码:
- int[] a1 = {1, 2, 3, 4};
- System.out.println(a1.getClass().getName());
- //打印出的数组类的名字为[I
- String[] s = new String[2];
- System.out.println(s.getClass().getName());
- //打印出的数组类的名字为 [Ljava.lang.String;
- String[][] ss = new String[2][3];
- System.out.println(ss.getClass().getName());
- //打印出的数组类的名字为 [[Ljava.lang.String;
打印出a1的类型为[ I ,s 的类型是[Ljava.lang.String; , ss的类型是[[Ljava.lang.String;
所以,
数组也是有类型的。只是这个类型显得比较奇怪。你可以说a1的类型是int[],这也无可厚非。但是我们没有自己创建这个类,也没有在Java的标准库中找到这个类。也就是说不管是我们自己的代码,还是在JDK中,都没有如下定义:
- public class int[] {
- // ...
- // ...
- // ...
- }
这只能有一个解释,那就是 虚拟机自动创建了数组类型,可以把数组类型和8种基本数据类型一样, 当做java的内建类型。这种类型的命名规则是这样的:
*
每一维度用一个[表示;开头两个[,就代表是二维数组。
* [后面是数组中元素的类型(包括基本数据类型和引用数据类型)
* [后面是数组中元素的类型(包括基本数据类型和引用数据类型)
在java语言层面上,s是数组,也是一个对象,那么他的类型应该是String[],这样说是合理的。但是在JVM中,他的类型为[java.lang.String。顺便说一句普通的类在JVM里的类型为 包名+类名,也就是全限定名。同一个类型在java语言中和在虚拟机中的表示可能是不一样的。
Java中数组的继承关系
上面已经验证了,数组是对象,也就是说可以以操作对象的方式来操作数组。并且数组在虚拟机中有它特别的类型。既然是对象,遵循Java语言中的规则 -- Object是上帝, 也就是说所有类的顶层父类都是Object。数组的顶层父类也必须是Object,这就说明数组对象可以向上直接转型到Object,也可以向下强制类型转换,也可以使用instanceof关键字做类型判定。 这一切都和普通对象一样。如下代码所示:
- //1 在test1()中已经测试得到以下结论: 数组也是对象, 数组的顶层父类是Object, 所以可以向上转型
- int[] a = new int[8];
- Object obj = a ; //数组的父类也是Object,可以将a向上转型到Object
- //2 那么能向下转型吗?
- int[] b = (int[])obj; //可以进行向下转型
- //3 能使用instanceof关键字判定吗?
- if(obj instanceof int[]){ //可以用instanceof关键字进行类型判定
- System.out.println("obj的真实类型是int[]");
- }
Java中数组的另一种“继承”关系
如下代码是正确的,却很容易让我们疑惑:
- String[] s = new String[5];
- Object[] obja = s; //成立,说明可以用Object[]的引用来接收String[]的对象
Object[]类型的引用可以指向String[]类型的数组对象? 由上文的验证可以得知数组类型的顶层父类一定是Object,那么上面代码中s的直接父类是谁呢?难道说String[]继承自Object[],而Object[]又继承自Object? 让我们通过反射的方式来验证这个问题: