
一、基础概念
1、数组是一种引用类型
2、数组是一种检点的数据结构,线性结构
3、数组是一个容器,可以用来存储其他元素,数组是可以存储任意数据类型的元素。
4、数组分为:一维数组,二维数组,三维数组、多维数组
5、数组中存储得元素类型是统一的,每个元素在内存中所占空间大小相同,知道数组的首元素的内存地址,要查找元素只要知道下表就可以快速的计算偏移量,通过首元素内存地址加上偏移量快速计算出要查找元素的内存地址,通过内存地址快速定位该元素,所以内存查找元素的效率较高
随机的对数组增删元素,当增加的元素的时候,为了保证数组中的元素,在空间存储上是有序的,所以被添加元素位置后面的所有元素都要向后移动。
删除元素要向前移动,所以数组增删元素效率较低
6、数组长度是不可改变得,数组一旦创建长度是不可变的,固定的。
举栗子:
class Test {
public void main(String[] args) {
// 声明一个一维数组,用来存储int类型
int[] a1 = {100,200,150,300}; // 静态初始化
// boolean数组
boolean[] b1 = {true,false,true};
//String数组
String[] strs = {"AB","CD","EF"};
// char数组
char[] c = {'a','b','c'};
//Object数组
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
Object[] objs = {o1,o2,o3};
}
}
存储结构如图:

二、初始化一维数组有两种方法:
1、静态初始化
2、动态初始化:
动态初始化一维数组,会先在堆内存中分配这个数组,并在数组中每个元素都采取默认值
byte,short,int,long 0
boolean false
引用 null
提问:什么时候使用动态初始化和动态初始化
1、无论动态初始化还静态初始化,最终的内存分布一定一样
2、如果在创建数组的时候,知道数组已应该存储什么数据,这个时候用静态初始化
如果无法预测到数组中存储什么数据,那么用动态初始化
举个栗子:
class Test {
public static void main(String[] args) {
// 静态初始化一维数组
System.out.println("静态初始化一维数组");
int[] a1 = {1,2,3};
// 取值
System.out.println(a1[0]);
System.out.println(a1[1]);
System.out.println(a1[2]);
System.out.println("长度:" + a1.length);
// 遍历
for(int i = 0;i < a1.length;i++) {
System.out.print(a1[i] + " ");
}
// 将第二个元素修改
a1[1] = 100;
System.out.println();
System.out.println("----------");
for(int i = 0;i < a1.length;i++) {
System.out.print(a1[i] + " ");
}
// 动态初始化一维数组
/*
1、动态初始化一维数组,会先在堆内存中分配这个数组,并在数组中每个元素都采取默认值
byte,short,int,long 0
float false
char \u0000
引用 null
* */
System.out.println("动态初始化一维数组");
// 动态声明一个int类型的数组,最多可以存储4个元素
int[] a = new int[4];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
for(int i = 0;i < a1.length;i++) {
System.out.print(a[i] + " ");
}
// 引用类型的数组
Object[] objs = new Object[3];
for(int index = 0;index < objs.length;index++) {
Object o = objs[index]; // o = null
// System.out.println(o.toString()); // NullPointerException
// 注意空指针异常,因为引用类型的数组类型默认为null
System.out.println(o); // null null null
}
}
}
三、深入一维数组
父类型的一维数组中放子类
举栗子:
class Test {
public static void main(String[] args) {
Animal1[] a = new Animal1[4];
Dog1 d1 = new Dog1();
Dog1 d2 = new Dog1();
Cat1 c1 = new Cat1();
Cat1 c2 = new Cat1();
a[0] = d1;
a[1] = d2;
a[2] = c1;
a[3] = c2;
// 需求:遍历数组,取出每个对象,如果是dog执行eat,是cat对象执行move
for(int i = 0;i < a.length;i++) {
Animal1 a1 = a[i];
if(a1 instanceof Cat1) {
Cat1 c = (Cat1)a1;
c.run();
}else if(a1 instanceof Dog1) {
Dog1 d = (Dog1)a1;
d.eat();
}
}
}
}
class Animal1{
}
class Dog1 extends Animal1{
public void eat() {
System.out.println("dog is eating");
}
}
class Cat1 extends Animal1{
public void run() {
System.out.println("cat is running");
}
}
输出:
dog is eating
dog is eating
cat is running
cat is running
方法调用传递数组的方式
举栗子:
class Test {
public static void main(String[] args) {
// 第一种方式
int[] a = {1,2,3};
m1(a);
System.out.println("-------------");
// 第二种方式
m1(new int[] {1,2,3});
}
public static void m1(int[] a) {
for(int i = 0; i < a.length;i++) {
System.out.println(a[i]);
}
}
}
主函数中的 String[] args的作用:
1、String[] args是专门用来接收指令参数的
2、例如:java ArrayTest07 abc def aaa
JVM在调用ArrayTest07类的main方法之前 ,先将abc def aaa以空格的方式分割后,然后放在String数组中
即,main方法的String[]数组的设计主要是用来接受命令行参数的
class Test {
public static void main(String[] args) {
System.out.println("String类型的数组中的长度"+args.length);
for(int i = 0;i < args.length;i++) {
System.out.println(args[i]);
}
}
}
输出:
String类型的数组中的长度0
关于数组的拷贝(SDK提供的方法)
class Test {
public static void main(String[] args) {
// arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
// arraycopy(源数组, 源数组的开始下标, 目标数组, 目标数组开始下标, 拷贝的长度)
int[] src = {2,3,4,5,6,7,8};
int[] dest = {10,11,12,13,14,15,6};
// 把src中的4,5,6拷贝到dest数组丛13开始
System.arraycopy(src, 2, dest, 3, 3);
// 遍历
for(int i = 0; i < dest.length;i++) {
System.out.println(dest[i]);
}
}
}
网友评论