3.4 Java数组类型

一、数组是一种类型

   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("
方法二初始化:");
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("
方法三初始化:");
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);
        }
    }
}
运行结果:
三国演义
水浒传
西游记
请按任意键继续. . .
原文地址:https://www.cnblogs.com/weststar/p/12305517.html