JAVA一维数组之 数组的对象,数组声明初始化, NullPointerException 空指针异常,Arrays类方法与四种浅拷贝
0、初识一维数组
数组:存放相同数据类型的元素的集合(容器)。数组是在内存中存储相同数据类型的连续的空间。内存是连续的。
例如声明数组a,那么在数组a上, 可以访问他的属性,也可以调用他的一些方法。这基本上可以认定,java中的数组也是对象,它具有java中其他对象的一些基本特点:封装了一些数据,可以访问属性,也可以调用方法。所以,数组是对象。
声明一个数组就是在内存空间中划出一串连续的空间。此处与C语言中的区别
c语言中是指针存储数组的地址,数组首元素的地址即数组的地址,
数组名代表的是连续空间的首地址
通过首地址可以依次访问数组所有元素
元素在数组中的排序叫做下标从零开始
数组中new new出来的内容 元素,存储在Heap即堆中,数组名这个变量,在栈上申请内存。数组对象存在堆上。
数组名 :变量名,变量名(数组名)的地址存放在栈上 , 作为一门面向对象语言,从数组开始已经面向对象了
他的int num={1,2,3,4,5};中等号右边就属于对象了,
1、Java一维数组的声明方式:
1.1、静态初始化
int[] array= {0,1,2,3};
int[] array0=new int[] {1,2,3,4};//指定元素,JAVA自己会识别数组长度,静态初始化,
上述两种,虽然第一种声明方式没new,但是胜在简洁方便,此处无new胜有new;
第二种,根据数组元素,自动识别数组长度,自动声明,在堆上开辟空间存储对象元素。
他的{1,2,3,4,5}就属于对象了
注意:给数组分配空间时,必须指定数组能够存储的元素个数来确定数组大小。创建数组之后不能修改数组的大小。可以使用length 属性获取数组的大小。
1.2、动态初始化
int[] nums=new int[3];
nums[0]=0;
nums[1]=1;
nums[2]=2;
nums.length;//此处的length属于他自己本身的方法。
num.length是对象调用自己本身的方法。指定长度,动态初始化。
System.out.println(array+"是数组在JVM的栈上,以变量名array存储的数组的地址,经过哈希处理,不是真实地址");
//输出结果是:经过哈希处理的地址:
//[I@123772c4
// //JAVA非常安全,
// JAVA栈上的地址你是拿不到的
//
// 其二:你能拿到
// 堆上的地址,
// 但是堆上的地址你拿到的是哈希处理过的
2、数组的遍历
foreach是四种循环中比较常用来遍历数组的
for(int i:array0)//冒号左边是数组中的元素是什么类型~
{
System.out.println(i);
} //foreach遍历数组,其中的int i,int是说明数组中每个元素的数据类型,i不是数组元素的下标,而是数组中的每一个元素
3、数组中的常见异常:
3.1、 NullPointerException 空指针异常
原因: 引用类型变量没有指向任何对象,而访问了对象的属性或者是调用了对象的方法。
int[] a2=new int[0];
int j=a2.length;
System.out.println(j);
此处输出的结果是0.
int[] a3= null;
System.out.println(a3[0]);
java.lang.NullPointerException
//空数组长度为0,但是如果是引用为空,如果指定的数组引用为空,则该类中的方法都抛出一个NullPointerException ,除非另有说明。
3.2、 ArrayIndexOutOfBoundsException 索引值越界。
int[] a=new int[]{0,1,2,3,4};
System.out.println(a[6]);
原因:访问了不存在的索引值
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 5
4、Arrays:操作数组的工具类。
4.1Java.util.Arrays :很多实用方法
4.1.1Arrays.toString();
将数组中的数组以字符串的形式进行输出》》》。
{
int[] a0=new int[]{0,1,2,3,4,5,6};
for (int i:a0)
{
System.out.print(i+" ");
}
System.out.println();
System.out.println(Arrays.toString(a0));
}
4.1.2、foreach遍历输出出来的 和 tostring返回值的区别。
5、数组中的四种浅拷贝方式:
5、1
public static void main(String[] args)
{
{//1直接传递
int[] a=new int[]{0,1,2,3,4,5,6};
int[] a0=new int[a.length];
a0=a;
System.out.println();
System.out.println(Arrays.toString(a0));
}
{//2
int[] a1={0,1,2,3,4,5,6};
int[] ret=Arrays.copyOf(a1, a1.length);
System.out.println(Arrays.toString(ret));
}
{//3
int[] a2=new int[7];
for (int i=0;i<7;i++)
{
a2[i]=i;
}
int[] rest1=new int[a2.length];
System.arraycopy(a2, 0, rest1, 0,a2.length );
System.out.println(Arrays.toString(rest1));
}
{//4
int[] a3=new int[] {0,1,2,3,4,5,6};
int[] ret1=a3.clone();
System.out.println(Arrays.toString(ret1));
}
}
结果如下:
数组的拷贝方式有四种
1,for循环拷贝
2,Arrays.copyOf
3, System.arraycopy
其中这个方法属于native方法,底层是用C语言和C++代码编写,拷贝速度应该是以上四种最快的!
4, clone( ):产生了这个对象的一个副本,这个方法是Object的克隆方法
从本质上看,都是浅拷贝
有四种浅拷贝,就有与之对应的深拷贝,后续博文将会深刻剖析四种浅拷贝和 其对应的深拷贝