收先要说明一点,java中的数组和C语言中的数组的写法是不一样的,之前一直学的C语言,在这里改改过来了!!!
java中的数组初始化分为两种:动态初始化和静态初始化
数据类型[] 数组名称 = new 数据类型 [长度] ;//长度固定
数组是一种引用数据类型,这就会涉及到它的内存分配问题,一般情况下,我们在创建数组时,就会在堆上开辟出空间存放数组,数组长度是几,就会在堆上开辟出多少个空间,我们访问数组的时候是同过索引进行访问的,假如我的数组长度是3,那么堆上就会给出0,1,2这三个索引。
需要注意的是:
我们在动态初始化数组开辟空间时,数组的每个元素会是数据类型的默认值。意思就是,如果我的数组是int型的,那么数组当中每个元素的默认值就是0;如果是String型的,那么每个元素的默认值就是null。
我们会发现数组的长度是固定的,这样就很容易出现访问越界的情况,一旦访问越界,就会出现数组访问越界的异常。
拿段代码来举个例子吧:
public class Arrays{
public static void main(String[] args){
int a[]=new int[3];//开辟了一个长度为3的数组
//我们不妨打印一下,看看结果中每个元素默认值是什么?
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
System.out.println();
a[0]=1;
a[1]=2;
a[2]=3;
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
}
}
结果如下:
我们可以看到我们在做动态初始化的时候没有赋值之前三个元素的默认值都是0(因为数组类型是int,默认值是0),我们赋了初值之后就有了。
数组分布实例化
int[] x = null ;
x = new int[3] ;
数组属于引用数据类型,因此在使用之前一定要开辟空间(实例化),否则就会产生NullPoninterException (空指针异常)
刚开始我也不知道这个引用传递是什么意思?后来经过了解,我来解释一下引用传递:
引用传递其实说的是内存分配的问题,前面提到数组是引用数据类型,那么它在堆上会开辟空间的,但是数组这个变量是在栈上的,也就是说这个在栈上的变量指向了在堆上给它分配的空间,而引用传递指的是同一块堆内存空间可以被不同的占空间所指向,说了一大顿,你可能还是不理解,没关系,用一个图来看再清楚不过了:
比如下面一段代码:
public class Arrays{
public static void main(String[] args){
int a[]=null;//开辟了一个长度为3的数组
int x[]=null;
a=new int[3];
a[0]=1;
a[1]=2;
a[2]=3;
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
System.out.println();
x=a;
x[0]=55;
//我们不妨打印一下,看看结果中每个元素默认值是什么?
System.out.print(a[0]); //55
//结果表明a[0]被改变了
}
}
在动态初始化数组时,我们是先开辟的内存空间,之后才设置的内容,而如果我们要向在开辟空间的同时设置内容的话,就要用到静态初始化了。
静态初始化有以下两种形式:
<1> 数据类型[] 数组名称 = {值,值,....}
<2> 数据类型[] 数组名称 = new 数据类型[] {值,值,....}
例如下面这段代码:
public class Arrays{
public static void main(String[] args) {
int[] x = {1,2,3,4,5} ; // 格式一
for (int i = 0; i<x.length ; i++) {
System.out.print(x[i]) ;
}
System.out.println();
int[] a=new int[]{1,2,3,4,5};//格式二
for (int i = 0; i<a.length ; i++) {
System.out.print(a[i]) ;
}
}
}
这两种静态化初始结果一样:
建议使用完整格式(格式二),这样可以轻松的使用匿名数组这一概念,下面简单看一下匿名数组的形式。
直接看代码就明白了:
public class ArrayDemo{
public static void main(String[] args) {
System.out.println(new int[]{1,2,3,4,5}.length) ; //匿名数组
}
}
二维数组开发过程中用的并不多,简单了解即可
二维数组动态初始化和一维数组一样都是先开辟内存空间,后赋值
数据类型[][] 对象数组 = new 数据类型[行个数][列个数] ;
代码示例:
public static void code5(){
int[][] intArray=new int[2][4];
intArray[0][0]=1;
intArray[0][1]=2;
intArray[0][2]=3;
intArray[0][3]=4;
for(int i=0;i<intArray.length;i++){
for(int j=0;j<intArray[i].length;j++){
System.out.printl(intArray[i][j]+" ");
}
System.out.println();
}
}
在开辟空间的同时赋值
数据类型[][] 对象数组 = new 数据类型[][]{{值,值,…},{值,值,…},…} ;
代码示例:
public class Arrays{
public static void main(String[] args) {
// 数组并不是等列数组
int[][] data = new int[][] {
{1,2,3},{4,5},{6,7,8,9}
};
// 在进行输出的时候一定要使用双重循环
for (int x = 0; x<data.length ; x++) {
for (int y = 0; y<data[x].length ; y ++) {
System.out.println("data["+x+"]["+y+"]="+data[x][y]+" ") ;
}
System.out.println();
}
}
}
之前所定义的数组都属于基本类型的数组,对象数组往往是以引用数据类型为主的定义,例如:
类、接口
。
其实学到这里,我们应该都知道了动态初始化和静态初始化的区别了,就是在内存开辟和赋值先后顺序上的区别,我们看看对象数组动态初始化的语法:
类名称[] 对象数组名称 = new 类名称[长度] ;
之前我们并没有接触过对象数组,这里我们举个例子来说明一下:
看一段代码:
class Person{//先定义一个Person类
private String name ;
private int age ;
public Person(String name, int age) {
this.name = name ;
this.age = age ;
}
public void getInfo() {
System.out.println("姓名:"+this.name+",年龄:"+this.age) ;
}
}
public class Test {
public static void main(String[] args){
Person[] per = new Person[3] ; // 数组动态初始化,每个元素都是其对应数据类型的默认值
per[0] = new Person("张三",1) ;
per[1] = new Person("李四",2) ;
per[2] = new Person("王五",3) ;
for (int x = 0 ; x < per.length ; x++) {
per[x].getInfo() ;
}
}
}
这样我们就知道 了,静态初始化其实只需将Test里面的部分稍作改动,如下:
public class Test {
public static void main(String[] args){
Person[] per = new Person[] {
new Person("张三",1) ,
new Person("李四",2) ,
new Person("王五",3)
} ; // 对象数组静态初始化
for (int x = 0 ; x < per.length ; x++) {
per[x].getInfo() ;
}
}
}
结果和上面一样。
在java中数组的使用和c语言中大多一样,比如说方法接收数组、方法返回数组、方法修改数组等等,但是要注意的是在方法返回数组的时候,我们要考虑两种情况:返回的数组是新数组还是修改原来数组的值,如果返回新数组,那么一开始一定要先new一个新数组,如果是修改原来数组的值,直接修改即可,无需返回值。