Java数组类型

在Java中,数组可以说是经常用到的,但关于数组是什么类型的这个问题,我却没有深入研究过。以下内容参考自《Java语言规范》,记录了数组的类型是什么?更进一步地说,数组对象的getClass()返回的是什么?

1.数组更详细的特点

数组具有以下几点特点:

a.在Java编程语言中,数组是动态创建的对象,可以被赋值给Object类型的变量。Object类的所有方法都可以在数组上调用。

b.数组对象包含大量的变量。

c.数组的所有元素都具有相同的类型,称为数组的元素类型。如果数组的元素类型为T,那么数组自身的类型就写作T[ ]。

这里针对数组的特点a进行详细说明:
下面代码片段中,会创建一个数组对象,并且这个对象可以赋值给Object对象。

int[] ai1 = {1,2};//隐式地创建一个新的数组对象
int[] ai = new int[2];//显式地创建一个数组对象
Object o = ai;//数组对象可以赋值给Object类型的变量
o = ai1;

通过上面的代码片段,再联系“数组是动态创建的对象”这句话,我们可以猜测:数组的类型很可能是运行时通过反射动态创建的,并且其类型是Object的子类。

既然知道数组具有特定类型了,那么这个类型具有什么成员呢?下面将进行说明。

2.数组类型的成员

数组类型的成员包括以下所有内容:

  • public final 域 length,它包含了数组的元素数量。length可以是正数或0。
  • public 方法 clone,它覆盖了Object类中的同名的方法,并且不会抛出任何受检异常。
    多维数组的克隆是浅复制,即它只创建单个新数组,子数组是共享的。
  • 所有从Object类继承而来的成员,Object中唯一没有被继承的方法就是clone方法。

因此,数组具有与下面的类相同的public域和方法:

class A<T> implements Cloneable,java.io.Serializable {
    public final int length = X;
    public T[] clone() {
        try{
            return (T[])super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
    }
}

注意:在上面例子中,如果数组真的以这种方式实现,那么其中向T[ ]的强制类型转换会产生非受检警告。

从上面可以知道,数组是可克隆的

class Test1 {
    public static void main(String[] args) {
        int ia1[] = {1,2};
        int ia2[] = ia1.clone();
        System.out.print((ia1 == ia2) + " ");
        ia1[1]++;
        System.out.println(ia2[1]);
    }
}

这个程序会产生下面的输出:
false 2
该输出展示了ia1和ia2所引用的数组元素是不同的变量。

下面的例子说明多维数组克隆后共享子数组:

class Test2 {
    public static void main(String[] args) throws Throwable {
        int ia[][] = { { 1, 2 }, null };
        int ja[][] = ia.clone();
        System.out.print((ia == ja) + " ");
        System.out.println(ia[0] == ja[0] && ia[1] == ja[1]);
    }
}

这个程序会产生下面的输出:
false true
该输出展示了 int[ ] 数组 ia[0] 和 int[ ] 数组 ja[0] 是同一个数组。

3.数组的Class对象

每个数组都与一个Class对象关联,并与其他具有相同元素类型的数组共享该对象。尽管数组类型不是类,但是每一个数组的Class对象起到的作用看起来都像是:

  • 每个数组类型的直接超类都是Object。
  • 每个数组类型都实现了Cloneable 接口和 java.io.Serializable 接口

    下面的代码用于测试上面的特点:

package com.test;

class A {

}

class B extends A implements Comparable<B>{

    @Override
    public int compareTo(B o) {
        return 0;
    }

}
public class Test2 {
    public static void main(String[] args) throws Throwable {
        B[] ba = new B[2];
        B b = new B();
        B[] ba1 = new B[2];
        //测试数组的Class对象是共享的
        System.out.println(ba == ba1);
        System.out.println(ba.getClass() == ba1.getClass());
        //测试数组ba和b的Class对象是否一样
        System.out.println(ba.getClass() + " | " + b.getClass());
        //测试数组ba和b的超类是否一样
        System.out.println(ba.getClass().getSuperclass() + " | " + b.getClass().getSuperclass());

        //测试数组ba和b实现的接口分别是什么
        for(Class<?>c : ba.getClass().getInterfaces())
            System.out.println("Superinterfaces: " + c);
        System.out.println("-----------");
        for(Class<?>c : b.getClass().getInterfaces())
            System.out.println("Superinterfaces: " + c);
    }
}

上面程序输出是:
false
true
class [Lcom.test.B; | class com.test.B
class java.lang.Object | class com.test.A
Superinterfaces: interface java.lang.Cloneable
Superinterfaces: interface java.io.Serializable
- - - - - - - - - - -
Superinterfaces: interface java.lang.Comparable

其中,字符串“[Lcom.test.B”是“元素类型为com.test.B的数组”的Class对象的运行时类型签名

根据上面的输出结果,可得出以下总结。

  • 数组的Class对象是共享的。

  • 虽然每个数组都与一个 Class 对象关联,但数组的Class对象并不等于数组元素的Class对象
    从上面这个输出可以看出:class [Lcom.test.B; | class com.test.B

  • 数组的类型是Object类的子类,并且数组的类型和数组元素的类型不一样。
    如上面的输出中, B[ ] 的超类是Object,而B的超类是A。B[ ]类型实现的是Cloneable 和 Serializable 接口,而B类实现的是Comparable 接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值