一、数组是一种类型
Java数组要求所有数组元素具有相同的数据类型,因此,在一个数组中,数组元素的类型是唯一的,即一个数组里中存储一种类型的数据,而不能存储多种类型的数据。一旦数组的初始化完成,数组在内存中的空间将被固定下来。 即使某个数组被清空,他所占的空间依然被保留。
二、定义数组
Java定义数组有两种方式:
type [] arrayName;
type araryName[];
推荐使用第一种格式,因为第一种格式不仅有较好的语意,而且具有较好的可读性。
type[]是一种变量类型,arrayName是变量名。这与我们通常的用法一致。
数组是一种引用类型的变量,因此使用它定义了一个变量时,仅仅只定义了一个引用变量(也就是定义了一个指针)(开辟了一个内存空间),这个引用变量还未指向任何有效的内容(该内存空间并没有初始化内容,即没有存储数组的首元素地址),因此定义数组时不能指定数组的长度,,所以还没有内存空间存储数组元素,因此这个数组不能使用,只能对数组初始化后才能使用。
三、数组的初始化
初始化就是为数组分配内存空间,并为每个数组赋予初值。
注意:一旦为数组的每个元素分配了内存空间(指定数组的长度),每个内存空间存储的内容就是该数组的值,即使这个内存空间的内容是空,这个空也是一个值(null)。不管以哪种方式初始化数组,只要为数组元素分配空间,数组元素就有初始值,初始值的获取有两种:一种由系统指定分配;一种由程序员指定。
数组的初始化方式:
(1)静态初始化:初始化时由程序员显式指定每个数组元素的初始值,由系统决定数组的长度。
(2)动态初始化:初始化时有程序员指定数组长度,由系统为数组元素分配初始化。
3.1 静态初始化
语法格式:
1 arrayName =new type[] {element1,element12,element13...}
2 type——数组元素的数据类型,此处的type必须与前面定义数组时的type相同,也可以是定义数组时type的子类
实例:
1 class ArrayTest1
2 {
3 public static void main(String[] args)
4 {
5 //方法一:
6 System.out.println("方法一初始化:");
7 //定义一个int类型的数组变量
8 int[] array1;
9 //使用静态初始化方法,初始化数组时只指定数组元素的初始值,不指定长度
10 array1=new int[] {5,6,8,10};
11 System.out.println(array1);//指针的地址
12 for(int i=0;i<4;i++)
13 {
14 System.out.print(" "+array1[i]);
15 }
16
17 //方法二:
18 System.out.println("\n方法二初始化:");
19 //定义一个Object数组类型的数组变量,只使用于引用类型数组
20 Object[] array2;
21 //使用静态初始化方法,初始化数组时数组元素的指定的type类型是定义数组元素的类型的子类
22 array2=new String[] {"hello","world","!"};
23 for(int i=0;i<3;i++)
24 {
25 System.out.print(" "+array2[i]);
26 }
27 //方法三:
28 System.out.println("\n方法三初始化:");
29 Object[] array3;
30 //使用静态初始化,显示指定数组元素的类型是type类型的子类
31 array3=new Object[] {"good","night"};
32 for(int i=0;i<2;i++)
33 {
34 System.out.print(" "+array3[i]);
35 }
36 }
37 }
运行结果:
---------- 运行Java ----------
方法一初始化:
[I@9e89d68
5 6 8 10
方法二初始化:
hello world !
方法三初始化:
good night
输出完成 (耗时 0 秒) - 正常终止
因为java语言是面向对象的编程语言,能够很好地支持子类和父类的继承关系:子类和实例是一种特殊的父类实例。上面的实例String类型是Object实例。
除此之外还有一种简洁的语法格式:
type[] arrayName={element1,element2,element3...}
1 class 静态初始化
2 {
3 public static void main(String[] args)
4 {
5 int[] array1={1,4,7,5};
6 for (int i=0;i<4;i++)
7 {
8 System.out.print(" "+array1[i]);
9 }
10 Object[] array2={1.23,2.3,5.6};
11 for (int i=0;i<3;i++)
12 {
13 System.out.print(" "+array2[i]);
14 }
15 }
16 }
17 运行结果:
18 ---------- 运行Java ----------
19 1 4 7 5 1.23 2.3 5.6
20 输出完成 (耗时 0 秒) - 正常终止
3.2 动态初始化
动态初始化只指定数组的长度,由系统为每个数组指定初始值。动态初始化的语句的格式:
arrayName=new type[length]
与静态初始化法相同,此处的type与前面的数组定义时使用的type类型相同或者是定义数组时使用type类型的子类。
{
public static void main(String[] args)
{
//方法一:
//定义数组
int[] array1;
//初始化
array1=new int[5];
for(int i=0;i<5;i++)
{
System.out.print(" "+array1[i]);
}
//方法二
Object[] array2=new String[5];//代码定义和初始化同时进行保持代码的简洁性
for(int i=0;i<5;i++)
{
System.out.print(" "+array2[i]);
}
}
}
输出结果:
---------- 运行Java ----------
0 0 0 0 0 null null null null null
输出完成 (耗时 0 秒) - 正常终止
执行动态初始化时,程序员只需要指定数组的长度,即为每个元素指定所需的内存空间,系统会自动为这些元素分配初始值。指定初始值时,系统按如下规则分配初始值:
整型数组(byte、short、int、long)——初始值为0
字符型数组——初始值为‘\u0000’
浮点型数组(float、double)——初始化为0.0
布尔类型数组(boolean)——初始值为false
引用类型数组(类、接口、数组)——初始值为null
注:不要同时使用静态初始化和动态初始化,即不要同时指定数组的长度,同时为每个数组元素赋值
在定义数组类型局部变量时,同时使用var定义变量——只要在定义该变量时为其指定初始值即可,这样编译器就可以推断该变量的类型。
例如:
1 var array1=new String[]{"hello","world"};
2 var array2=new double[4]
注意:使用静态初始化数组·时,不能使用var定义数组变量。
四、访问数组元素
访问数组元素都是通过数组引用变量后紧跟一个方括号([]),方括号里是数组元素的索引值。Java数组索引从开始,也就是说,第一个数组的索引值为0,最后一个数组元素的索引值为数组长度减1。
如果访问的数组元素指定的索引值小于0或者大于或等于数组长度,编译程序不会报任何错误,但运行时会出现异常:java.lang.ArrayIndexOutOfBoundsException:N(数组索引越界异常),异常信息N就是程序员试图访问数组索引。
1 class ArrayTest
2 {
3 public static void main(String[] args)
4 {
5 Object[] array1;
6 array1=new String[] {"hello","world"};
7 /*
8 System.out.println(array1[2]);
9 Exception in thread "main"
10 java.lang.ArrayIndexOutOfBoundsException: Index 2 out
11 of bounds for length 2
12 */
13 System.out.println(array1[0]);
14
15 }
16 }
17
所有数组都提供了一个length属性,通过该属性可以访问数组的长度,这样就可以通过循环遍历该数组的每个元素。
1 class Arraylenth
2 {
3 public static void main(String[] args)
4 {
5 //数组定义与动态初始化同时完成
6 int[] array=new int[]{1,34,64,768,34};
7 for(int i=0;i<array.length;i++)
8 {
9 System.out.println(array[i]);
10 }
11 }
12 }
13 ---------- 运行java ----------
14 1
15 34
16 64
17 768
18 34
19
20 输出完成 (耗时 0 秒) - 正常终止
foreach循环遍历数组和集合:
foreach语法格式:
for(type variableName:array|collection)
{
//variableName自动迭代访问每个元素
}
class Arrayforeach
{
public static void main(String[] args)
{
//定义数组
Object[] array;
//初始化数组
array=new String[] {"good","morning","!"};
System.out.println("数组长度:"+array.length);
//for(String i : array)
//Arrayforeach.java:11: 错误: 不兼容的类型: Object无法转换为String
for(String i : array)
{
System.out.println(i);
}
}
}
---------- 运行java ----------
数组长度:3
good
morning
!
输出完成 (耗时 0 秒) - 正常终止
使用foreach循环遍历数组元素时无须获取数组的长度,也无须根据索引来访问数组元素。foreach循环与普通循环不同的是,它无须循环条件,无须循环语句,这些部分有系统完成。foreach循环自动迭代数组的每个元素,当每个元素迭代一次后,foreach循环会自动结束。
对于foreach循环而言,循环变量类型可以由编译器自动推断出来,而且可以使用var变量来声明循环变量。
在foreach循环对数组元素赋值时,结果不能正确地遍历数组元素。而且再一次访问数组元素时,数组元素的值依然没有变化。foreach循环变量相当于一个临时变量,系统会把数组数组元素的值一次赋给这个临时变量。
class ForeachError
{
public static void main(String[] args)
{
//动态初始化数组
var books=new String[] {"三国演义","水浒传","西游记"};
//foreach循环对数组元素赋值
for(var book:books)
{
book="红楼梦";
}
//遍历数组元素
for(var book:books)
{
System.out.println(book);
}
}
}
运行结果:
三国演义
水浒传
西游记
请按任意键继续. . .