在Java语言中,数组是对象(An object is a class instance or an array.),而且是动态创建的。
数组超类是Objcet,可以在数组上调用Object类的所有方法。
每个数组都有一个关联的Class对象,与具有相同组成类型的所有其他数组共享(§10.8)。
虽然数组类型不是一个class,但每个数组的Class对象的行为如下:
以下规则定义了数组类型之间的直接超类型关系(§4.10.3):
数组类型的超类型关系与超类关系不同:
推一篇相关分析的文章:Java中的数组是对象吗?
在Java语言中,一个char数组并不是一个String,并且String和char数组都不会被'\ u0000'(NUL字符)终止。
String对象是不可变的,它的内容永远不变,而char数组有可变元素。
String类中的toCharArray方法返回一个包含与String相同字符序列的字符数组。StringBuffer类在可变字符数组上实现有用的方法。
以下是数组类型的所有成员:
问:为什么数组有length属性,而字符串没有?或者,为什么字符串有length()方法,而数组没有?
答:
一旦数组被创建,他的长度就是固定的了。数组的长度可以作为final实例变量的长度。因此,长度可以被视为一个数组的属性。
String背后的数据结构是一个char数组,所以没有必要来定义一个不必要的属性(因为该属性在char数值中已经提供了)。
数组与其他种类的容器之间的区别有三方面:效率、类型和保存基本类型的能力。
在Java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。
数组之所以优于泛型之前的同期,就是因为可以创建一个数组去持有某种具体类型。
随着自动包装机制的出现,容器已经可以与数组几乎一样方便的用于基本类型中了。
数组硕果仅存的优点就是效率。然而,如果要解决更一般化的问题,数组可能会受到过多的限制,因此在这些情形下还是会使用容器。
无论什么类型的数组,数组标识符只是一个引用,指向在堆中创建的一个真实对象,这个(数组)对象用以保存指向其他对象的引用。
可以作为数组初始化语法的一部分隐式地创建此对象,或者用new表达式显式地创建。
只读成员length是数组对象的一部分(事实上,这是唯一一个可以访问的字段),表示此数组可以存储多少元素。
“[]”语法是访问数组对象的唯一的方式。
对象数组和基本类型数组在使用上几乎是相同的,唯一的区别就是对象数组保存的是引用,基本类型数组直接保存基本类型的值。
多维数组中构成矩阵的每个向量都可以具有任意的长度(这被称为粗糙数组)。
通常,数组与泛型不能很好的结合。不能实例化具有参数化类型的数组。
/**
* 擦除会移除参数类型信息,而数组必须知道它们所持有的确切类型,以强制保证类型安全。
* 但可以参数化数组本身。
*/
public class ParameterizedArrayType {
public static void main(String[] args) {
Integer[] ints = { 1, 2, 3, 4, 5 };
Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 };
Integer[] ints2 = new ClassParameter<Integer>().f(ints);
Double[] doubles2 = new ClassParameter<Double>().f(doubles);
ints2 = MethodParameter.f(ints);
doubles2 = MethodParameter.f(doubles);
}
}
class ClassParameter<T> {
public T[] f(T[] arg){
return arg;
}
}
class MethodParameter {
public static <T> T[] f(T[] arg){
return arg;
}
}
使用参数化方法而不使用参数化类的方便之处在于:
java.util类库中的Arrays类,有一套用于数组的static实用方法。其中有六个基本方法:
这些方法对各种基本类型和Object类做了重载。此外,Arrays.asList()接收任意的序列或数组作为其参数,并将其转变为List容器。
标准类库提供的System.arraycopy(),用它复制数组比用for循环快很多。其针对所有类做了重载。
需要的参数有:源数组,表示从源数组中的什么位置开始复制的偏移量,表示从目标数组的什么位置开始复制的偏移量,需要复制的元素个数。
对数组的任意越界操作都会导致异常。
基本类型和对象数组都可以复制。
如果复制对象数组,只是复制了对象的引用,而不是对象本身的拷贝,即浅复制(shallow copy,亦称为浅拷贝)。
不会自动包装盒自动拆包,两个数组必须具有相同的确切类型。
equals(),数组相等的条件:
可以通过对每个元素使用equals()作比较来判断,对于基本类型,需要使用基本类型的包装器类的equals()。如,对于int类型需要使用Integer,equals()作比较;
java有两种方式提供比较功能。
一种是实现java.lang.Comparable接口,使类具有“天生”的比较能力。
若没有实现Comparable接口或者不喜欢原有的,可以创建一个实现了Comparator接口的单独的类。这是策略模式的一个应用实例。
一般不需要实现里面的equals()方法,除非有特殊功能需求。
Collections类包含一个reverseOrder()方法,可以产生一个Comparator,可以反转自然的排序顺序,这很容易应用于CompType.
1.《Java编程思想》(第4版)