数组是第一级对象

来源:互联网 发布:数据库系统工程师教程 编辑:程序博客网 时间:2024/05/16 05:07
无论使用哪种数组,数组标识符其实只是一个引用,指向在堆(heap)中创建的一个真实
对象,这个(数组)对象用以保存指向其他对象的引用。可以作为数组初始化语法的一部
分隐式地创建此对象,或者用 new 表达式显式地创建。只读成员 length 是数组对象的一
部分(事实上,这是唯一一个可以访问的属性或方法),表示此数组对象可以存储多少元
素。’[]’语法是访问数组对象唯一的方式。


下例将演示初始化数组的各种方式,以及如何对指向数组的引用赋值,使之指向另一个数
组对象。此例也证明,对象数组和基本类型数组在使用上几乎是同样的。唯一的区别就是
对象数组保存的是引用,基本类型数组直接保存基本类型的值。


//: c11:ArraySize.java
// Initialization & re-assignment of arrays.
import com.bruceeckel.simpletest.*; 


class Weeble {} // A small mythical creature


public class ArraySize { 
private static Test monitor = new Test(); 
public static void main(String[] args) { 
// Arrays of objects:
    Weeble[] a; // Local uninitialized variable
    Weeble[] b = new Weeble[5]; // Null references
    Weeble[] c = new Weeble[4]; 
for(int i = 0; i < c.length; i++) 
if(c[i] == null) // Can test for null reference
        c[i] = new Weeble(); 
// Aggregate initialization:
    Weeble[] d = {
new Weeble(), new Weeble(),new Weeble()
    };
// Dynamic aggregate initialization:
    a = new Weeble[] { 
new Weeble(), new Weeble()
    };
    System.out.println("a.length=" + a.length); 
    System.out.println("b.length = " + b.length); 
// The references inside the array are
// automatically initialized to null:
for(int i = 0; i < b.length; i++) 
      System.out.println("b[" + i + "]=" + b[i]); 
    System.out.println("c.length = " + c.length); 
    System.out.println("d.length = " + d.length); 
    a = d; 
    System.out.println("a.length = " + a.length); 


// Arrays of primitives:
int[] e; // Null reference
int[] f = new int[5]; 
int[] g = new int[4]; 
for(int i = 0; i < g.length; i++) 
      g[i] = i*i;
int[] h = { 11, 47, 93 }; 
// Compile error: variable e not initialized:
//!System.out.println("e.length=" + e.length);
    System.out.println("f.length = " + f.length); 
// The primitives inside the array are
// automatically initialized to zero:
for(int i = 0; i < f.length; i++) 
      System.out.println("f[" + i + "]=" + f[i]); 
    System.out.println("g.length = " + g.length); 
    System.out.println("h.length = " + h.length); 
    e = h; 
    System.out.println("e.length = " + e.length); 
    e = new int[] { 1, 2 }; 
    System.out.println("e.length = " + e.length); 
    monitor.expect(new String[] { 
"a.length=2",
"b.length = 5",
"b[0]=null",
"b[1]=null",
"b[2]=null",
"b[3]=null",
"b[4]=null",
"c.length = 4",
"d.length = 3",
"a.length = 3",
"f.length = 5",
"f[0]=0",
"f[1]=0",
"f[2]=0",
"f[3]=0",
"f[4]=0",
"g.length = 4",
"h.length = 3",
"e.length = 3",
"e.length = 2"
    });
  }
} ///:~


数组 a 是一个尚未初始化的局部变量,在将其恰当地初始化之前,编译器不允许你用此引
用做任何事情。数组 b 初始化为指向一个 Weeble 引用的数组,但其实并没有 Weeble 对
象置入数组中。你仍然可以询问数组的大小,因为 b 指向一个合法的对象。这样做有一个
小缺点:你无法知道在此数组中确切地有多少元素,因为 length 只表示数组能够容纳多少
元素。也就是说,length 是数组的大小,而不是实际保存的元素个数。新生成一个数组对
象时,其中所有的引用被自动初始化为 null,所以检查其中的引用是否为 null,即可知道
数组的某个位置是否存有对象。同样地,基本类型的数组如果是数值型的,就被自动初始
化为 0,字符型(char)数组被初始化为(char)0,布尔(boolean)数组被初始化为 false。


数组 c 在创建之后,随即将数组的各个位置都赋值为 Weeble 对象。数组 d 演示了使用“聚
集初始化(aggregate initialization)”语法创建数组对象(隐式地使用 new 在堆中创
建,就像数组 c 一样),并且以 Weeble 对象将其初始化的过程,这些操作只用了一条语
句。


下一个数组初始化可以看作“动态的聚集初始化”。数组 d 采用的聚集初始化动作必须在
定义 d 的位置使用,但若使用第二种语法,你可以在任意位置创建和初始化数组对象。例
如,假设方法 hide()需要一个 Weeble 对象的数组作为输入参数。可以如下调用:


hide(d);


但你也可以动态地创建数组,将其作为参数传递:


hide(new Weeble[] { new Weeble(),new Weeble() });


在许多情况下,此语法使得代码书写变得更方便了。


表达式:


a = d;
演示了如何将指向某个数组对象的引用赋值指向另一个数组对象,这与其他类型对象的引
用没什么区别。现在 a 与 d 都指向堆中的同一个数组对象。


ArraySize.java 的第二部分说明,基本类型的数组的工作方式与对象数组一样,不过基本

类型的数组直接存储基本类型数据的值。