注意, 本文讲的是数组(Array), 非数组型线性表容器(ArrayList).
一. C语言的静态数组和动态数组.
稍微接触过c的程序猿都应该知道, c语言里的数组分为静态数组和动态数组.
1.1 静态数组
所谓静态数组就是内存全部位于Stack(栈)内存里的数组.
简单地讲, 就是没有用malloc动态分配内存定义的数组.
例如下面三种定义语句都是定义了1个长度为5静态整形数组:
注意下面的是c代码而不是java代码.
#include <stdio.h>
int main(){
int a[5];
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
a[4] = 4;
int b[5] = {0,1,2,3,4};
int c[] = {0,1,2,3,4};
}
内存分配是这样的:
如上图, 数组内所有内存都是存放在Stack内存中的.
静态数组的特点是长度一旦分配就不能改变.
1.2 动态数组
所谓动态数组就是利用malloc方法动态分配内存的长度的数组.
动态数组的内存保存在Heap区中, 然后把Heap区内存的头部指针放到Stack内存中.
例如下面定义的就是1个长度为5的整形动态数组.
#include <stdio.h>
#include <stdlib.h>
int main(){
int * a = (int *)malloc(sizeof(int) * 5);
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
a[4] = 4;
}
内存分配是这样的:
真正的数组内容放在Heap内存, 然后把Heap内存的头部地址放入Stack内存.
动态数组的好处就是可以利用realloc 函数来扩展长度(重新分配内存)啦
还可以跨函数使用内存啦.
坏处就是用完注意释放啦.
二. Java里的数组都是动态数组
好了, 到了Java语言, Java是由C/C++ 发展而来的, 但是java已经是1个完全的面向对象语言.
Java里已经不存在静态数组这玩意. 所有数组都是动态数组.
也就是说:
Java里的数组内容全部都是放在Heap内存, Stack内存只会存放数组的引用(数组名).
三. Java数组的定义方法
Java里定义1个数组跟C语言有点区别.
c语言定义1个数组, 方括号只能写作数组名后面,例如:
int a[5]; //而且必须制定长度哦
java里定义1个数组, 方括号可以写作数组后面, 但是更加建议写在类型后面, 例如:
int[] a; //建议
//int a[]; //也可以
而且不能在定义1个数组名时制定长度了, 因为java不再支持Stack区静态内存
int[5] a; //错误, 编译失败
int a[5]; //同上
当执行完定义语句, 数组a是还没能被使用的, 因为java只是定义了1个数组的引用, 并没有分配内存.
内存分配如下图:
见上图,
int[] a;
这条语句只在Stack区分配了1个数组的引用内存, 这块内存的长度是4字节(32bit 系统地址长度), 但是内存是空的.
因为是动态分配, 我们还需为数组a分配内存.
a = new int[5];
上面代码的意思就是在heap区分配1个长度为5的整形内存, 然后把地址赋给a啊.
见到new, 就相当于见到c语言的malloc函数, 动态分配啊.
是不是跟C语言的动态分配内存很相似? 值得留意的是java会给分配内存格式化.. 全部赋予初始值0. 这也是跟c语言一个大区别.
接下来为数组每1个位置赋值. 跟c语言写法类似:
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
a[4] = 4;
数组内存里就有值了, 如下图:
完整的代码如下:
public class Array1{
public static void f(){
int a[];
a = new int[5];
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
a[4] = 4;
showArr(a);
}
public static void showArr(int[] a){
int i;
for (i=0; i<a.length; i++){
System.out.println(a[i]);
}
}
}
另外, 下面这两种写法也可以,
int[] b = new int[]{1,2,3};
int[] c = {1,2,3};
但是它们的效果都跟第一种写法一样, 都是动态数组.
四. Java数组是不是类?
有人可能觉得这类的定义方法很类似啊,
都要用到new , 就如new1个对象出来.
而且上面代码的showArr()方法, 还见到 a.length , 这不是类的写法, length貌似是数组a的成员啊.
实际上答案是 java中数组不是类.
java变量有两种
1就是基本类型 例如int char (等8种)
2就是引用类型
其中引用类型包括 类, 接口, 数组
它们都需要动态分配内存(new).
也就是说, 我们可以把数组看成是1个跟类与接口平行的东西, 一个特殊的引用类型.
而length也不是数组的属性, 而是1个特别的指令, 它专用于返回数组的长度.
更不是a的方法, 写成
a.length()
是错误的.
五. Java基本类型数组和引用类型数组.
java数组也可以分成两类,
5.1 基本类型数组
所谓基本类型数组就是存放 int char float等8个基本类型的数组, 上面的整形数组就是这种类型.
不再详细介绍了.
5.2 引用类型数组
所谓引用类型数组就是存放对象的数组, 数组里不是存放对象本身, 而是存放各个对象的地址.
类似与c语言的指针类型数组.
例如下面的代码:
package Array_kng;
class Student{
int id;
private String name;
public Student(int id, String name){
this.id = id;
this.name = name;
}
public String toString(){
return this.id + ": " + this.name;
}
}
public class Array2{
public static void f(){
Student[] sArr = new Student[3];
sArr[0] = new Student(1,"Jack");
sArr[1] = new Student(2,"Bill");
sArr[2] = new Student(3,"Cindy");
showArr(sArr);
}
public static void showArr(Object[] a){
int i;
for (i=0; i<a.length; i++){
System.out.println(a[i]);
}
}
}
sArr数组在内存的分配如下图:
也就是讲引用类型数组有双重的指针指向.
理解了这个, 二维数组(跟c语言类似,本文不再讲解了)也不难理解了.
六. Java数组的一些操作方法.
Java本身提供了一些静态方法方便我们对数组操作.
多数位于
java.util.Arrays类中.
最常用的莫过于静态方法sort. 和 binarySearch
还有1个数组很常用的copy的方法.
它就是
System.arraycopy().
注意arraycopy没有大写字母哦
具体使用方法请自行查阅JDK API...