数组类型
理解数组
java中要求数组元素具有相同的数据类型,及一个数组这里只能存储一种数据类型的数据。
一旦数组的初始化完成,数组在内存中所占的空间将被固定下来,数组的长度不可改变。
定义数组
java支持两种语法格式来定义数组:
type[] arrayName; //推荐
type arrayName;
数组是一种引用类型的变量,因此用它定义一个变量仅仅表示定义了一个引用变量,这个引用变量还未指向任何有效的内存,因此定义数组时不能指定数组的长度,而且没有内存空间来存储数组元素,所以只有对数组进行初始化后才可以使用。
注意:定义数组时不能指定数组长度
数组的初始化
数组的初始化有两种方式:
- 静态初始化:初始化时由程序员显式的指定每个数组元素的初始值,由系统决定数组长度
- 动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值
注意:不能同时使用静态初始化和动态初始化。即,不能数组初始化时及指定长度,又指定初始值
1 静态初始化
arrayName = new type[]{element1, element2, element3, ...}
简化写法:
//声明和初始化一起完成
int[] a = {1,2,3,4};
实例:
int[] intArr;
intArr = new int[]{1,2,3,4}
Object[] objArr;
objArr = new Object[]{"你好", "世界"};
objArr = new String[]{"你好", "世界"};
2 动态初始化
arrayName = new type[length];
简化写法:
//数组的定义和初始化同时完成
int[] a = new int[4];
- 注意:动态初始化时,系统为元素分配的初始值为:
基本类型整数类型:0
基本类型浮点类型:0.0
基本类型字符类型:'\u0000'
基本类型布尔类型:false
引用类型(类、接口和数组):null
内存中的数组
实际的数组对象被存储在堆(heap)内存中,如果引用该数组对象的数组引用变量是一个局部变量那么它被存储在栈(stack)内存中。
- 注:为什么要分栈内存和堆内存?
当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法中定义的变量都将会被逐个放入栈内存中,方法执行结束,这个方法的内存栈自然销毁。因此,所有在方法中定义的局部变量都是放在栈内存中的。
在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本很大),这个运行时数据区就是堆内存。堆内存中对象不会随方法结束而销毁,只有当一个对象没有任何引用变量引用它时,会变成垃圾,但是长度依然不变。
实例:
int[] a = new int[]{1, 2, 3, 4}
int[] b = new int[4];
b = a;
//b = a,即把数组a的值赋给b后,就是让数组变量b指向数组变量a所指向的地址,而原来堆中数组b失去引用,变成垃圾,但长度依然不变
注:对待数组问题要分成两部分看待,一部分是数组引用,即定义的数组引用变量;一部分是实际的数组对象,在堆内存中运行的,通常无法直接访问它,只能通过数组引用变量来访问。
引用类型数组的初始化
引用类型的数组,存储的每一个数组元素也是引用,指向另一块内存。
代码示例:
//person.java
package tmp;
public class Person {
public int age;
public double height;
// 定义一个info方法
public void info() {
System.out.println("我的年龄是:" + age + ",我的身高是:" + height);
}
}
//ReferenceArraryTest.java
package tmp;
public class ReferenceArrayTest {
public static void main(String[] args) {
//定义一个students数组变量,类型是Person[],并初始化
Person[] students = new Person[2];
//创建一个person实例,并将这个person实例赋给zhang变量
Person zhang = new Person();
//为zhang所引用的person对象的age、height赋值
zhang.age=22;
zhang.height=184;
//创建一个person实例,并将这个person实例赋给wang变量
Person wang = new Person();
wang.age = 21;
wang.height=165;
//将zhang、wang变量的值分别赋给数组的元素
students[0]=zhang;
students[1]=wang;
//下面这两行代码是等效的,zhang和students[0]指向的是
//同一个Person实例
//zhang.info();
students[0].info();
}
}
输出结果:
我的年龄是:22,我的身高是:184.0
java8 中的增强工具类:Arrarys
java提供的Arrarys类里包含的一些static修饰的方法可以直接操作数组。
具体可查看api
常用的方法主要是:
- int binarySearch(type[] a, type key):使用二分法查询key元素值在a数组中出现的索引;如果a数组不包含key元素值,则返回负数。调用该方法时要求数组中元素已经按升序排列。
- int binarySearch(type[] a,int fromIndex, int toIndex, type key):跟上一个类似,但它只搜索a数组中fromIndex到toIndex索引的元素。调用该方法时要求数组中元素已经按升序排列。
- type[] copyOf(type[] original, int length):这个方法将会把original数组复制成新数组,长度为length。如果length小于original数组的长度,则新数组就是原数组的前面length个元素;length大于original数组的长度,则新数组就是原数组的所有元素,后面补充相应数据类型的默认值,如int为0,boolean为false等
- copyOfRange、equals、fill、sort、toString
- 等等……
注意:Arrarys类处于 java.util 包下,为了在程序中使用Arrary类,需要进行导包
实例:
package tmp;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrarysTest {
public static void main(String[] args) {
// 定义一个a数组
int[] a = new int[] { 3, 4, 5, 6 };
// 定义一个a2数组
int[] a2 = new int[] { 3, 4, 5, 6 };
// a和a2数组的长度、每个元素顺序值均相等,将输出true
System.out.println("a、a2数组是否相等:" + Arrays.equals(a, a2));
// 通过赋值a数组生成新数组b
int[] b = Arrays.copyOf(a, 6);
System.out.println("a、b数组是否相等:" + Arrays.equals(a, b));
System.out.println("b的数组元素为:" + Arrays.toString(b));
// 将数组b的第3个元素到第5个元素赋值为1(区间前闭后开)
Arrays.fill(b, 3, 5, 1);
System.out.println(Arrays.toString(b));
// 将b数组进行排序
Arrays.sort(b);
System.out.println(Arrays.toString(b));
}
}
运行结果:
a、a2数组是否相等:true
a、b数组是否相等:false
b的数组元素为:[3, 4, 5, 6, 0, 0]
[3, 4, 5, 1, 1, 0]
[0, 1, 1, 3, 4, 5]