数组初始化:
Java中数组必须经过初始化才可以使用,而java的数组是静态的,所以数组初始化以后数组的长度是不可以变的。
所谓初始化,就是为数组对象的元素分配内存空间,并为每个数组元素指定初始值。
数组的初始化有2中方式:
1、静态初始化:初始化时由程序员显示指定每个数组元素的初始值,由系统决定数组长度。
2、动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值。
不管采用哪种方式初始化,一旦数组初始化完成,数组的长度是不可以变的。
示例如下:
public class ArrayDemo {
public static void main(String args[]){
//采用静态初始化方式初始化第一个数组
int[] x1 = new int[]{1,2,3,4};
System.out.println("静态初始化方式初始化第一个数组:");
printArray(x1);
//采用静态初始化方式初始化第二个数组
int[] x2 ={1,2,3,4};
System.out.println("静态初始化方式初始化第二个数组:");
printArray(x2);
//采用动态初始化方式初始化数组
int[] x3 = new int[4];
for(int i = 0; i<4; i++){
x3[i] = i;
}
System.out.println("动态初始化方式初始化数组:");
printArray(x3);
}
//打印数组
public static void printArray(int[] x){
System.out.print("[");
for(int i=0; i< x.length;i++){
if(i == x.length-1)
System.out.print(x[i]);
else
System.out.print(x[i]+",");
}
System.out.println("]");
}
}
在执行动态初始化时,只需要指定数组的长度,即为每个数组元素指定所需的内存空间,系统将负责为这些数组元素分配初始值。
指定初始值时,系统将按照如下规则分配初始值:
数组元素的类型时基本数据类型中的整数类型(byte、short、int和long),则数组元素的值是0。
数组元素的类型时基本数据类型中的浮点类型(float、double),则数组元素的值是0.0。
数组元素的类型时基本数据类型中的字符类型(char),则数组元素的值是'\u0000'。
数组元素的类型时基本数据类型中的布尔类型(boolean),则数组元素的值是false。
数组元素的类型是引用类型(类、接口和数组),则数组元素的值是null。
注意:不要同时使用静态初始化和动态初始化,即不要在进行数组初始化时,既指定数组的长度,也为每个数组元素分配初始值。
数组一定要初始化吗?
记住:
Java的数组变量是引用类型的变量,它并不是数组对象本身,只要让数组变量指向有效的数组对象,程序中就可以使用该数组变量。
示例:
class ArrayTest2{
public static void main(String args[]){
//定义并初始化数组
int[] nums = new int[]{3,5,20,12};
//定义一个prices数组变量
int[] prices;
//让prices数组指向nums所引用的数组
prices = nums;
for(int i=0; i<prices.length; i++){
System.out.println(prices[i]);
}
//将prices数组的第三个元素赋值为23
prices[2] = 23;
//访问nums数组的第三个元素,将看到输出23
System.out.println("nums数组的第三个元素的值是:"+nums[2]);
}
}
结论:这会不会和使用java数组之前一定要进行初始化矛盾呢?
个引用变量,通
常存放在栈内存中(也可以放入堆内存中),而数组对象就是保存在堆内存中的连续内存空间。对数组执行初始化,其
实并不是对数组变量执行初始化,而是要对数组对象执行初始化------也就是为该数组对象分配一块连续的内存空间,这
块连续的内存空间的长度就是数组的长度。虽然上面程序中的prices变量看似没有进过初始化,但执行prices = nums;
就会让prices变量直接指向一个已经执行初始化的数组。
对于数组变量来说,它并不需要进行所谓的初始化,只要让数组变量指向一个有效的数组对象,程序就可以正常使用该数组变量。
对于java程序中所有的引用变量,它们都不需要进过所谓的初始化操作,需要进行初始化操作的是该引用变量所引用的对象。
引用类型数组的初始化:
引用类型数组的数组元素依然是引用引用类型的,因此数组元素里存储的还是引用,它指向另一块内存里存储了该引用变量所引用的对象(包括数组和java对象)。
用下面的程序说明:
class Person{ //定义一个Person类
int age;
double height;
void info(){
System.out.println("我的年龄是:"+age+",我的身高是:"+height);
}
}
public class ArrayTest3 {
public static void main(String args[]){
Person[] students; //定义一个Person[]数组
students = new Person[2]; //动态初始化数组
Person zhang = new Person(); //创建一个Person实例。并赋值给zhang
zhang.age = 20;
zhang.height = 180.0; //为Person对象的属性赋值
students[0] = zhang; //将zhang变量的值赋值给第一个数组元素
Person Lee = new Person(); //创建一个Person实例。并赋值给Lee
Lee.age = 22;
Lee.height = 175.0; //为Person对象的属性赋值
students[1] = Lee; //将Lee变量的值赋值给第一个数组元素
Lee.info();
students[1].info(); //这2中方式的执行结果一样,因为Lee和students[1]指向的是同一个Person实例
}
}
Person[] students;
这行代码仅仅在栈内存中定义了一个引用变量,也就是一个指针,这个指针并未指向任何有效的内存区。
此时内存中的存储如图:
students = new Person[2];
这是对students数组执行动态初始化,由系统为数组元素分配默认的初始值null,内存中的存储如图:
然后程序定义了2个引用变量zhang和Lee,让它们指向堆内存中的2个Person对象。
Person zhang = new Person();
Person Lee = new Person();
然后为这两个Person对象的属性赋值。这时在内存中的存储如图:
students[0] = zhang;
students[1] = Lee;
这两句将zhang和Lee变量的值分别赋给students数组的第一个和第二个元素,这时内存的存储如图所示:
从上图可以看出:此时Lee和students[1]指向同一个内存区,而且它们都是引用类型变量,因此通过Lee和students[1]来访问Person实例的属性和方法的效果都是一样的。
不论修改studetns[1]所指向的Person实例的属性,还是修改Lee变量所指向的Person实例的属性,所修改的都是同一个内存区,所以结果必然一样。
折半查找:
public static int halfSearch(int[] arr,int key){
int min,max,mid;
min = 0;
max = arr.length-1;
mid = (max+min)/2;
while(arr[mid]!=key){
if(key>arr[mid])
min = mid + 1;
else if(key<arr[mid])
max = mid - 1;
if(min>max)
return -1;
mid = (max+min)/2;
}
return mid;
}<span style="color:#ff0000;">
</span>