Java语言的数组变量是引用变量,是静态的,既当Java数组必须经过初始化才可以使用,初始化之后,该数组所占用的内存空间以及数组长度都是不可变的。
数组的初始化有两种方法:
1:静态初始化:初始化时显示指定每个数组元素,系统确定数组长度。
2:动态初始化:初始化时指定数组长度,数组元素由Java提供默认值。
无论采用哪一种初始化方式,长度确定后一定不可再次改变!
当采用动态初始化方式时,Java分配的默认值如下:
a、当数据类型为int,short,long,byte等整数类型时,默认值为0;
b、当数据类型为double、float这些浮点数时,默认值为0.0;
c、当数据类型boolean时,默认值为false;
d、当数据类型为char时,默认值为'\u0000'(代表了一个空格);
e、当数据类型为类、接口时,默认值为null;
这里要说明的是数组变量并不是数组本身,它只是堆内存中的的数组对象,因此说可以改变一个数组变量所引用的数组,这样就造成了数组长度变化的假象。
public class array {
public static void main(String[] args) {
// TODO Auto-generated method stub
String [] name = new String[]{
"赵","钱","孙","李","周","吴",
};
String [] book = new String[]{
"三字经","百家姓","弟子规"
};
int [] num = new int [3];
char [] character = new char[3];
boolean[] bool = new boolean[3];
double [] df = new double[3];
String [] none = new String[2];
//验证Java默认初始化值
System.out.println(num[0]);
System.out.println(character[0]);
System.out.println(bool[0]);
System.out.println(df[0]);
System.out.println(none[0]);
//长度变化假象
System.out.println("数组name长度" + name.length);
System.out.println("数组book长度" + name.length);
name = book;
System.out.println("数组name长度" + name.length);
}
}
运行结果是:
0
false
0.0
nul
数组name长度是6
数组book长度是3
数组name长度是3
看起来似乎是数组长度变了,实际上是name数组变量指向的对内存区域变化了,导致了数组长度变化,致使这种错觉的内存分配情况图如下:
初始化时的情况:
当执行该行代码后,内存情况如下:
name = book;
数组变量只是一个引用变量,而数组对象就是存储在堆内存上的连续内存空间。(PS: 所有的局部变量都是存放在占内存中保存的,不管其实基本类型的变量还是引用类型的变量;但是说引用变量所引用的对象则总是存储在堆内存上。)
引用变量本质上是一个指针,只是在程序需要通过引用访问属性、调用方法是才会由引用的对象替代。因此说Java内有多维数组,java中的多维数组都可以当成一位数组进行处理。
在数据结构中可以封装数组成为一种适用于快速查找的线性表结构,这里我写了一个自定义的有数组做底层的线性表
import java.util.Arrays;
public class SequenceList<T> {
// 默认数组长度
private int DEFAULT_SIZE = 16;
// 保存数组长度
private int capacity;
// 用于保存线性表的数组
private Object[] elementData;
// 当前存储数据个数
private int size = 0;
// 以默认长度创建存储数组
public SequenceList() {
elementData = new Object[DEFAULT_SIZE];
capacity = DEFAULT_SIZE;
}
// 存储数组长度不足时,数组拓展
private void ensure(int oldsize) {
if (oldsize > capacity) {
while (capacity < oldsize) {
capacity <<= 1;
}
elementData = Arrays.copyOf(elementData, capacity);
}
}
// 以某元素初始化存储数组
public SequenceList(T elemenT) {
this();
elementData[0] = elemenT;
size++;
}
// 以某元素及指定长度初始化存储数组
public SequenceList(T element, int initsize) {
capacity = initsize;
elementData = new Object[initsize];
elementData[0] = element;
size++;
}
// 获取线性表长度
public int length() {
return size;
}
// 获取线性表是否为空
public boolean empty() {
return size == 0;
}
// 获取指定索引的元素
public T get(int i) {
if (i > size - 1 || i < 0) {
throw new RuntimeException("索引越界");
}
return (T)elementData[i];
}
// 查找线性表中的元素位置
public int contains(T key) {
for (int i = 0; i < size; i++) {
if (elementData[i].equals(key)) {
return i;
}
}
return -1;
}
// 向线性表中添加元素
public void add(T element) {
Insert(element, size);
}
// 想存储数组中指定位置插入元素
public void Insert(T element, int index) {
if (index > size || index < 0) {
throw new IndexOutOfBoundsException("不存在该位置");
}
ensure( size + 1);
System.arraycopy(element, index, element, index + 1, size - index);
elementData[index] = element;
size++;
}
// 删除最后一个元素
public T remove() {
return delete(size - 1);
}
// 删除指定位置元素
public T delete(int index) {
if (index < 0 || index > size - 1) {
throw new IndexOutOfBoundsException("线性表越界");
}
T oldValue = (T)elementData[index];
elementData[index] = null;
int key = size - index - 1;
if (key > 0) {
System.arraycopy(elementData, index + 1, elementData, index, key);
}
return oldValue;
}
// 线性表清空
public void clear() {
Arrays.fill(elementData, null);
}
// 输出
public String toString() {
if (size == 0) {
return null;
} else {
StringBuilder str = new StringBuilder();
str.append("[");
for (int i = 0; i < size; i++) {
str.append(elementData[i] + ",");
}
str.append("]");
return str.toString();
}
}
}